View Javadoc

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