View Javadoc

1   package cz.cuni.amis.pogamut.sposh.engine;
2   
3   import cz.cuni.amis.pogamut.sposh.elements.LapPath;
4   import cz.cuni.amis.pogamut.sposh.elements.LapType;
5   import cz.cuni.amis.pogamut.sposh.elements.PoshElement;
6   import cz.cuni.amis.pogamut.sposh.elements.Sense;
7   import cz.cuni.amis.pogamut.sposh.elements.Trigger;
8   import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
9   import java.util.ArrayList;
10  import java.util.Collections;
11  import java.util.Iterator;
12  import java.util.LinkedList;
13  import java.util.List;
14  import java.util.logging.Logger;
15  
16  /**
17   * Class that immutably stores the result of evaluation of trigger. Trigger is
18   * basically a list of sense calls (i.e. {@link SenseListExecutor}).
19   */
20  class TriggerResult implements Iterable<SenseResult> {
21  
22      private final List<SenseResult> senses;
23      private final boolean success;
24  
25      /**
26       * Create new result of trigger
27       *
28       * @param senses list of results, what did each sense ended up as
29       * @param success was the trigger as a whole successful
30       */
31      public TriggerResult(List<SenseResult> senses, boolean success) {
32          this.success = success;
33          this.senses = Collections.unmodifiableList(new ArrayList<SenseResult>(senses));
34      }
35  
36      /**
37       * Create new result of trigger, without specifying any senses.
38       *
39       * @param success was the trigger successful
40       */
41      public TriggerResult(boolean success) {
42          this(Collections.<SenseResult>emptyList(), success);
43      }
44  
45      public boolean wasSuccess() {
46          return success;
47      }
48  
49      /**
50       * Get iterator to the all senses of this trigger. Unmodifiable.
51       *
52       * @return iterator to the start of sens's list.
53       */
54      @Override
55      public Iterator<SenseResult> iterator() {
56          return senses.iterator();
57      }
58  }
59  
60  /**
61   * Executor that decicdes if goal or trigger are fulfilled. That happens only is
62   * all its senses are fired.
63   *
64   * @author Honza
65   */
66  final class SenseListExecutor<T extends PoshElement> extends AbstractExecutor {
67  
68      private List<SenseExecutor> sensesExecutors = new ArrayList<SenseExecutor>();
69  
70      /**
71       * Create an executor for triggers.
72       *
73       * @param trigger source of senses, can be null, then no senses will be
74       * used.
75       * @param senseListPath Path to the parent of all senses. Trigger/goal
76       * itself isn't node (e.g. it is a path to drive that have trigger senses).
77       * @param ctx variable context that should be passed to the senses
78       * @param engineLog logger to record actions of this executor
79       */
80      SenseListExecutor(Trigger<T> trigger, LapPath senseListPath, VariableContext ctx, EngineLog engineLog) {
81          super(senseListPath, ctx, engineLog);
82  
83          int triggerSenseId = 0;
84          for (Sense sense : trigger) {
85              LapPath triggerSensePath = senseListPath.concat(LapType.SENSE, triggerSenseId++);
86              SenseExecutor senseExecutor = new SenseExecutor(sense, triggerSensePath, ctx, engineLog);
87              sensesExecutors.add(senseExecutor);
88          }
89      }
90  
91      /**
92       * Create an executor without any senses (it will always return
93       * defaultReturn).
94       *
95       * @param senseListPath Path to the parent of all senses. Trigger/goal
96       * itself isn't node (e.g. it is a path to drive that have trigger senses).
97       * @param ctx variable context that should be passed to the senses.
98       * @param log log to write debug info.
99       */
100     SenseListExecutor(LapPath senseListPath, VariableContext ctx, EngineLog log) {
101         super(senseListPath, ctx, log);
102     }
103 
104     /**
105      * Evaluate all senses until first one fails. If no senses were specified,
106      * consider it a fail.
107      *
108      * @param defaultReturn what to return if no senses were specified. In
109      * trigger true, in goal false
110      * @return Result of the senselist. The result is true if none of senses
111      * fails, false if at least one fails.
112      */
113     public TriggerResult fire(IWorkExecutor workExecuter, boolean defaultReturn) {
114         List<SenseResult> senses = new LinkedList<SenseResult>();
115 
116         for (SenseExecutor senseExecutor : sensesExecutors) {
117             defaultReturn = true;
118 
119             SenseResult res = senseExecutor.fire(workExecuter);
120             senses.add(res);
121 
122             if (!res.wasSuccessful()) {
123                 return new TriggerResult(senses, false);
124             }
125         }
126         return new TriggerResult(senses, defaultReturn);
127     }
128 }