Path: blob/master/sourcetools/objectmodel/com/ibm/j9tools/om/FlagVerifier.java
6004 views
/*******************************************************************************1* Copyright (c) 2007, 2011 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21package com.ibm.j9tools.om;2223import java.text.MessageFormat;24import java.util.Collection;25import java.util.HashSet;26import java.util.Map;2728/**29* Verifier class to check the validity of the flags in a given {@link IFlagContainer}. Validity30* is determined by the consistency of the requires and precludes list. Consistency is determined as follows:31*32* <ol>33* <li>A flag must not requires itself</li>34* <li>A flag must not preclude itself</li>35* <li>There must be no cycle in the requires list</li>36* <li>There must be no cycle in the precludes list</li>37* <li>There must be no conflict between a flag's recursive requires and precludes list</li>38* </ol>39*40* @author Gabriel Castro41* @author Han Xu42*/43public class FlagVerifier {44private final Collection<OMException> errors = new HashSet<OMException>();45private final FlagDefinitions flagDefinitions;46private final Map<String, Flag> containerFlags;4748/**49* Creates a new {@link FlagVerifier} for the given {@link IFlagContainer} and the given flag definitions.50*51* @param container the flag container to be verified52* @param flagDefinitions the flag definitions from the container's build-info53*/54public FlagVerifier(IFlagContainer container, FlagDefinitions flagDefinitions) {55this.flagDefinitions = flagDefinitions;56this.containerFlags = container.getFlags();57}5859/**60* Walks the flags provided by the Feature or BuildSpec.61*62* This will not do a complete validation because since it validates all flags, a complete validation of each single flag will be redundant.63* That is to say, checking that flag A precludes B, and checking that B is precluded by A, are the same.64*/65public Collection<OMException> verify() {66for (Flag flag : containerFlags.values()) {67verifyExistence(flag);6869// Only check requires and precludes if the flag is enabled, otherwise it's like the flags aren't there70if (flag.getState()) {71verifyRequires(flag, false);72verifyPrecludes(flag, false);73}74}7576return errors;77}7879/**80* Validate a flag81*82* @param flag Flag to verify83* @param parentToggled The parent (AKA category) of the flag was toggled (from a tree), thus assume that all children of this parent are of the same state as <code>flag</code>84*/85public void verify(Flag flag, boolean parentToggled) {86verifyExistence(flag);8788if (flag.getState()) {89verifyRequires(flag, parentToggled);90verifyPrecludes(flag, parentToggled);91}92}9394/**95* Validate a flag, assuming that the parent was not toggled. This is equivalent to:96* <code>validateFlag(flag, false);</code>97*98* @param flag Flag to verify99*/100public void verify(Flag flag) {101verify(flag, false);102}103104/**105* Helper method used to verify existence of a given flag.106*107* @param flag Flag to verify108*/109private void verifyExistence(Flag flag) {110if (flagDefinitions.getFlagDefinition(flag.getId()) == null) {111errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.invalidFlag"), new Object[] { flag.getId() }), flag)); //$NON-NLS-1$112}113}114115/**116* Check that the requirements are turned on117*118* @param flag Flag to verify119* @param parentToggled The parent (AKA category) of the flag was toggled (from a tree), thus assume that all children of this parent are of the same state as <code>flag</code>120*/121private void verifyRequires(Flag flag, boolean parentToggled) {122// Don't validate if the flag is disabled. A disabled flag acts as a non-existent flag.123if (!flag.getState() || flagDefinitions.getFlagDefinition(flag.getId()) == null) {124return;125}126127// Check the local requires128for (FlagDefinition require : flagDefinitions.getFlagDefinition(flag.getId()).getLocalRequires().values()) {129Flag requiredFlag = containerFlags.get(require.getId());130131// When a parent category is checked we don't need to check the children as they will all be enabled in the end132if ((!parentToggled || !require.getCategory().equals(flag.getCategory())) && (requiredFlag == null || !requiredFlag.getState())) {133errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.requiredFlag"), new Object[] { flag.getId(), require.getId() }), flag)); //$NON-NLS-1$134}135}136137}138139/**140* Verify that the flags which this <code>flag</code> precludes are turned off141*142* @param flag Flag to verify143* @param parentToggled The parent (AKA category) of the flag was toggled (from a tree), thus assume that all children of this parent are of the same state as <code>flag</code>144*/145private void verifyPrecludes(Flag flag, boolean parentToggled) {146// Don't validate if the flag is disabled. A disabled flag acts as a non-existent flag.147if (!flag.getState() || flagDefinitions.getFlagDefinition(flag.getId()) == null) {148return;149}150151// Check the local requires152for (FlagDefinition preclude : flagDefinitions.getFlagDefinition(flag.getId()).getLocalPrecludes().values()) {153Flag precludedFlag = containerFlags.get(preclude.getId());154155if ((parentToggled && precludedFlag != null && precludedFlag.getCategory().equals(flag.getCategory())) || (precludedFlag != null && precludedFlag.getState())) {156errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.precludedFlag"), new Object[] { flag.getId(), precludedFlag.getId() }), flag)); //$NON-NLS-1$157}158}159}160}161162163