* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, The Mir-coders gives permission to link
- * the code of this program with any library licensed under the Apache Software License,
- * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
- * (or with modified versions of the above that use the same license as the above),
- * and distribute linked combinations including the two. You must obey the
- * GNU General Public License in all respects for all of the code used other than
- * the above mentioned libraries. If you modify this file, you may extend this
- * exception to your version of the file, but you are not obligated to do so.
+ * the code of this program with any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two. You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries. If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
* If you do not wish to do so, delete this exception statement from your version.
*/
package mir.util;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Vector;
import mir.generator.Generator;
import mir.generator.GeneratorExc;
import multex.Exc;
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.beanutils.PropertyUtils;
+
public class ParameterExpander {
final static String NODE_SEPARATOR = ".";
final static char STRING_ESCAPE_CHARACTER = '\\';
+ /**
+ * Fundamental method to retrieve a field of an object. Supported are
+ * maps, beans and objects with a generic get method
+ */
+ public static Object getObjectField(Object anObject, Object aField) {
+ if (anObject instanceof Map) {
+ return ((Map) anObject).get(aField);
+ }
+ else if ((aField instanceof String) && PropertyUtils.isReadable(anObject, (String) aField)) {
+ try {
+ return PropertyUtils.getProperty(anObject, (String) aField);
+ }
+ catch (Throwable t) {
+ throw new RuntimeException(t.getMessage());
+ }
+ }
+ else {
+ try {
+ return MethodUtils.invokeExactMethod(anObject, "get", aField);
+ }
+ catch (Throwable t) {
+ throw new RuntimeException("Invalid reference of " + aField + " into " + anObject);
+ }
+ }
+ }
+
private static Object findNode(String aKey, Map aMap, List aParts, boolean aMakeIfNotPresent) throws Exception {
Iterator i;
String location = "";
((Map) node).put(part, newNode);
}
else
- throw new ParameterExpanderExc( "Can't expand key {1}: {2} does not exist", new Object[]{aKey,location} );
+ throw new ParameterExpanderExc( "Can't expand key " + aKey + ": " + location + " does not exist");
node = newNode;
}
Object expandedValue = findValueForKey(aMap, aKey);
if (!(expandedValue instanceof String))
- throw new ParameterExpanderExc( "Value of key is not a string but a {1}", new Object[]{expandedValue.getClass().getName()} );
+ throw new ParameterExpanderExc( "Value of key is not a string but a " + expandedValue.getClass().getName());
return (String) expandedValue;
}
Object node=findNode(aKey, aMap, parts, true);
+ // todo: bean support
if (node instanceof Map) {
((Map) node).put(key, aValue);
}
else
- throw new ParameterExpanderExc( "Can't set key {1}: not inside a Map", new Object[]{aKey} );
+ throw new ParameterExpanderExc( "Can't set key " + aKey + " : not inside a Map");
}
- public static String expandExpression(Map aMap, String anExpression) throws Exception {
+ public static String expandExpression(Object aContext, String anExpression) throws Exception {
int previousPosition = 0;
int position;
int endOfExpressionPosition;
endOfExpressionPosition++;
}
if (endOfExpressionPosition>=anExpression.length()) {
- throw new ParameterExpanderExc("Unterminated string in {1}",new Object[]{anExpression});
+ throw new ParameterExpanderExc("Unterminated string in '" +anExpression+"'");
}
}
endOfExpressionPosition++;
}
if (endOfExpressionPosition<anExpression.length()) {
- result.append(evaluateStringExpression(aMap, anExpression.substring(position+2, endOfExpressionPosition)));
+ result.append(evaluateStringExpression(aContext, anExpression.substring(position+2, endOfExpressionPosition)));
previousPosition=endOfExpressionPosition+1;
}
else {
- throw new ParameterExpanderExc("Missing } in {1}",new Object[]{anExpression});
+ throw new ParameterExpanderExc("Missing } in " + anExpression);
}
}
else
return result.toString();
}
- public static boolean evaluateBooleanExpression(Map aMap, String anExpression) throws Exception {
+ public static boolean evaluateBooleanExpression(Object aMap, String anExpression) throws Exception {
Parser parser = new Parser(anExpression, aMap);
return parser.parseBoolean();
}
- public static String evaluateStringExpression(Map aMap, String anExpression) throws Exception {
+ public static String evaluateStringExpression(Object aMap, String anExpression) throws Exception {
Parser parser = new Parser(anExpression, aMap);
return parser.parseString();
}
- public static int evaluateIntegerExpressionWithDefault(Map aMap, String anExpression, int aDefault) throws Exception {
+ public static int evaluateIntegerExpressionWithDefault(Object aMap, String anExpression, int aDefault) throws Exception {
if (anExpression == null || anExpression.trim().equals(""))
return aDefault;
else
return evaluateIntegerExpression(aMap, anExpression);
}
- public static int evaluateIntegerExpression(Map aMap, String anExpression) throws Exception {
+ public static int evaluateIntegerExpression(Object aMap, String anExpression) throws Exception {
Parser parser = new Parser(anExpression, aMap);
return parser.parseInteger();
}
- public static Object evaluateExpression(Map aMap, String anExpression) throws Exception {
- Parser parser = new Parser(anExpression, aMap);
+ public static Object evaluateExpression(Object aRoot, String anExpression) throws Exception {
+ Parser parser = new Parser(anExpression, aRoot);
return parser.parseWhole();
}
private static abstract class Token {
}
- public static abstract class PunctuationToken extends Token { public PunctuationToken() { }; }
- private static class LeftSquareBraceToken extends PunctuationToken {};
- private static class RightSquareBraceToken extends PunctuationToken {};
- private static class EqualsToken extends PunctuationToken {};
- private static class EqualsNotToken extends PunctuationToken {};
- private static class NOTToken extends PunctuationToken {};
- private static class LeftParenthesisToken extends PunctuationToken {};
- private static class RightParenthesisToken extends PunctuationToken {};
- private static class CommaToken extends PunctuationToken {};
- private static class PeriodToken extends PunctuationToken {};
- private static class PlusToken extends PunctuationToken {};
- private static class TimesToken extends PunctuationToken {};
- private static class DivideToken extends PunctuationToken {};
- private static class MinusToken extends PunctuationToken {};
- private static class ConcatenateToken extends PunctuationToken {};
- private static class LessThanOrEqualsToken extends PunctuationToken {};
- private static class GreaterThanOrEqualsToken extends PunctuationToken {};
- private static class LessThanToken extends PunctuationToken {};
- private static class GreaterThanToken extends PunctuationToken {};
+ public static abstract class PunctuationToken extends Token { public PunctuationToken() { } }
+ private static class LeftSquareBraceToken extends PunctuationToken {}
+ private static class RightSquareBraceToken extends PunctuationToken {}
+ private static class EqualsToken extends PunctuationToken {}
+ private static class EqualsNotToken extends PunctuationToken {}
+ private static class NOTToken extends PunctuationToken {}
+ private static class LeftParenthesisToken extends PunctuationToken {}
+ private static class RightParenthesisToken extends PunctuationToken {}
+ private static class CommaToken extends PunctuationToken {}
+ private static class PeriodToken extends PunctuationToken {}
+ private static class PlusToken extends PunctuationToken {}
+ private static class TimesToken extends PunctuationToken {}
+ private static class DivideToken extends PunctuationToken {}
+ private static class MinusToken extends PunctuationToken {}
+ private static class ConcatenateToken extends PunctuationToken {}
+ private static class LessThanOrEqualsToken extends PunctuationToken {}
+ private static class GreaterThanOrEqualsToken extends PunctuationToken {}
+ private static class LessThanToken extends PunctuationToken {}
+ private static class GreaterThanToken extends PunctuationToken {}
private static class IdentifierToken extends Token {
public void skipWhitespace() {
while (reader.hasNext() && Character.isWhitespace(reader.peek().charValue()))
reader.getNext();
- };
+ }
private boolean isIdentifierStart(char c) {
return Character.isLetter(c) || (c == '_');
private static class Parser {
private Scanner scanner;
- private Map valueMap;
+ private Object valueMap;
- public Parser(String anExpression, Map aValueMap) {
+ public Parser(String anExpression, Object aValueMap) {
scanner = new Scanner(new Reader(anExpression));
valueMap = aValueMap;
}
private List parseList() {
Token token;
Object expression;
- List result = new Vector();
+ List result = new ArrayList();
token = scanner.scan();
if (!(token instanceof LeftParenthesisToken)) {
do {
expression = parse();
- if (expression==null) {
- throw new RuntimeException("expression expected");
- }
-
result.add(expression);
token = scanner.scan();
if (!(token instanceof RightSquareBraceToken))
throw new RuntimeException("] expected");
- if (currentValue instanceof Map) {
- currentValue = ((Map) currentValue).get(qualifier);
- }
- else {
- throw new RuntimeException("cannot reference into anything other than a map ('"+qualifier+"')");
- }
+ currentValue = getObjectField(currentValue, qualifier);
}
else if (token instanceof IdentifierToken) {
scanner.scan();
qualifier = ((IdentifierToken) token).getName();
- if (currentValue instanceof Map) {
- currentValue = ((Map) currentValue).get(qualifier);
- }
- else {
- throw new RuntimeException("cannot reference into anything other than a map ('"+qualifier+"')");
- }
+ currentValue = getObjectField(currentValue, qualifier);
}
else if (token instanceof LeftParenthesisToken) {
- if (currentValue instanceof Generator.GeneratorFunction) {
+ if (currentValue instanceof Generator.Function) {
parameters = parseList();
try {
- currentValue = ((Generator.GeneratorFunction) currentValue).perform(parameters);
+ currentValue = ((Generator.Function) currentValue).perform(parameters);
}
catch (GeneratorExc t) {
throw new RuntimeException(t.getMessage());
if (aValue instanceof Boolean)
return ((Boolean) aValue).booleanValue();
+ if (aValue instanceof RewindableIterator) {
+ ((RewindableIterator) aValue).rewind();
+ }
+
+ if (aValue instanceof Iterator) {
+ return ((Iterator) aValue).hasNext();
+ }
+
+ if (aValue instanceof List) {
+ return ((List) aValue).size()>0;
+ }
+
+ if (aValue instanceof String) {
+ return ((String) aValue).length()>0;
+ }
+
return aValue!=null;
}
private int interpretAsInteger(Object aValue) {
- if (aValue instanceof Integer)
+ if (aValue instanceof Integer) {
return ((Integer) aValue).intValue();
-
- if (aValue instanceof String) {
- try {
- return Integer.parseInt((String) aValue);
- }
- catch (Throwable t) {
- }
}
- throw new RuntimeException("Not an integer");
+ try {
+ return Integer.parseInt(aValue.toString());
+ }
+ catch (NumberFormatException t) {
+ throw new RuntimeException("Not an integer");
+ }
}
private String interpretAsString(Object aValue) {
+ if (aValue==null)
+ return "";
if (aValue instanceof String)
return (String) aValue;
if (aValue instanceof Integer)
- return ((Integer) aValue).toString();
+ return aValue.toString();
throw new RuntimeException("Not a string");
}
if (aToken instanceof ConcatenateToken)
return interpretAsString(aValue1) + interpretAsString(aValue2);
- if (aToken instanceof LessThanOrEqualsToken)
+ if (aToken instanceof LessThanOrEqualsToken) {
return new Boolean(interpretAsInteger(aValue1) <= interpretAsInteger(aValue2));
- if (aToken instanceof LessThanToken)
+ }
+ if (aToken instanceof LessThanToken) {
return new Boolean(interpretAsInteger(aValue1) < interpretAsInteger(aValue2));
- if (aToken instanceof GreaterThanOrEqualsToken)
+ }
+ if (aToken instanceof GreaterThanOrEqualsToken) {
return new Boolean(interpretAsInteger(aValue1) >= interpretAsInteger(aValue2));
- if (aToken instanceof GreaterThanToken)
+ }
+ if (aToken instanceof GreaterThanToken) {
return new Boolean(interpretAsInteger(aValue1) > interpretAsInteger(aValue2));
+ }
throw new RuntimeException("Internal error: unknown binary operator: " + aToken.getClass().getName());
}
}
public static class ParameterExpanderExc extends Exc {
- public ParameterExpanderExc(String msg, Object[] objects) {
- super(msg, objects);
+ public ParameterExpanderExc(String msg) {
+ super(msg);
}
}
}
\ No newline at end of file