View Javadoc

1   package cz.cuni.amis.pogamut.sposh.elements;
2   
3   import cz.cuni.amis.pogamut.sposh.exceptions.DuplicateNameException;
4   import cz.cuni.amis.pogamut.sposh.exceptions.FubarException;
5   import cz.cuni.amis.pogamut.sposh.executor.DoNothing;
6   import cz.cuni.amis.pogamut.sposh.executor.Succeed;
7   import java.io.StringReader;
8   import java.util.ArrayList;
9   import java.util.Arrays;
10  import java.util.Collections;
11  import java.util.LinkedList;
12  import java.util.List;
13  import java.util.logging.Level;
14  import java.util.logging.Logger;
15  
16  /**
17   * This is a factory class that should be used to create various elements. Do
18   * not create elements with their constructor, if you can avoid it, this factory
19   * will make sure that returned elements are valid, e.g. all parent links in
20   * elements are correctly linked and so on.
21   *
22   * @author HonzaH
23   */
24  public class LapElementsFactory {
25  
26      /**
27       * Name of action that will be used unless user specifies a name of action
28       * that should be used.
29       */
30      public static String DEFAULT_ACTION = DoNothing.class.getName();
31      /**
32       * Name of trigger that will be used unless user specifies some other
33       * trigger in the arguments.
34       */
35      public static String DEFAULT_TRIGGER_SENSE = Succeed.class.getName();
36      public static String DEFAULT_DRIVE_COLLECTION_NAME = "life";
37  
38      /**
39       * Create a new competence with multiple choices. The choices have default
40       * action and trigger.
41       *
42       * @param name name of new competence
43       * @param choices unique sequence of choices for this competence
44       * @return created competence
45       */
46      public static Competence createCompetence(String name, String... choices) throws DuplicateNameException {
47          List<CompetenceElement> elements = new ArrayList<CompetenceElement>(choices.length);
48  
49          for (String choice : choices) {
50              elements.add(LapElementsFactory.createCompetenceElement(choice));
51          }
52  
53          return new Competence(name, new FormalParameters(), elements);
54      }
55  
56      /**
57       * Create new drive with default trigger and action.
58       *
59       * @param driveName name of the drive
60       */
61      public static DriveElement createDriveElement(String driveName) {
62          return new DriveElement(driveName, Arrays.asList(new Sense(DEFAULT_TRIGGER_SENSE)), new PrimitiveCall(DEFAULT_ACTION), Freq.INFINITE, "");
63      }
64  
65      /**
66       * Create new drive with specified name and empty list of triggers and
67       * default action.
68       *
69       * @param name name of created drive element
70       */
71      public static DriveElement createDriveElementNoTriggers(String name) {
72          return new DriveElement(name, Collections.<Sense>emptyList(), new PrimitiveCall(DEFAULT_ACTION), Freq.INFINITE, "");
73      }
74  
75      /**
76       * Create new competence element with no trigger sense and default action.
77       *
78       * @param name name of competence element
79       * @return created element
80       */
81      public static CompetenceElement createCompetenceElement(String name) {
82          return new CompetenceElement(name, Collections.<Sense>emptyList(), new PrimitiveCall(DEFAULT_ACTION), CompetenceElement.INFINITE_RETRIES, "");
83      }
84  
85      /**
86       * Create new sense.
87       *
88       * @param name name of the sense
89       * @return created sense
90       */
91      public static Sense createSense(String name) {
92          return new Sense(name);
93      }
94  
95      /**
96       * Create default action.
97       */
98      public static TriggeredAction createAction() {
99          return new TriggeredAction(DEFAULT_ACTION);
100     }
101 
102     /**
103      * Create action with specified name.
104      *
105      * @param name Name of the action
106      * @return created action
107      */
108     public static TriggeredAction createAction(String name) {
109         return new TriggeredAction(name);
110     }
111 
112     /**
113      * Create action for specified call.
114      */
115     public static TriggeredAction createAction(PrimitiveCall call) {
116         return new TriggeredAction(new PrimitiveCall(call));
117     }
118 
119     /**
120      * Create new action pattern without parameters and one {@link #DEFAULT_ACTION default}
121      * action.
122      *
123      * @param name Name of new action pattern
124      * @return created AP
125      */
126     public static ActionPattern createActionPattern(String name) {
127         return new ActionPattern(name, new FormalParameters(), Arrays.asList(new TriggeredAction(DEFAULT_ACTION)), "");
128     }
129 
130     /**
131      * Create new action pattern without parameters and containing passed
132      * actions.
133      *
134      * @param name Name of new action pattern
135      * @param actions Sequence of actions that will in the AP
136      * @return created AP
137      */
138     public static ActionPattern createActionPattern(String name, TriggeredAction... actions) {
139         return new ActionPattern(name, new FormalParameters(), Arrays.asList(actions), "");
140     }
141 
142     /**
143      * Create empty action pattern with specified name and parameters, but
144      * without any actions in it.
145      *
146      * @param name Name of the AP
147      * @return created AP
148      */
149     public static ActionPattern createActionPattern(String name, FormalParameters params) {
150         return new ActionPattern(name, params, Collections.<TriggeredAction>emptyList(), "");
151     }
152 
153     /**
154      * Create action pattern
155      *
156      * @param name Name of the AP
157      * @param params parameters of this AP
158      * @param actions actions that will be in the AP
159      * @return created AP
160      */
161     public static ActionPattern createActionPattern(String name, FormalParameters params, List<TriggeredAction> actions) {
162         return new ActionPattern(name, params, actions, "");
163     }
164 
165     /**
166      * Create an AP with same structure as passed ap (only structure, no
167      * listeners or shared objects).
168      *
169      * @param ap action pattern to copy
170      * @return ap with same structure as the ap.
171      */
172     public static ActionPattern createActionPattern(ActionPattern ap) {
173         // XXX: Proper copy constructor
174         String serializedActionPattern = ap.toString();
175         try {
176             return new PoshParser(new StringReader(serializedActionPattern.substring(serializedActionPattern.indexOf('(') + 1))).actionPattern();
177         } catch (ParseException ex) {
178             String msg = "Tried to serialize and deserialize action pattern as copy constructor: " + serializedActionPattern;
179             Logger.getLogger(LapElementsFactory.class.getName()).log(Level.SEVERE, msg, ex);
180             throw new FubarException(msg, ex);
181         }
182     }
183 
184     /**
185      * Create a C with same structure as passed c (only structure, no listeners
186      * or shared objects).
187      *
188      * @param c competence to copy
189      * @return competence with same structure as the c.
190      */
191     public static Competence createCompetence(Competence c) {
192         // XXX: Proper copy constructor
193         String serializedCompetence = c.toString();
194         try {
195             return new PoshParser(new StringReader(serializedCompetence.substring(serializedCompetence.indexOf('(') + 1))).competence();
196         } catch (ParseException ex) {
197             String msg = "Tried to serialize and deserialize competence as copy constructor: " + serializedCompetence;
198             Logger.getLogger(LapElementsFactory.class.getName()).log(Level.SEVERE, msg, ex);
199             throw new FubarException(msg, ex);
200         }
201     }
202 
203     public static DriveElement createDriveElement(DriveElement drive) {
204         // XXX: Proper copy constructor
205         String serializedDrive = drive.toString();
206         try {
207             return new PoshParser(new StringReader(serializedDrive)).driveElement(new FormalParameters());
208         } catch (ParseException ex) {
209             String msg = "Tried to serialize and deserialize drive as copy constructor: " + serializedDrive;
210             Logger.getLogger(LapElementsFactory.class.getName()).log(Level.SEVERE, msg, ex);
211             throw new FubarException(msg, ex);
212         }
213     }
214 
215     /**
216      * Create a copy of sense (only structure, no listeners or shared objects)
217      *
218      * @param sense
219      * @return
220      */
221     public static Sense createSense(Sense sense) {
222         // XXX: Proper copy constructor
223         String serializedSense = sense.toString();
224         try {
225             return new PoshParser(new StringReader(serializedSense)).fullSense(new FormalParameters());
226         } catch (ParseException ex) {
227             String msg = "Tried to serialize and deserialize sense as copy constructor: " + serializedSense;
228             Logger.getLogger(LapElementsFactory.class.getName()).log(Level.SEVERE, msg, ex);
229             throw new FubarException(msg, ex);
230         }
231     }
232 
233     /**
234      * Create empty drive collection without trigger senses and drives, with
235      * blank name.
236      *
237      * @return
238      */
239     public static DriveCollection createDriveCollection() {
240         // XXX: Current structure of parser requires to create DC before we have name, so put something there.
241         return new DriveCollection("placeholder");
242     }
243 
244     /**
245      * Create empty (i.e. no drives) {@link DriveCollection} with specified
246      * name.
247      *
248      * @param driveCollectionName Name of the created {@link DriveCollection}
249      * @return Newly created {@link DriveCollection}.
250      */
251     public static DriveCollection createDriveCollection(String driveCollectionName) {
252         return new DriveCollection(driveCollectionName);
253     }
254 
255     public static CompetenceElement createCompetenceElement(String name, List<Sense> triggerSenses, String actionName) {
256         return new CompetenceElement(name, triggerSenses, new PrimitiveCall(actionName), CompetenceElement.INFINITE_RETRIES, "");
257     }
258 
259     /**
260      * Create new drive element
261      *
262      * @param name Name of the drive element
263      * @param triggerSenses list of senses that will be used as a trigger
264      * @param actionCall What to call if drive is elected
265      * @param freq How frequently can be this drive called (if called more
266      * frequently, the calls will not be elegible)
267      * @param comment Comment about the element
268      * @return Created drive
269      */
270     public static DriveElement createDriveElement(String name, List<Sense> triggerSenses, PrimitiveCall actionCall, Freq freq, String comment) {
271         return new DriveElement(name, triggerSenses, actionCall, freq, comment);
272     }
273 
274     /**
275      * Create choice from the passed drive.
276      *
277      * @param drive Base for created choice
278      * @return Choice created according to the drive, infinite retries.
279      */
280     public static CompetenceElement createCompetenceElement(DriveElement drive) {
281         return new CompetenceElement(
282                 drive.getName(),
283                 copySenses(drive.getTrigger()),
284                 new PrimitiveCall(drive.getAction().getActionCall()),
285                 CompetenceElement.INFINITE_RETRIES,
286                 drive.getComment());
287     }
288 
289     /**
290      * Create a copy of a passed choice.
291      *
292      * @param choice Choice that will be used as original
293      * @return created element
294      */
295     public static CompetenceElement createCompetenceElement(CompetenceElement choice) {
296         return new CompetenceElement(
297                 choice.getName(),
298                 copySenses(choice.getTrigger()),
299                 new PrimitiveCall(choice.getAction().getActionCall()),
300                 choice.getRetries(),
301                 choice.getComment());
302     }
303     
304     
305     /**
306      * Create drive based on the choice.
307      *
308      * @param choice Choice used as base for new drive.
309      * @return Drive created from the choice, infinite frequency
310      */
311     public static DriveElement createDriveElement(CompetenceElement choice) {
312         return new DriveElement(
313                 choice.getName(),
314                 copySenses(choice.getTrigger()),
315                 new PrimitiveCall(choice.getAction().getActionCall()),
316                 Freq.INFINITE,
317                 choice.getComment());
318     }
319 
320     /**
321      * Create a deep copy of senses in the trigger.
322      */
323     private static <OWNER extends PoshElement> List<Sense> copySenses(Trigger<OWNER> trigger) {
324         List<Sense> senses = new LinkedList<Sense>();
325         for (Sense sense : trigger) {
326             senses.add(createSense(sense));
327         }
328         return senses;
329     }
330 
331     /**
332      * Create new plan with DC
333      *
334      * @param dcName name of the DC
335      * @return created plan
336      */
337     public static PoshPlan createPlan(String dcName) {
338         return new PoshPlan(dcName);
339     }
340 
341     /**
342      * Create new plan with empty {@link DriveCollection} that has {@link #DEFAULT_DRIVE_COLLECTION_NAME}
343      * name.
344      */
345     static PoshPlan createPlan() {
346         return createPlan(DEFAULT_DRIVE_COLLECTION_NAME);
347     }
348 
349     /**
350      * Copy method for an action. Parent is not copied, only the data of the
351      * element.
352      *
353      * @param original
354      * @return
355      */
356     public static TriggeredAction createAction(TriggeredAction original) {
357         return new TriggeredAction(new PrimitiveCall(original.getActionCall()));
358     }
359 }