View Javadoc

1   package cz.cuni.amis.pogamut.sposh.engine;
2   
3   import cz.cuni.amis.pogamut.sposh.elements.Arguments;
4   import cz.cuni.amis.pogamut.sposh.elements.Arguments.Argument;
5   import cz.cuni.amis.pogamut.sposh.elements.FormalParameters;
6   import cz.cuni.amis.pogamut.sposh.elements.Result;
7   import java.util.Arrays;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.Map;
11  import java.util.Map.Entry;
12  import java.util.Set;
13  
14  /**
15   * This class is responsible for storing and passing arguments throught the posh plan.
16   * Unnamed varibales are named as number (e.g. "0", "1"...), named variables
17   * have same name as in plan.
18   * @author Honza
19   */
20  final public class VariableContext {
21      private VariableContext parent;
22      private Map<String, Object> vars = new HashMap<String, Object>();
23  
24      public VariableContext() {
25          this.parent = null;
26      }
27      
28      /**
29       * Create new VariableContext that will contain only variables from call arguments.
30       * @param callArgs
31       */
32      public VariableContext(VariableContext ctx, Arguments callArgs) {
33          this.parent = ctx;
34          for (Arguments.Argument param : callArgs) {
35              String argumentVariable = param.getParameterVariable();
36              if (argumentVariable != null) {
37                  vars.put(param.getName(), ctx.getValue(argumentVariable));
38              } else {
39                  vars.put(param.getName(), param.getValue());
40              }
41          }
42      }
43  
44      /**
45       * Create new variable context for diving into another function.
46       * New context will contain only variables from formal parameters, and its
47       * values will be values passed from call arguments or (if missing) default value
48       * from formal parametrs.
49       * 
50       * @param ctx
51       * @param callParameters
52       * @param formalParameters
53       */
54      public VariableContext(VariableContext ctx, Arguments callParameters, FormalParameters formalParameters) {
55          this.parent = ctx;
56          HashSet<Argument> unusedArgs = new HashSet<Argument>(callParameters);
57          for (int index = 0; index < formalParameters.size(); ++index) {
58              String ctxVariableName = formalParameters.get(index).getName();
59              Object ctxVariableValue = formalParameters.get(index).getDefaultValue();
60  
61              // if user supplied value, get it and put it into ctxVariableValue instead of default value
62              for (Argument param : callParameters) {
63                  String argumentName = param.getName();
64                  try {
65                      int paramterIndex = Integer.parseInt(argumentName);
66                      if (index != paramterIndex) {
67                          continue;
68                      }
69                  } catch (NumberFormatException ex) {
70                      // nope, this is not a unnamed parametr, this one has a name
71                      // Is name among formal parametrs?
72                      String parameterName = param.getName();
73                      if (!parameterName.equals(ctxVariableName))
74                          continue;
75                  }
76                  
77                  unusedArgs.remove(param);
78                  
79                  String variableName = param.getParameterVariable();
80                  if (variableName != null) {
81                      ctxVariableValue = ctx.getValue(variableName);
82                  } else {
83                      ctxVariableValue = param.getValue();
84                  }
85              }
86  
87              vars.put(ctxVariableName, ctxVariableValue);
88          }
89          for (Argument unusedArg : unusedArgs) {
90              String variableName = unusedArg.getParameterVariable();
91              if (variableName != null) {
92                  if (ctx.hasVariable(variableName)) {
93                      vars.put(unusedArg.getName(), ctx.getValue(variableName));
94                  }
95              } else {
96                  vars.put(unusedArg.getName(), unusedArg.getValue());
97              }
98          }
99      }
100 
101     /**
102      * Put another variable into this context
103      * @param parameterName name of new parameter
104      * @param value value of parameter
105      * @return old value for parameterName or null if it is a new parameter.
106      */
107     public synchronized Object put(String parameterName, Object value) {
108         return vars.put(parameterName, value);
109     }
110 
111     /**
112      * Get keys of all variables in this context.
113      * @return
114      */
115     public synchronized String[] getKeys() {
116         Set<String> allKeys = new HashSet<String>();
117         VariableContext currentCtx = this;
118         while (currentCtx != null) {
119             allKeys.addAll(currentCtx.vars.keySet());
120             currentCtx = currentCtx.parent;
121         }
122         return allKeys.toArray(new String[allKeys.size()]);
123     }
124 
125     /**
126      * Get value stored in the 
127      * @param variableName
128      * @return
129      * @throws IllegalArgumentException If such variable is not present.
130      */
131     public synchronized Object getValue(String variableName) {
132         if (vars.containsKey(variableName)) {
133             return vars.get(variableName);
134         }
135         if (this.parent != null) {
136             return parent.getValue(variableName);
137         }
138         throw new IllegalArgumentException("There is no variable in the context with name \"" + variableName + "\".");
139     }
140 
141     @Override
142     public String toString() {
143         StringBuilder sb = new StringBuilder();
144 
145         sb.append('[');
146         String[] list = new String[vars.size()];
147         int index = 0;
148         for (Entry entry : vars.entrySet()) {
149             list[index++] = entry.getKey() + "=" + Result.toLap(entry.getValue());
150         }
151         Arrays.sort(list);
152         for (int i = 0; i < list.length; ++i) {
153             if (i != 0) {
154                 sb.append(", ");
155             }
156             sb.append(list[i]);
157         }
158 
159         sb.append(']');
160         return sb.toString();
161     }
162 
163     public synchronized int size() {
164         return this.vars.size();
165     }
166 
167     public boolean hasVariable(String variableName) {
168         if (vars.containsKey(variableName)) {
169             return true;
170         }
171         if (this.parent != null) {
172             return parent.hasVariable(variableName);
173         }
174         return false;
175     }
176 }