001: /*
002: * Licensed under the Apache License, Version 2.0 (the "License");
003: * you may not use this file except in compliance with the License.
004: * You may obtain a copy of the License at
005: *
006: * http://www.apache.org/licenses/LICENSE-2.0
007: *
008: * Unless required by applicable law or agreed to in writing, software
009: * distributed under the License is distributed on an "AS IS" BASIS,
010: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: * See the License for the specific language governing permissions and
012: * limitations under the License.
013: */
014: package org.tp23.antinstaller.runtime.logic;
015:
016: import java.util.Arrays;
017: import java.util.Comparator;
018: import java.util.HashMap;
019: import java.util.Map;
020:
021: import org.tp23.antinstaller.input.ResultContainer;
022: import org.tp23.antinstaller.runtime.ConfigurationException;
023:
024: /**
025: * @author mwilson
026: * @version $Id: ExpressionBuilder.java,v 1.2 2006/12/21 00:03:18 teknopaul Exp $
027: * @since 0.7.4 patch 2
028: */
029: public class ExpressionBuilder {
030: private static final int GROUPING_START_OPERATOR = '(';
031:
032: private static final int GROUPING_END_OPERATOR = ')';
033:
034: private static final ValuesTest[] testValueConditions = {
035: new EndsWithTest(), new EqualsTest(),
036: new GreaterThanOrEqualsTest(), new LessThanOrEqualsTest(),
037: new NotEqualsTest(), new StartsWithTest() };
038:
039: private static final LogicalTest[] testLogicalConditions = {
040: new LogicalAndTest(), new LogicalOrTest() };
041:
042: private static final SingleExpressionTest SINGLE_EXPRESSION_TEST = new SingleExpressionTest();
043:
044: private static Map tokenMap = new HashMap();
045:
046: private static String[] valueTokens;
047:
048: private static String[] logicalTokens;
049:
050: static {
051: for (int i = 0; i < testValueConditions.length; i++) {
052: String[] tmpTokens = testValueConditions[i].getTestTokens();
053: for (int j = 0; j < tmpTokens.length; j++) {
054: tokenMap.put(tmpTokens[j], testValueConditions[i]);
055: }
056: }
057:
058: valueTokens = new String[tokenMap.size()];
059: int index = 0;
060: for (int i = 0; i < testValueConditions.length; i++) {
061: String[] tmpTokens = testValueConditions[i].getTestTokens();
062: for (int j = 0; j < tmpTokens.length; j++) {
063: valueTokens[index++] = tmpTokens[j];
064: }
065: }
066:
067: Comparator lengthComparator = new StringLengthComparator();
068:
069: //Have to sort so that longest test operator is checked for first
070: Arrays.sort(valueTokens, lengthComparator);
071:
072: index = 0;
073: final int mapInitialSize = tokenMap.size();
074:
075: for (int i = 0; i < testLogicalConditions.length; i++) {
076: String[] tmpTokens = testLogicalConditions[i]
077: .getTestTokens();
078: for (int j = 0; j < tmpTokens.length; j++) {
079: tokenMap.put(tmpTokens[j], testLogicalConditions[i]);
080: }
081: }
082:
083: logicalTokens = new String[tokenMap.size() - mapInitialSize];
084: for (int i = 0; i < testLogicalConditions.length; i++) {
085: String[] tmpTokens = testLogicalConditions[i]
086: .getTestTokens();
087: for (int j = 0; j < tmpTokens.length; j++) {
088: logicalTokens[index++] = tmpTokens[j];
089: }
090: }
091:
092: Arrays.sort(logicalTokens, lengthComparator);
093:
094: }
095:
096: public static Expression parseLogicalExpressions(
097: ResultContainer container, String exprStr)
098: throws ConfigurationException {
099:
100: int startIndex = skipWhiteSpace(exprStr, 0);
101: int index = exprStr
102: .indexOf(GROUPING_START_OPERATOR, startIndex);
103:
104: if (index == -1) {
105: return getSimpleExpression(container, exprStr
106: .substring(startIndex));
107: }
108:
109: if (index != 0) {
110: throw new ConfigurationException(
111: "Illegal ifProperty value: If present, grouping operator "
112: + GROUPING_START_OPERATOR
113: + " must be at start of property string");
114: }
115:
116: ++startIndex; //Skip over grouping operator
117:
118: int endIndex = getMatchingParenthesisIndex(exprStr, startIndex);
119:
120: if (endIndex == -1) {
121: throw new ConfigurationException(
122: "Missing grouping end bracket "
123: + GROUPING_END_OPERATOR + " in expression "
124: + exprStr);
125: }
126:
127: try {
128: Expression expr1 = parseLogicalExpressions(container,
129: exprStr.substring(startIndex, endIndex));
130:
131: LogicalTest test = null;
132:
133: startIndex = endIndex + 1;
134:
135: //Look for logical operator token
136: String logicalToken = getLogicalToken(exprStr, startIndex);
137:
138: for (int i = 0; i < logicalTokens.length; i++) {
139:
140: if (logicalTokens[i].compareTo(logicalToken) == 0) {
141: test = (LogicalTest) tokenMap.get(logicalTokens[i]);
142: index = exprStr.indexOf(logicalTokens[i],
143: startIndex);
144: startIndex = index + logicalTokens[i].length();
145: break;
146: }
147: }
148:
149: if (test == null) {
150: return new CompoundExpression(expr1,
151: SINGLE_EXPRESSION_TEST, null);
152: } else {
153: startIndex = skipWhiteSpace(exprStr, startIndex);
154: String expr2Str = exprStr.substring(startIndex, exprStr
155: .length());
156: return new CompoundExpression(expr1, test,
157: parseLogicalExpressions(container, expr2Str));
158:
159: }
160: } catch (Exception e) {
161: throw new ConfigurationException(
162: "Invalid ifProperty expression: " + exprStr, e);
163: }
164: }
165:
166: private static Expression getSimpleExpression(
167: ResultContainer resultContainer, String exprStr)
168: throws ConfigurationException {
169: try {
170: int index = -1;
171: int i;
172:
173: for (i = 0; i < valueTokens.length; i++) {
174: index = exprStr.indexOf(valueTokens[i]);
175:
176: if (index != -1) {
177: break;
178: }
179: }
180:
181: return new SimpleExpression(resultContainer, exprStr
182: .substring(0, index), (ValuesTest) tokenMap
183: .get(valueTokens[i]), exprStr.substring(index
184: + valueTokens[i].length()));
185: } catch (Exception e) { // can be StringIndexOutOfBoundsException - PH
186: throw new ConfigurationException(
187: "Invalid ifProperty expression: " + exprStr, e);
188: }
189: }
190:
191: private static int skipWhiteSpace(final String str,
192: final int startIndex) {
193: final int strLen = str.length();
194: int index = startIndex;
195:
196: while (index < strLen) {
197: if ((str.charAt(index) != ' ')
198: && (str.charAt(index) != '\t')) {
199: break;
200: }
201:
202: ++index;
203: }
204:
205: return index;
206: }
207:
208: private static String getLogicalToken(final String str,
209: final int startIndex) {
210: final int strLen = str.length();
211: int tokenStart = skipWhiteSpace(str, startIndex);
212: int endIndex = tokenStart;
213:
214: while (endIndex < strLen) {
215: int chr = str.charAt(endIndex);
216: if ((chr == ' ') || (chr == '\t')
217: || (chr == GROUPING_START_OPERATOR)) {
218: break;
219: }
220:
221: ++endIndex;
222: }
223:
224: return str.substring(tokenStart, endIndex);
225: }
226:
227: /*
228: * Return the index for the matching close parenthesis
229: */
230: private static int getMatchingParenthesisIndex(String str,
231: int startIndex) throws ConfigurationException {
232: int index = startIndex;
233: int level = 1;
234:
235: while ((index < str.length()) && (level > 0)) {
236: if (str.charAt(index) == GROUPING_START_OPERATOR) {
237: ++level;
238: } else if (str.charAt(index) == GROUPING_END_OPERATOR) {
239: --level;
240: }
241: if (level > 0) {
242: ++index;
243: }
244: }
245:
246: if (level > 0) {
247: throw new ConfigurationException(
248: "Invalid ifProperty expression: '" + str
249: + "' Missing grouping end operator '"
250: + GROUPING_END_OPERATOR + "'");
251: }
252:
253: return index;
254:
255: }
256: }
|