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