View Javadoc

1   package cz.cuni.amis.pogamut.sposh.elements;
2   
3   import cz.cuni.amis.pogamut.sposh.exceptions.CycleException;
4   import cz.cuni.amis.pogamut.sposh.exceptions.DuplicateNameException;
5   import cz.cuni.amis.pogamut.sposh.exceptions.FubarException;
6   import cz.cuni.amis.pogamut.sposh.exceptions.InvalidNameException;
7   import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
8   import java.awt.datatransfer.DataFlavor;
9   import java.util.Collections;
10  import java.util.List;
11  
12  /**
13   * Triggered action is basically a call of some other entity that is supposed to
14   * be executed. The other entity can be action (through {@link IWorkExecutor}, {@link Competence}
15   * or {@link ActionPattern}. The call needs name of a callee and possibly some
16   * arguments to pass.
17   * <p/>
18   * How is the target determined? Engine takes the name and checks if there is a {@link Competence}
19   * or {@link ActionPattern} with same name (names of all C and AP are unique,
20   * otherwise they get {@link DuplicateNameException}). If there is, the action
21   * will execute the found C/AP. If there is no such C/AP, it assumes that is is
22   * a name of an action so it tries to use {@link IWorkExecutor}. If that fails,
23   * stop the bot.
24   * <p/>
25   * Note that we do not allow cycles (thx to {@link CycleException}).
26   *
27   * @author HonzaH
28   */
29  public class TriggeredAction extends PoshDummyElement implements IReferenceElement, INamedElement {
30  
31      private PrimitiveCall actionCall;
32      public static final DataFlavor dataFlavor = new DataFlavor(TriggeredAction.class, "triggered_action");
33      public static final String taName = "taName";
34      public static final String taArgs = "taAruments";
35  
36      TriggeredAction(String actionName) {
37          this.actionCall = new PrimitiveCall(actionName);
38      }
39  
40      TriggeredAction(PrimitiveCall actionCall) {
41          this.actionCall = actionCall;
42      }
43  
44      @Override
45      public List<PoshElement> getChildDataNodes() {
46          return Collections.<PoshElement>emptyList();
47      }
48  
49      @Override
50      public String toString() {
51          return actionCall.toString();
52      }
53  
54      @Override
55      public String getName() {
56          return actionCall.getName();
57      }
58  
59      public PrimitiveCall getActionCall() {
60          return actionCall;
61      }
62  
63      /**
64       * Set name of the action.
65       *
66       * @param newName New name of an action
67       * @throws InvalidNameException If name is not valid
68       * @throws CycleException if namechange would cause a cycle.
69       */
70      public void setActionName(String newName) throws InvalidNameException, CycleException {
71          newName = newName.trim();
72  
73          if (!newName.matches(IDENT_PATTERN)) {
74              throw InvalidNameException.create(newName);
75          }
76  
77          String oldName = this.getName();
78          this.actionCall = new PrimitiveCall(newName, actionCall.getParameters());
79  
80          if (getRootNode() != null && getRootNode().isCycled()) {
81              this.actionCall = new PrimitiveCall(oldName, actionCall.getParameters());
82              throw CycleException.createFromName(newName);
83          }
84          firePropertyChange(taName, oldName, newName);
85      }
86  
87      @Override
88      public boolean moveChild(int newIndex, PoshElement child) {
89          throw new UnsupportedOperationException();
90      }
91  
92      @Override
93      public DataFlavor getDataFlavor() {
94          return dataFlavor;
95      }
96  
97      @Override
98      public LapType getType() {
99          return LapType.ACTION;
100     }
101     
102     /**
103      * Take @source action and set all properties (name, parameters...) to be
104      * same as the @source. All changes will be emitted.
105      *
106      * @param source The source of the data this action will synchronize to.
107      */
108     public void synchronize(TriggeredAction source) throws CycleException {
109         try {
110             this.setActionName(source.getName());
111             Arguments sourceArguments = source.getActionCall().getParameters();
112             setArguments(new Arguments(sourceArguments));
113         } catch (InvalidNameException ex) {
114             throw new FubarException("Name of the source action \"" + source.getName() + "\" is not valid for this action.", ex);
115         }
116     }
117 
118     /**
119      * Get parameters that can be used as arguments of the action call. The
120      * parameters are specified in after the "vars" keyword in the parent.
121      *
122      * @return List of parameters. If element doesn't have parameters, null.
123      */
124     private FormalParameters getElementParameters(PoshElement element) {
125         assert element != null;
126         
127         if (element instanceof DriveElement) {
128             return new FormalParameters();
129         }
130         if (element instanceof CompetenceElement) {
131             CompetenceElement cel = (CompetenceElement) element;
132             Competence competence = cel.getParent();
133             return competence.getParameters();
134         }
135         if (element instanceof ActionPattern) {
136             ActionPattern ap = (ActionPattern) element;
137             return ap.getParameters();
138         }
139         return null;
140     }
141     
142     /**
143      * Action basically consists from
144      */
145     public void setArguments(Arguments newArguments) {
146         String actionName = actionCall.getName();
147         Arguments oldArguments = actionCall.getParameters();
148         this.actionCall = new PrimitiveCall(actionName, newArguments);
149 
150         // TODO: Check that all variables used as values in the newArguments are present in the parameters of parent, use getParentParameters().
151         
152         firePropertyChange(taArgs, oldArguments, newArguments);
153     }
154 
155     /**
156      * Get arguments of this action.
157      *
158      * @return Arguments of the action.
159      */
160     @Override
161     public Arguments getArguments() {
162         return this.actionCall.getParameters();
163     }
164 }