001: package org.osbl.agent.gui;
002:
003: import java.awt.GridBagConstraints;
004: import java.awt.event.ActionEvent;
005: import java.awt.event.ActionListener;
006: import java.util.ArrayList;
007: import java.util.HashMap;
008: import java.util.List;
009: import java.util.Map;
010:
011: import org.concern.Controller;
012: import org.concern.ControllerException;
013: import org.concern.ControllerLookup;
014: import org.concern.UnknownSubjectException;
015: import org.concern.Work;
016: import org.concern.model.Activity;
017: import org.concern.model.AsynchronousActivity;
018: import org.concern.model.Process;
019: import org.osbl.agent.logic.AgentSystem;
020: import org.osbl.agent.logic.RuntimeContext;
021: import org.osbl.agent.logic.TaskRuntimeContext;
022: import org.osbl.agent.model.Rule;
023: import org.osbl.agent.model.RuleContext;
024: import org.osbl.client.wings.concern.TaskEditor;
025: import org.osbl.client.wings.concern.TaskForm;
026: import org.osbl.client.wings.concern.TaskList;
027: import org.osbl.client.wings.form.NestedObjectForm;
028: import org.osbl.client.wings.shell.Client;
029: import org.wings.SComboBox;
030: import org.wings.SComponent;
031: import org.wings.SConstants;
032: import org.wings.SDimension;
033: import org.wings.SLabel;
034: import org.wings.SListCellRenderer;
035: import org.wings.SPanel;
036:
037: /**
038: * The Class TaskDesignContext.
039: *
040: * @author Sebastian Nozzi.
041: */
042: public class TaskDesignContext extends SubjectDesignContext {
043:
044: /** The activity combo. */
045: SComboBox activityComboFilter;
046:
047: /** The activity combo specifier. */
048: SComboBox activityComboSpecifier;
049:
050: /** The old process combo index. */
051: int oldProcessComboIndex;
052:
053: /**
054: * Instantiates a new task design context.
055: *
056: * @param taskEditor the task editor
057: */
058: public TaskDesignContext(TaskEditor taskEditor) {
059: super (taskEditor);
060:
061: // We need THE AgentSystem instance for accessing the Rules repository
062: agentSystem = AgentSystem.getSingletonInstance();
063:
064: ruleEditorPanel = new RuleEditorPanel(this );
065: sidePanel = new SidePanel(this );
066: }
067:
068: /* (non-Javadoc)
069: * @see org.osbl.agent.gui.DesignContext#getAgentSidePanel()
070: */
071: public SidePanel getAgentSidePanel() {
072: return sidePanel;
073: }
074:
075: /* (non-Javadoc)
076: * @see org.osbl.agent.gui.DesignContext#getRuleEditorPanel()
077: */
078: public RuleEditorPanel getRuleEditorPanel() {
079: return ruleEditorPanel;
080: }
081:
082: /**
083: * Update activities.
084: *
085: * @param processList the process list
086: * @param activityCombo the activity combo
087: * @param addAny the add any
088: */
089: protected void updateActivities(List<Process> processList,
090: SComboBox activityCombo, boolean addAny) {
091:
092: // Remove all activities already there.
093: activityCombo.removeAllItems();
094:
095: if (addAny) {
096: // First item is reserved for the wildcard "all"
097: activityCombo.addItem(msg("all"));
098: }
099:
100: // For each selected processes (maybe one, maybe many)
101: for (Process process : processList) {
102:
103: // Get the activities and add them to the activity combo
104: for (Object act : process.getActivities()) {
105:
106: // Only add AsynchronousActivities (those that require
107: // user intervention and for which we are offering Agents)
108: if (act instanceof AsynchronousActivity)
109: activityCombo.addItem(act);
110: }
111: }
112: }
113:
114: /**
115: * Adds the process activity combos.
116: *
117: * @param processCombo the process combo
118: * @param activityCombo the activity combo
119: * @param target the target
120: */
121: protected void addProcessActivityCombos(SComboBox processCombo,
122: SComboBox activityCombo, SPanel target) {
123:
124: GridBagConstraints constraints = new GridBagConstraints();
125:
126: super .addProcessCombo(processCombo, target);
127:
128: // Add the label for the activity combo
129: constraints.gridx = 0;
130: constraints.gridy = 1;
131: constraints.gridwidth = 1;
132: target.add(new SLabel(msg("activity") + ":"), constraints);
133:
134: // Add the activity combo
135: constraints.gridx = 1;
136: constraints.gridy = 1;
137: constraints.gridwidth = constraints.REMAINDER;
138: target.add(activityCombo, constraints);
139: activityCombo.setHorizontalAlignment(SConstants.LEFT_ALIGN);
140:
141: activityCombo.setRenderer(new SListCellRenderer() {
142:
143: SLabel label = new SLabel();
144:
145: public SComponent getListCellRendererComponent(
146: SComponent list, java.lang.Object value,
147: boolean isSelected, int index) {
148:
149: String result = value.toString();
150:
151: // For the special case of "<all>", value is a String and not an Activity
152: if (value instanceof Activity) {
153:
154: result = ((Activity) value).getName();
155:
156: // Since an Activity doesn't know its parent Process, we have to look it up
157: for (Process process : agentSystem.getProcessList()) {
158: if (process.getActivities().contains(value)) {
159: // Once found, we can construct the key to ask for a translation
160: // of the Activity
161: result = Client
162: .getInstance()
163: .getResourceProvider()
164: .getMessage(
165: "process."
166: + process.getName()
167: + "."
168: + ((Activity) value)
169: .getName());
170: break;
171: }
172: }
173: }
174:
175: label.setText(result);
176:
177: return label;
178: }
179: });
180:
181: }
182:
183: /* (non-Javadoc)
184: * @see org.osbl.agent.gui.SubjectDesignContext#recomputeCurrentRules()
185: */
186: public void recomputeCurrentRules() {
187:
188: currentRules.clear();
189:
190: // If a specific activity is selected (index 0 is for "all")...
191: if (activityComboFilter.getSelectedIndex() != 0) {
192:
193: // We'll want to find the parentWindow Process for the Activity
194: // here
195: Process parentProcess = null;
196: // Get the selected activity (which IS a valid Activity, since
197: // idx!=0)
198: Activity act = (Activity) activityComboFilter
199: .getSelectedItem();
200:
201: // If the processCombo is in "all" (index 0)
202: if (processComboFilter.getSelectedIndex() == 0) {
203: // Look for the parentWindow Process to which the Activity
204: // belongs
205: for (Process process : agentSystem.getProcessList()) {
206: if (process.getActivities().contains(act)) {
207: // Parent found!
208: parentProcess = process;
209: break;
210: }
211: }
212: // Otherwise finding the parentWindow process is
213: // straightforward...
214: } else {
215: // ... get it from the combo box!
216: parentProcess = getSelectedProcessList(
217: processComboFilter, true).get(0);
218: }
219:
220: // At this point we have one Process/Activity pair, so...
221:
222: // ...re-compute rules for our Process/Activity pair.
223: recomputeCurrentRules(parentProcess, act);
224: // Activity combo was on "all"...
225: } else {
226: // Get list of selected Process (may be one or many) and
227: // iterate over them/it
228: for (Process proc : getSelectedProcessList(
229: processComboFilter, true)) {
230: // For each Process get its Activities...
231: for (Object act : proc.getActivities()) {
232: // Re-compute rules for each Process/Activity pair.
233: recomputeCurrentRules(proc, (Activity) act);
234: }
235: }
236: }
237: }
238:
239: /**
240: * Recompute current rules.
241: *
242: * @param proc the proc
243: * @param act the act
244: */
245: private void recomputeCurrentRules(Process proc, Activity act) {
246:
247: List<Rule> rulesToAdd = new ArrayList<Rule>();
248:
249: // Now filter out non-corresponding Rules...
250: for (Rule aRule : agentSystem.getRules()) {
251:
252: if (belongsToDesignContext(aRule)) {
253: String processName = (String) aRule
254: .getMetaInformation().get(
255: RuleContext.PROCESS_NAME_KEY);
256: String activityName = (String) aRule
257: .getMetaInformation().get(
258: RuleContext.ACTIVITY_NAME_KEY);
259:
260: if (aRule.isPublic() == false
261: && aRule.getCreatorUser().equals(
262: DesignContext.getCurrentUser()) == false) {
263: continue;
264: }
265:
266: if (processName.equals(proc.getName())
267: && activityName.equals(act.getName())) {
268: rulesToAdd.add(aRule);
269: }
270: }
271: }
272:
273: currentRules.addAll(rulesToAdd);
274: }
275:
276: /* (non-Javadoc)
277: * @see org.osbl.agent.gui.SubjectDesignContext#addSideFilters(org.osbl.agent.gui.SidePanel)
278: */
279: public void addSideFilters(final SidePanel targetPanel) {
280:
281: // This two combos will let the user specify the process/activity
282: // pair.
283: processComboFilter = new SComboBox();
284: activityComboFilter = new SComboBox();
285:
286: activityComboFilter.setPreferredSize(new SDimension("140px",
287: SDimension.AUTO));
288: processComboFilter.setPreferredSize(new SDimension("140px",
289: SDimension.AUTO));
290:
291: addProcessActivityCombos(processComboFilter,
292: activityComboFilter, targetPanel);
293:
294: populateProcessCombo(processComboFilter, true);
295:
296: // Force the activities combo to update
297: updateActivities(agentSystem.getProcessList(),
298: activityComboFilter, true);
299:
300: // Selecting another Process causes Activities and Rules to be
301: // updated.
302: processComboFilter.addActionListener(new ActionListener() {
303: public void actionPerformed(ActionEvent e) {
304: updateActivities(getSelectedProcessList(
305: processComboFilter, true), activityComboFilter,
306: true);
307: recomputeCurrentRules();
308: targetPanel.refreshTable();
309: }
310: });
311:
312: // Selecting another Activity just causes Rules to be udated.
313: activityComboFilter.addActionListener(new ActionListener() {
314: public void actionPerformed(ActionEvent e) {
315: recomputeCurrentRules();
316: targetPanel.refreshTable();
317: }
318: });
319: }
320:
321: /* (non-Javadoc)
322: * @see org.osbl.agent.gui.SubjectDesignContext#addSpecifierComponents(org.osbl.agent.gui.RuleEditorPanel)
323: */
324: public void addSpecifierComponents(RuleEditorPanel targetPanel) {
325: // This two combos will let the user specify the process/activity
326: // pair.
327: processComboSpecifier = new SComboBox();
328: activityComboSpecifier = new SComboBox();
329:
330: addProcessActivityCombos(processComboSpecifier,
331: activityComboSpecifier, targetPanel.contentPane);
332:
333: populateProcessCombo(processComboSpecifier, false);
334:
335: // Force the activities combo to update
336: updateActivities(getSelectedProcessList(processComboSpecifier,
337: false), activityComboSpecifier, false);
338:
339: updateBeanMeta();
340:
341: oldProcessComboIndex = processComboSpecifier.getSelectedIndex();
342:
343: processComboSpecifier
344: .addActionListener(new ProcessChangeListener() {
345: protected void processChanged() {
346: // Force the activities combo to update
347: updateActivities(getSelectedProcessList(
348: processComboSpecifier, false),
349: activityComboSpecifier, false);
350: }
351: });
352: }
353:
354: /* (non-Javadoc)
355: * @see org.osbl.agent.gui.SubjectDesignContext#enableSpecifierComponents(boolean)
356: */
357: public void enableSpecifierComponents(boolean enabled) {
358: super .enableSpecifierComponents(enabled);
359: activityComboSpecifier.setEnabled(enabled);
360: }
361:
362: /**
363: * Gets the specified activity.
364: *
365: * @return the specified activity
366: */
367: public Activity getSpecifiedActivity() {
368: return (Activity) activityComboSpecifier.getSelectedItem();
369: }
370:
371: /* (non-Javadoc)
372: * @see org.osbl.agent.gui.SubjectDesignContext#populateRule(org.osbl.agent.model.Rule)
373: */
374: public void populateRule(Rule editedRule) {
375:
376: Activity activity = getSpecifiedActivity();
377:
378: editedRule.getMetaInformation().put(
379: RuleContext.ACTIVITY_NAME_KEY, activity.getName());
380:
381: super .populateRule(editedRule);
382: }
383:
384: /* (non-Javadoc)
385: * @see org.osbl.agent.gui.SubjectDesignContext#changeSpecifiers(org.osbl.agent.model.Rule)
386: */
387: public void changeSpecifiers(Rule rule) {
388:
389: super .changeSpecifiers(rule);
390:
391: String ruleActivityImpl = (String) rule.getMetaInformation()
392: .get(RuleContext.ACTIVITY_NAME_KEY);
393:
394: setConfirmProcessChange(false);
395:
396: // It CAN be NULL for new Rules.
397: if (ruleActivityImpl != null) {
398: for (int i = 0; i < activityComboSpecifier.getItemCount(); i++) {
399: Activity comboActivity = (Activity) activityComboSpecifier
400: .getItemAt(i);
401: if (ruleActivityImpl.equals(comboActivity.getName()))
402: activityComboSpecifier.setSelectedIndex(i);
403: }
404: }
405:
406: setConfirmProcessChange(true);
407: }
408:
409: /* (non-Javadoc)
410: * @see org.osbl.agent.gui.SubjectDesignContext#getRuntimeObjectClass()
411: */
412: public Class getRuntimeObjectClass() {
413: return Work.class;
414: }
415:
416: /* (non-Javadoc)
417: * @see org.osbl.agent.gui.SubjectDesignContext#getRuntimeContext()
418: */
419: public RuntimeContext getRuntimeContext() {
420:
421: return new TaskRuntimeContext();
422: }
423:
424: /* (non-Javadoc)
425: * @see org.osbl.agent.gui.SubjectDesignContext#getPreviewControllerInstance()
426: */
427: public PreviewController getPreviewControllerInstance() {
428:
429: PreviewController result = new PreviewController(this ) {
430:
431: TaskForm taskForm = new TaskForm();
432:
433: public NestedObjectForm getObjectForm() {
434: return taskForm;
435: }
436:
437: public Object getListObject(int rowIdx) {
438: Object result = ((TaskList) designContext
439: .getObjectEditor().getList()).getRow(rowIdx);
440: return result;
441: }
442:
443: public void populateForm(Object targetObject) {
444: taskForm.setTask((Work) targetObject);
445: taskForm.getEnvironment().setActive(true);
446: taskForm.setObject(targetObject);
447: }
448:
449: protected void postUpdateActions(Object targetObject) {
450:
451: Work task = (Work) targetObject;
452: Controller controller = getController(targetObject);
453:
454: Map<String, String> annotations = new HashMap<String, String>();
455: annotations.put("user", DesignContext.getCurrentUser());
456:
457: try {
458: controller.complete(task.getSubjectId(), task
459: .getActivity(), annotations);
460: controller.announceSubject(task.getSubjectId());
461: } catch (UnknownSubjectException e) {
462: // TODO Auto-generated catch block
463: e.printStackTrace();
464: } catch (ControllerException e) {
465: // TODO Auto-generated catch block
466: e.printStackTrace();
467: }
468: }
469:
470: protected Controller getController(Object targetObject) {
471: Work task = (Work) targetObject;
472: return ControllerLookup.getInstance().getController(
473: task.getProcess());
474: }
475:
476: public Object getSubjectInstance(Object targetObject) {
477: return ((Work) targetObject).getSubject();
478: }
479:
480: };
481:
482: return result;
483: }
484:
485: }
|