View Javadoc

1   package cz.cuni.amis.pogamut.sposh.elements;
2   
3   import java.util.List;
4   import java.awt.datatransfer.DataFlavor;
5   import java.util.Collections;
6   import java.util.HashSet;
7   import javax.swing.JOptionPane;
8   
9   /**
10   * Triggered action is basically identifier, string that maches some function specified
11   * outside the POSH plan. It can also be a reference to Action pattern or competence 
12   * (if action and reactive plan has same name). Cycles are not allowed.
13   *
14   * @author Honza
15   */
16  public class TriggeredAction extends NamedLapElement implements Comparable<TriggeredAction> {
17  	public static final String taName = "taName";
18  	private Sense.SenseCall actionCall;
19  
20  	public TriggeredAction(String actionName) {
21  		this.actionCall = new Sense.SenseCall(actionName);
22  	}
23  
24  	public TriggeredAction(Sense.SenseCall actionCall) {
25  		this.actionCall = actionCall;
26  	}
27  
28  	@Override
29  	public List<PoshElement> getChildDataNodes() {
30  		return Collections.<PoshElement>emptyList();
31  	}
32  
33  	@Override
34  	public String toString() {
35  		return actionCall.toString();
36  	}
37      @Override
38  	public String getName() {
39  		return actionCall.getName();
40  	}
41  
42          public Sense.SenseCall getActionCall() {
43              return actionCall;
44          }
45  
46  	/**
47  	 * Does this action has a cycle?
48  	 * Cycle = competence with name X has action with name X or similar situations.
49  	 *
50  	 * @return true if it has, false if it doesn't
51  	 */
52  	protected boolean detectCycle() {
53  		PoshPlan root = this.getRootNode();
54  		if (root == null) {
55  			throw new RuntimeException("Missing root node.");
56  		}
57  
58  		HashSet<String> connected = new HashSet<String>();
59  
60  		connected.add(getName());
61  
62  		// now go through whole set and find AP or Competence
63  		int addedItems;
64  		do {
65  			addedItems = 0;
66  			String[] connectedArray = connected.toArray(new String[]{});
67  			
68  			for (String processedAction : connectedArray) {
69  				List<String> compositeChildren = root.getAPorCompActions(processedAction);
70  				// and if it exists, add all
71  				for (String compositeChild : compositeChildren) {
72  					if (this.getName().equals(compositeChild)) {
73  						return true;
74  					}
75  
76  					if (!connected.contains(compositeChild)) {
77  						connected.add(compositeChild);
78  						addedItems++;
79  					}
80  				}
81  			}
82  		} while (addedItems > 0);
83  
84  		return false;
85  	}
86  
87  	/**
88  	 * Set action function. It has to match with IDENT_PATTERN and it can't
89  	 * cause cycle. If cycle is detected, messagebox appears.
90  	 * 
91  	 * @param actionName
92  	 */
93  	public void setActionName(String actionName) {
94  		actionName = actionName.trim();
95  
96  		if (!actionName.matches(IDENT_PATTERN)) {
97  			throw new IllegalArgumentException("Invalid name.");
98  		}
99  
100 		String oldName = this.getName();
101 		this.actionCall = new Sense.SenseCall(actionName, actionCall.getParameters());
102 
103 		if (getRootNode() != null && getRootNode().isCycled()) {
104 			this.actionCall = new Sense.SenseCall(oldName, actionCall.getParameters());
105 
106 			JOptionPane.showMessageDialog(
107                                 null,
108                                 "This namechange is causing cycle, please use another name.",
109                                 "Cycle detected", JOptionPane.ERROR_MESSAGE);
110 		} else {
111                         // Don't use old name because it doesn't fire when oldname and
112                         // new name are same, but I am relying on firing after added competence or
113                         // action pattern.
114 			firePropertyChange(taName, null, actionName);
115 		}
116 	}
117 
118 	@Override
119 	public boolean moveChild(PoshElement child, int relativePosition) {
120 		return false;
121 	}
122 	
123 	public static final DataFlavor dataFlavor = new DataFlavor(TriggeredAction.class, "triggered_action");
124 
125 	@Override
126 	public DataFlavor getDataFlavor() {
127 		return dataFlavor;
128 	}
129 
130 	@Override
131 	public void addChildDataNode(PoshElement newChild) {
132 		throw new RuntimeException("Class " + newChild.getClass().getSimpleName() + " not accepted.");
133 	}
134 
135 	@Override
136 	public void neutralizeChild(PoshElement childNode) {
137 		throw new RuntimeException("TriggeredActions doesn't have children.");
138 	}
139 
140     @Override
141     public int compareTo(TriggeredAction o) {
142         return this.getName().compareTo(o.getName());
143     }
144 
145 }