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 referenced element 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      /**
88       * XXX: Not implemented, because I don't have a usecase, but interface has it.
89       * 
90       * Finds all actions in the plan with the same name as this sense and changes
91       * their name to newName. } + fire property.
92       * 
93       * @param newName What will be new name of all actions with old name.
94       */
95      @Override
96      public void rename(String newName) throws InvalidNameException, CycleException, DuplicateNameException {
97          throw new UnsupportedOperationException("Not yet implemented");
98      }
99      
100     @Override
101     public boolean moveChild(int newIndex, PoshElement child) {
102         throw new UnsupportedOperationException();
103     }
104 
105     @Override
106     public DataFlavor getDataFlavor() {
107         return dataFlavor;
108     }
109 
110     @Override
111     public LapType getType() {
112         return LapType.ACTION;
113     }
114     
115     /**
116      * Take @source action and set all properties (name, parameters...) to be
117      * same as the @source. All changes will be emitted.
118      *
119      * @param source The source of the data this action will synchronize to.
120      */
121     public void synchronize(TriggeredAction source) throws CycleException {
122         try {
123             this.setActionName(source.getName());
124             Arguments sourceArguments = source.getActionCall().getParameters();
125             setArguments(new Arguments(sourceArguments));
126         } catch (InvalidNameException ex) {
127             throw new FubarException("Name of the source action \"" + source.getName() + "\" is not valid for this action.", ex);
128         }
129     }
130     
131     /**
132      * Action basically consists from
133      */
134     public void setArguments(Arguments newArguments) {
135         String actionName = actionCall.getName();
136         Arguments oldArguments = actionCall.getParameters();
137         this.actionCall = new PrimitiveCall(actionName, newArguments);
138 
139         // TODO: Check that all variables used as values in the newArguments are present in the parameters of parent, use getParentParameters().
140         
141         firePropertyChange(taArgs, oldArguments, newArguments);
142     }
143 
144     /**
145      * Get arguments of this action.
146      *
147      * @return Arguments of the action.
148      */
149     @Override
150     public Arguments getArguments() {
151         return this.actionCall.getParameters();
152     }
153 }