View Javadoc

1   package cz.cuni.amis.pogamut.sposh.elements;
2   
3   import cz.cuni.amis.pogamut.sposh.executor.IAction;
4   import java.util.AbstractList;
5   import java.util.ArrayList;
6   import java.util.List;
7   
8   /**
9    * This class represents the arguments of the {@link PrimitiveCall}. {@link PrimitiveCall}
10   * can reference either normal {@link IAction}, {@link ActionPattern} or {@link Competence}
11   * that will get these arguments, mix them with their own {@link FormalParameters}
12   * and create the values for the Action/C/AP.
13   *
14   * Arguments is stored as list of {@link Argument}, each argument is basically
15   * (key; argument) pair. Arguments are sorted according to the key. What is the
16   * key? Either a variable name or index of the argument in the list or
17   * arguments. Variable names have '$' prefix, e.g. $name. The indexes are simply
18   * string representations of the numbers, e.g. index 3 is represented as "3".
19   *
20   * Calling convention:
21   * 
22   * TODO: Properly document.
23   * TODO: Properly test.
24   * TODO: This probably doesn;t need to be abstract list
25   *
26   * Example: call run("street", speed=14.5) will create
27   *
28   * @author Honza Havlicek
29   */
30  public class Arguments extends AbstractList<Arguments.Argument> {
31  
32      public static Arguments EMPTY = new Arguments();
33      
34      public static abstract class Argument {
35  
36          final private String parameterName;
37  
38          /**
39           * Create paramter with name.
40           *
41           * @param parameterName
42           */
43          protected Argument(String parameterName) {
44              this.parameterName = parameterName;
45          }
46  
47          /**
48           * Retrieve value of parameter.
49           *
50           * @return
51           */
52          public abstract Object getValue();
53  
54          /**
55           * Is value of this parameter retrieved from variable or value?
56           *
57           * @return null if this is a value, string with name of parameter
58           * variable else
59           */
60          public abstract String getParameterVariable();
61  
62          public String getParameterName() {
63              return parameterName;
64          }
65  
66          @Override
67          public abstract String toString();
68  
69          @Override
70          protected abstract Argument clone();
71          
72          /**
73           * Create new argument object with specified name and value.
74           *
75           * @param argumentName name of argument.
76           * @param value Object representation of the argument value
77           * @return
78           */
79          public static Argument createValueArgument(String argumentName, Object value) {
80              return new ValueArgument(argumentName, value);
81          }
82          
83          /**
84           * Create new argument with specified name and its value is defined by
85           * the content of the variable.
86           *
87           * @param argumentName name of created argument
88           * @param variableName name of variable that will be used to get the
89           * value.
90           * @return
91           */
92          public static Argument createVariableArgument(String argumentName, String variableName) {
93              return new VariableArgument(argumentName, variableName);
94          }
95      }
96  
97      /**
98       * This parameter is dependant on value of some kind of variable.
99       */
100     protected static final class VariableArgument extends Arguments.Argument {
101 
102         protected final String variableName;
103 
104         protected VariableArgument(int index, String variableName) {
105             super(Integer.toString(index));
106             this.variableName = variableName;
107         }
108 
109         /**
110          * New call parameter.
111          *
112          * @param parameterName name of parameter of called primitive
113          * @param variableName variable where is stored the value passed to
114          * primitive
115          */
116         protected VariableArgument(String parameterName, String variableName) {
117             super(parameterName);
118             this.variableName = variableName;
119         }
120 
121         @Override
122         public String getValue() {
123             throw new UnsupportedOperationException("Not yet implemented");
124         }
125 
126         @Override
127         public String getParameterVariable() {
128             return variableName;
129         }
130 
131         @Override
132         public String toString() {
133             if (getParameterName().startsWith("$")) {
134                 return getParameterName() + "=" + variableName;
135             }
136             return variableName;
137         }
138 
139         @Override
140         protected VariableArgument clone() {
141             return new VariableArgument(getParameterName(), variableName);
142         }
143     }
144 
145     /**
146      * This parameter is static value, neverchanging.
147      */
148     protected static final class ValueArgument extends Arguments.Argument {
149 
150         private final Object value;
151 
152         /**
153          * Create a value parameter that represents fixed value. <p> Sequence
154          * number is used as name of this parameter. Since normal variables
155          * starts with $, it won't mix.
156          *
157          * @param sequenceNumber number of this parameter in sequence of all
158          * parameters. Starting from 0.
159          * @param value value of parameter.
160          */
161         protected ValueArgument(int sequenceNumber, Object value) {
162             super(Integer.toString(sequenceNumber));
163             this.value = value;
164         }
165 
166         protected ValueArgument(String parameterName, Object value) {
167             super(parameterName);
168             this.value = value;
169         }
170 
171         @Override
172         public Object getValue() {
173             return value;
174         }
175 
176         @Override
177         public String getParameterVariable() {
178             return null;
179         }
180 
181         @Override
182         public String toString() {
183             if (getParameterName().startsWith("$")) {
184                 return getParameterName() + "=" + Result.toLap(value);
185             }
186             return Result.toLap(value);
187         }
188 
189         @Override
190         protected ValueArgument clone() {
191             return new ValueArgument(getParameterName(), value);
192         }
193     }
194     private List<Arguments.Argument> parameters = new ArrayList<Argument>();
195 
196     /**
197      * Create a new list of call parameters. <p> Every added variable parameter
198      * has to be checked against list of formal parameters.
199      */
200     public Arguments() {
201     }
202 
203     /**
204      * Copy constructor. Beware, this doesn't copy reference to the formal
205      * parameters.
206      *
207      * @param parameters orginal
208      */
209     protected Arguments(Arguments parameters) {
210         for (int i = 0; i < parameters.size(); ++i) {
211             Argument parameter = parameters.get(i);
212             Argument clone = parameter.clone();
213             this.parameters.add(clone);
214         }
215     }
216 
217     @Override
218     public synchronized Arguments.Argument get(int index) {
219         return parameters.get(index);
220     }
221 
222     @Override
223     public synchronized int size() {
224         return parameters.size();
225     }
226 
227     @Override
228     public void add(int index, Argument element) {
229         parameters.add(index, element);
230     }
231     
232     public synchronized boolean addFormal(Arguments.Argument element, FormalParameters formalParams) {
233         // check if variable is defined in the context
234         String parameterVariable = element.getParameterVariable();
235         if (parameterVariable != null) {
236             if (!formalParams.containsVariable(parameterVariable)) {
237                 throw new IllegalArgumentException("Variable \"" + parameterVariable + "\" is not defined in formal parameters (" + formalParams.toString() + ").");
238             }
239         }
240 
241         // next check that named parameter isn't duplicated
242         for (int i = 0; i < parameters.size(); ++i) {
243             String parameterName = parameters.get(i).getParameterName();
244             // check if there isn't already variable name with same name
245             if (parameterName != null && parameterName.equals(element.getParameterName())) {
246                 throw new IllegalArgumentException("Named parameter \"" + element.getParameterName() + "\" has already been defined.");
247             }
248         }
249         return parameters.add(element);
250     }
251 
252     /**
253      * Get string representation of arguments (comma separated arguments,
254      * compatible with lap).
255      *
256      * @return arguments separated with comma (e.g. |"Friends of peace.",
257      * $when=now, $who=just_first_player|)
258      */
259     @Override
260     public String toString() {
261         StringBuilder sb = new StringBuilder();
262         for (int argumentIndex = 0; argumentIndex < parameters.size(); ++argumentIndex) {
263             if (argumentIndex != 0) {
264                 sb.append(',');
265             }
266             Argument argument = parameters.get(argumentIndex);
267             sb.append(argument.toString());
268         }
269         return sb.toString();
270     }
271 }