View Javadoc

1   package cz.cuni.amis.pogamut.sposh.elements;
2   
3   import cz.cuni.amis.pogamut.sposh.engine.PoshEngine;
4   import cz.cuni.amis.pogamut.sposh.exceptions.DuplicateNameException;
5   import cz.cuni.amis.pogamut.sposh.exceptions.InvalidNameException;
6   import java.util.ArrayList;
7   import java.util.List;
8   import java.awt.datatransfer.DataFlavor;
9   
10  /**
11   * Drive element (very informative, I know). What is drive? Basically it is a
12   * top node of decision tree. It has a trigger and an action. When trigger is
13   * satisfied, the drive is elegible to be traversed. Action is just a name, it
14   * can be reference (=having same name) to some action, but it can also be
15   * reference to C or AP.
16   * <p/>
17   * In posh it has following syntax(minus variables):
18   * <code>
19   *   (&lt;name&gt; [&lt;trigger&gt;] &lt;name&gt;)
20   * </code> The first name is name of the element and second name is name of the
21   * action.
22   * <p/>
23   * In the past, it used to have this form, but not anymore (none knew how to use
24   * it and no need to waste scarce resources to support unused features.)
25   * <code>
26   *   (&lt;name&gt; [&lt;trigger&gt;] &lt;name&gt; [&lt;freq&gt;] [&lt;comment&gt;])
27   * </code> The drive is elegible for execution if it has satisfied trigger and
28   * it was called less frequently that specified by its frequency ({@link DriveElement#getFreq()
29   * }).
30   *
31   * @see DriveCollection Useful to have an idea what is {@link DriveElement} for.
32   * @author HonzaH
33   */
34  public final class DriveElement extends NamedLapElement<DriveElement, DriveCollection> {
35  
36      /**
37       * Name of the drive. Unique in the DC.
38       */
39      private String name;
40      /**
41       * Trigger of this drive.
42       */
43      private final Trigger<DriveElement> trigger = new Trigger<DriveElement>(this);
44      /**
45       * Action of this drive.
46       */
47      private final TriggeredAction action;
48      /**
49       * If drive is called more frequenctly than specified by this frequency, it
50       * is not elegible to be processed during evaluation.
51       *
52       * @deprecated XXX: Not used in editor, maybe remove later
53       */
54      @Deprecated
55      private Freq freq;
56      /**
57       * Comment about this drive element.
58       *
59       * @deprecated XXX: Not used in editor, maybe remove later
60       */
61      @Deprecated
62      private String comment;
63      /**
64       * Property name for name of a drive
65       */
66      public static final String deName = "deName";
67      /**
68       * Data flavor of drive, used in drag-and-drop
69       */
70      public static final DataFlavor dataFlavor = new DataFlavor(DriveElement.class, "drive-element");
71  
72      /**
73       * Create a new DriveElement
74       *
75       * @param name name of drive element
76       * @param triggerSenses Senses that will form the trigger.
77       * @param actionCall action that will be called if driver is eligible and
78       * its trigger is satisfied.
79       */
80      DriveElement(String name, List<Sense> triggerSenses, PrimitiveCall actionCall, Freq freq, String comment) {
81          assert name != null;
82          this.name = name;
83  
84          assert freq != null;
85          this.freq = freq;
86  
87          assert comment != null;
88          this.comment = comment;
89  
90          for (Sense triggerSense : triggerSenses) {
91              assert !triggerSense.isChildOfParent();
92              trigger.add(triggerSense);
93          }
94  
95          this.action = LapElementsFactory.createAction(actionCall);
96          this.action.setParent(this);
97      }
98  
99      /**
100      * Get trigger of this drive.
101      */
102     public Trigger<DriveElement> getTrigger() {
103         return trigger;
104     }
105 
106     /**
107      * Get action of this drive (will be performed if elegible, has satisfied
108      * trigger and highest priority).
109      *
110      * @return action of this drive
111      */
112     public TriggeredAction getAction() {
113         return action;
114     }
115 
116     @Override
117     public String toString() {
118         StringBuilder sb = new StringBuilder();
119 
120         sb.append('(');
121         sb.append(name);
122         if (!trigger.isEmpty()) {
123             sb.append(" (trigger ");
124             sb.append(trigger.toString());
125             sb.append(')');
126         }
127         sb.append(' ');
128         sb.append(this.action.toString());
129         sb.append(')');
130 
131         return sb.toString();
132     }
133 
134     @Override
135     public List<PoshElement> getChildDataNodes() {
136         List<PoshElement> children = new ArrayList<PoshElement>();
137         children.addAll(trigger);
138         children.add(this.action);
139 
140         return children;
141     }
142 
143     @Override
144     public String getName() {
145         return name;
146     }
147 
148     /**
149      * Set name of the drive to new name.
150      *
151      * @param newName New name of the drive.
152      * @throws InvalidNameException If name doesn't match {@link PoshDummyElement#IDENT_PATTERN}
153      * regexp.
154      */
155     public void setDriveName(String newName) throws InvalidNameException, DuplicateNameException {
156         newName = newName.trim();
157         if (!newName.matches(IDENT_PATTERN)) {
158             throw InvalidNameException.create(newName);
159         }
160         DriveCollection dc = getParent();
161         for (DriveElement drive : dc.getDrives()) {
162             if (drive.getName().equals(newName) && drive != this) {
163                 throw new DuplicateNameException("There already is a drive with name " + newName);
164             }
165         }
166         
167         
168         String oldName = this.name;
169         this.name = newName;
170 
171         firePropertyChange(deName, oldName, newName);
172     }
173 
174     @Override
175     public boolean moveChild(int newIndex, PoshElement child) {
176         throw new UnsupportedOperationException();
177     }
178 
179     @Override
180     public DataFlavor getDataFlavor() {
181         return dataFlavor;
182     }
183 
184     @Override
185     public LapType getType() {
186         return LapType.DRIVE_ELEMENT;
187     }
188 
189     /**
190      * Get how frequent can this drive be executed. Basically {@link PoshEngine}
191      * in each evaluation selects the drive with highest priority that has
192      * satisfied trigger and is being called less frequently, than specified by
193      * the frequency of the drive element.
194      *
195      * @return maximal frequency with which this drive can be called.
196      * @deprecated Part of original posh, not supported in editor.
197      */
198     @Deprecated
199     public Freq getFreq() {
200         return freq;
201     }
202 
203     /**
204      * Get comment of this drive.
205      *
206      * @return comment of the drive
207      * @deprecated Not supported in editor
208      */
209     @Deprecated
210     public String getComment() {
211         return comment;
212     }
213 }