Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/sourcetools/objectmodel/com/ibm/j9tools/om/FlagVerifier.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2007, 2011 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
package com.ibm.j9tools.om;
23
24
import java.text.MessageFormat;
25
import java.util.Collection;
26
import java.util.HashSet;
27
import java.util.Map;
28
29
/**
30
* Verifier class to check the validity of the flags in a given {@link IFlagContainer}. Validity
31
* is determined by the consistency of the requires and precludes list. Consistency is determined as follows:
32
*
33
* <ol>
34
* <li>A flag must not requires itself</li>
35
* <li>A flag must not preclude itself</li>
36
* <li>There must be no cycle in the requires list</li>
37
* <li>There must be no cycle in the precludes list</li>
38
* <li>There must be no conflict between a flag's recursive requires and precludes list</li>
39
* </ol>
40
*
41
* @author Gabriel Castro
42
* @author Han Xu
43
*/
44
public class FlagVerifier {
45
private final Collection<OMException> errors = new HashSet<OMException>();
46
private final FlagDefinitions flagDefinitions;
47
private final Map<String, Flag> containerFlags;
48
49
/**
50
* Creates a new {@link FlagVerifier} for the given {@link IFlagContainer} and the given flag definitions.
51
*
52
* @param container the flag container to be verified
53
* @param flagDefinitions the flag definitions from the container's build-info
54
*/
55
public FlagVerifier(IFlagContainer container, FlagDefinitions flagDefinitions) {
56
this.flagDefinitions = flagDefinitions;
57
this.containerFlags = container.getFlags();
58
}
59
60
/**
61
* Walks the flags provided by the Feature or BuildSpec.
62
*
63
* This will not do a complete validation because since it validates all flags, a complete validation of each single flag will be redundant.
64
* That is to say, checking that flag A precludes B, and checking that B is precluded by A, are the same.
65
*/
66
public Collection<OMException> verify() {
67
for (Flag flag : containerFlags.values()) {
68
verifyExistence(flag);
69
70
// Only check requires and precludes if the flag is enabled, otherwise it's like the flags aren't there
71
if (flag.getState()) {
72
verifyRequires(flag, false);
73
verifyPrecludes(flag, false);
74
}
75
}
76
77
return errors;
78
}
79
80
/**
81
* Validate a flag
82
*
83
* @param flag Flag to verify
84
* @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>
85
*/
86
public void verify(Flag flag, boolean parentToggled) {
87
verifyExistence(flag);
88
89
if (flag.getState()) {
90
verifyRequires(flag, parentToggled);
91
verifyPrecludes(flag, parentToggled);
92
}
93
}
94
95
/**
96
* Validate a flag, assuming that the parent was not toggled. This is equivalent to:
97
* <code>validateFlag(flag, false);</code>
98
*
99
* @param flag Flag to verify
100
*/
101
public void verify(Flag flag) {
102
verify(flag, false);
103
}
104
105
/**
106
* Helper method used to verify existence of a given flag.
107
*
108
* @param flag Flag to verify
109
*/
110
private void verifyExistence(Flag flag) {
111
if (flagDefinitions.getFlagDefinition(flag.getId()) == null) {
112
errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.invalidFlag"), new Object[] { flag.getId() }), flag)); //$NON-NLS-1$
113
}
114
}
115
116
/**
117
* Check that the requirements are turned on
118
*
119
* @param flag Flag to verify
120
* @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>
121
*/
122
private void verifyRequires(Flag flag, boolean parentToggled) {
123
// Don't validate if the flag is disabled. A disabled flag acts as a non-existent flag.
124
if (!flag.getState() || flagDefinitions.getFlagDefinition(flag.getId()) == null) {
125
return;
126
}
127
128
// Check the local requires
129
for (FlagDefinition require : flagDefinitions.getFlagDefinition(flag.getId()).getLocalRequires().values()) {
130
Flag requiredFlag = containerFlags.get(require.getId());
131
132
// When a parent category is checked we don't need to check the children as they will all be enabled in the end
133
if ((!parentToggled || !require.getCategory().equals(flag.getCategory())) && (requiredFlag == null || !requiredFlag.getState())) {
134
errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.requiredFlag"), new Object[] { flag.getId(), require.getId() }), flag)); //$NON-NLS-1$
135
}
136
}
137
138
}
139
140
/**
141
* Verify that the flags which this <code>flag</code> precludes are turned off
142
*
143
* @param flag Flag to verify
144
* @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>
145
*/
146
private void verifyPrecludes(Flag flag, boolean parentToggled) {
147
// Don't validate if the flag is disabled. A disabled flag acts as a non-existent flag.
148
if (!flag.getState() || flagDefinitions.getFlagDefinition(flag.getId()) == null) {
149
return;
150
}
151
152
// Check the local requires
153
for (FlagDefinition preclude : flagDefinitions.getFlagDefinition(flag.getId()).getLocalPrecludes().values()) {
154
Flag precludedFlag = containerFlags.get(preclude.getId());
155
156
if ((parentToggled && precludedFlag != null && precludedFlag.getCategory().equals(flag.getCategory())) || (precludedFlag != null && precludedFlag.getState())) {
157
errors.add(new InvalidFlagException(MessageFormat.format(Messages.getString("FlagVerifier.precludedFlag"), new Object[] { flag.getId(), precludedFlag.getId() }), flag)); //$NON-NLS-1$
158
}
159
}
160
}
161
}
162
163