merged with 1.1
[mir.git] / source / mir / util / ParameterExpander.java
index 8db5736..a65015b 100755 (executable)
@@ -1,30 +1,51 @@
-package  mir.util;
+/*
+ * Copyright (C) 2001, 2002 The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mir; if not, write to the Free Software
+ * 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.
+ * If you do not wish to do so, delete this exception statement from your version.
+ */
+package mir.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.commons.beanutils.*;
 
-import multex.Failure;
 import multex.Exc;
 
-import java.util.*;
+import mir.generator.Generator;
+import mir.generator.GeneratorExc;
 
 public class ParameterExpander {
   final static String NODE_SEPARATOR = ".";
   final static char STRING_ESCAPE_CHARACTER = '\\';
 
-  public static List splitString(String aString, String aSeparator) {
-    List result= new Vector();
-    int previousPosition = 0;
-    int position;
-    int endOfNamePosition;
-
-    while ((position = aString.indexOf(aSeparator, previousPosition))>=0) {
-      result.add(aString.substring(previousPosition, position));
-      previousPosition = position + aSeparator.length();
-    }
-
-    result.add(aString.substring(previousPosition, aString.length()));
-
-    return result;
-  }
-
   private static Object findNode(String aKey, Map aMap, List aParts, boolean aMakeIfNotPresent) throws Exception {
     Iterator i;
     String location = "";
@@ -63,7 +84,7 @@ public class ParameterExpander {
 
   public static Object findValueForKey(Map aMap, String aKey) throws Exception {
     Object node;
-    List parts = splitString(aKey, NODE_SEPARATOR);
+    List parts = StringRoutines.splitString(aKey, NODE_SEPARATOR);
 
     node = findNode(aKey, aMap, parts, false);
 
@@ -80,7 +101,7 @@ public class ParameterExpander {
   }
 
   public static void setValueForKey(Map aMap, String aKey, Object aValue) throws Exception {
-    List parts = splitString(aKey, NODE_SEPARATOR);
+    List parts = StringRoutines.splitString(aKey, NODE_SEPARATOR);
 
     String key = (String) parts.get(parts.size()-1);
     parts.remove(parts.size()-1);
@@ -121,7 +142,7 @@ public class ParameterExpander {
                   endOfExpressionPosition++;
                 endOfExpressionPosition++;
               }
-              if (endOfExpressionPosition<anExpression.length()) {
+              if (endOfExpressionPosition>=anExpression.length()) {
                 throw new ParameterExpanderExc("Unterminated string in {1}",new Object[]{anExpression});
               }
             }
@@ -147,33 +168,33 @@ public class ParameterExpander {
     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();
   }
@@ -469,9 +490,9 @@ public class ParameterExpander {
 
   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;
     }
@@ -521,14 +542,14 @@ public class ParameterExpander {
       return parseUntil(MAX_OPERATOR_LEVEL);
     }
 
-    private Object parseSet() {
+    private List parseList() {
       Token token;
       Object expression;
-      Set result = new HashSet();
+      List result = new Vector();
 
       token = scanner.scan();
       if (!(token instanceof LeftParenthesisToken)) {
-        throw new RuntimeException("( expected after in keyword");
+        throw new RuntimeException("( expected");
       }
 
       if (scanner.peek() instanceof RightParenthesisToken) {
@@ -539,10 +560,6 @@ public class ParameterExpander {
       do {
         expression = parse();
 
-        if (expression==null) {
-          throw new RuntimeException("expression expected");
-        }
-
         result.add(expression);
 
         token = scanner.scan();
@@ -556,42 +573,76 @@ public class ParameterExpander {
       return result;
     }
 
+    private Object evaluateObjectField(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 Object parseVariable() {
       boolean done;
       Token token;
       Object currentValue = valueMap;
       Object qualifier;
+      List parameters;
 
       do {
-        token = scanner.scan();
+        token = scanner.peek();
+
         if (token instanceof LeftSquareBraceToken) {
+          scanner.scan();
           qualifier = parseUntil(MAX_OPERATOR_LEVEL);
           token = scanner.scan();
           if (!(token instanceof RightSquareBraceToken))
             throw new RuntimeException("] expected");
+
+          currentValue = evaluateObjectField(currentValue, qualifier);
         }
         else if (token instanceof IdentifierToken) {
+          scanner.scan();
           qualifier = ((IdentifierToken) token).getName();
-        }
-        else
-          throw new RuntimeException("fieldname or [ expected");
 
-        if (currentValue!=null) {
-          if (currentValue instanceof Map) {
-            currentValue = ((Map) currentValue).get(qualifier);
-          }
-          else {
-            throw new RuntimeException("cannot reference into anything other than a map");
-          }
+          currentValue = evaluateObjectField(currentValue, qualifier);
         }
-        else {
-          // throw? or allow null.null?
+        else if (token instanceof LeftParenthesisToken) {
+          if (currentValue instanceof Generator.GeneratorFunction) {
+            parameters = parseList();
+            try {
+              currentValue = ((Generator.GeneratorFunction) currentValue).perform(parameters);
+            }
+            catch (GeneratorExc t) {
+              throw new RuntimeException(t.getMessage());
+            }
+          }
+          else
+            throw new RuntimeException("not a function");
         }
+        else
+          throw new RuntimeException("fieldname or [ expected");
 
-        if (scanner.peek() instanceof PeriodToken)
-        {
-          scanner.scan();
+        if (scanner.peek() instanceof PeriodToken ||
+            scanner.peek() instanceof LeftSquareBraceToken ||
+            scanner.peek() instanceof LeftParenthesisToken) {
           done = false;
+
+          if (scanner.peek() instanceof PeriodToken)
+            scanner.scan();
         }
         else
           done = true;
@@ -618,7 +669,7 @@ public class ParameterExpander {
         value = parseUntil(unaryOperatorLevel(token));
         value = expandOperatorExpression(token, value);
       }
-      else if (token instanceof IdentifierToken) {
+      else if (token instanceof IdentifierToken || token instanceof LeftSquareBraceToken) {
         value = parseVariable();
       }
       else if (token instanceof LiteralToken) {
@@ -635,7 +686,7 @@ public class ParameterExpander {
         scanner.scan();
 
         if (isINOperator(token)) {
-          value2 = parseSet();
+          value2 = parseList();
         }
         else {
           value2 = parseUntil(binaryOperatorLevel(token));
@@ -649,7 +700,7 @@ public class ParameterExpander {
       return value;
     }
 
-    private static final int MAX_OPERATOR_LEVEL = 1000;               // && || !
+    private static final int MAX_OPERATOR_LEVEL = 1000;                //
     private static final int LOGICAL_OPERATOR_LEVEL = 5;               // && || !
     private static final int COMPARISON_OPERATOR_LEVEL = 4;            // == <= >= in < >
     private static final int ADDITION_OPERATOR_LEVEL = 3;              // + - &
@@ -749,6 +800,8 @@ public class ParameterExpander {
     }
 
     private String interpretAsString(Object aValue) {
+      if (aValue==null)
+        return "";
       if (aValue instanceof String)
         return (String) aValue;
       if (aValue instanceof Integer)
@@ -775,11 +828,11 @@ public class ParameterExpander {
 
     private Object expandOperatorExpression(Token aToken, Object aValue1, Object aValue2) {
       if (isINOperator(aToken)) {
-        if (!(aValue2 instanceof Set)) {
-          throw new RuntimeException("Internal error: set expected");
+        if (!(aValue2 instanceof List)) {
+          throw new RuntimeException("Internal error: List expected");
         }
 
-        Iterator i = ((Set) aValue2).iterator();
+        Iterator i = ((List) aValue2).iterator();
 
         while (i.hasNext()) {
           if (areEqual(aValue1, i.next()))