001: package org.obe.client;
002:
003: import org.apache.log4j.Level;
004: import org.apache.log4j.Logger;
005: import org.obe.client.api.ClientConfig;
006: import org.obe.client.api.WMClient;
007: import org.obe.client.api.WMClientFactory;
008: import org.obe.client.api.model.OBEWorkItem;
009: import org.obe.client.api.model.WMAAuditEntryAttributes;
010: import org.obe.client.api.tool.ToolInvocation;
011: import org.obe.util.CommonConfig;
012: import org.obe.util.FormattingPrintWriter;
013: import org.obe.xpdl.model.data.FormalParameter;
014: import org.obe.xpdl.model.data.ParameterMode;
015: import org.obe.xpdl.model.pkg.XPDLPackage;
016: import org.obe.xpdl.model.workflow.WorkflowProcess;
017: import org.wfmc.audit.WMAAuditEntry;
018: import org.wfmc.audit.WMAAuditEntryIterator;
019: import org.wfmc.wapi.*;
020:
021: import java.io.*;
022: import java.lang.reflect.InvocationTargetException;
023: import java.lang.reflect.Method;
024: import java.util.*;
025:
026: /**
027: * @author Adrian Price
028: */
029: public abstract class AbstractCLClient {
030: private static final int BUF_LEN = 4096;
031: protected static final Object[] PRINT_LAST_EXCEPTION = { "E",
032: "Print Last Exception", "showLastException" };
033: protected static final Object[] MENU = { "M", "Redisplay menu",
034: "redisplayMenu" };
035: protected static final Object[] BACK = { "Q",
036: "Back to previous menu", null };
037: protected static final String UNDERLINE = "-----------------------------------------------------------------------------";
038: private static final String JNDI_FACTORY_PROPERTY = "java.naming.factory.initial";
039: private static final String JNDI_FACTORY_DEFAULT = "org.jnp.interfaces.NamingContextFactory";
040: protected static final int[] PROC_DEF_TABS = { 25, 50, 70, 79 };
041: protected static final String[] PROC_DEF_FIELDS = {
042: "processDefinitionId", "packageId", "name", "state" };
043: protected static final int[] PROC_INST_TABS = { 20, 40, 50, 79 };
044: protected static final String[] PROC_INST_FIELDS = {
045: "processInstanceId", "name", "priority", "state" };
046: protected static final int[] ACTIVITY_INSTANCE_TABS = { 25, 50, 60,
047: 79 };
048: protected static final String[] ACTIVITY_INSTANCE_FIELDS = {
049: "activityInstanceId", "name", "priority", "state" };
050: private static final int[] WORKITEM_TABS = { 12, 32, 41, 56, 68, 79 };
051: private static final String[] WORKITEM_FIELDS = { "workItemId",
052: "name", "priority", "state", "participant", "performer" };
053: private static final int[] ATTR_INST_TABS = { 25, 30, 79 };
054: private static final String[] ATTR_INST_FIELDS = { "name", "type",
055: "value" };
056: private static final int[] AUDIT_ENTRY_TABS = { 12, 22, 36, 50, 60,
057: 70, 80 };
058: private static final String[] AUDIT_ENTRY_FIELDS = { "procDefId",
059: "actDefId", "procState", "event", "iPrInstId", "cPrInstId",
060: "actInstId" };
061: private static final int SYSTEM_IN_WAIT = 2000;
062:
063: protected boolean _connected;
064: protected String _hostUrl;
065: protected String _userId;
066: protected String _password;
067: protected WMClient _client;
068: protected BufferedReader _stdin;
069: protected FormattingPrintWriter _stdout;
070: protected String _pkgId;
071: protected String _procDefId;
072: protected String _procInstId;
073: protected String _actInstId;
074: protected String _workItemId;
075: protected String _performerId;
076: protected String _file;
077: protected String _attrName;
078: protected String _protocol = CommonConfig.getProtocol();
079: protected String _newState;
080: protected Throwable _lastException;
081: protected String _logger = "org.obe";
082: protected String _filtExpr;
083: protected Map _attrValues = new HashMap();
084:
085: private static final class AttributeComparator implements
086: Comparator {
087: public int compare(Object o1, Object o2) {
088: return ((WMAttribute) o1).getName().compareTo(
089: ((WMAttribute) o2).getName());
090: }
091: }
092:
093: private static List iteratorToList(WMIterator attrs) {
094: List list = new ArrayList(attrs.getCount());
095: while (attrs.hasNext())
096: list.add(attrs.next());
097: return list;
098: }
099:
100: private static String truncate(String s, int max) {
101: if (s.length() > max)
102: s = s.substring(0, max - 3) + "...";
103: return s;
104: }
105:
106: protected static String readFile(String fileName)
107: throws IOException {
108:
109: Reader reader = null;
110: try {
111: reader = new FileReader(fileName);
112: StringBuffer sbuf = new StringBuffer();
113: char[] cbuf = new char[BUF_LEN];
114: int offset = 0, count;
115: do {
116: count = reader.read(cbuf, offset, cbuf.length);
117: if (count > 0)
118: sbuf.append(cbuf, 0, count);
119: } while (count > 0);
120: return sbuf.toString();
121: } finally {
122: if (reader != null)
123: reader.close();
124: }
125: }
126:
127: protected static void writeFile(String fileName, String xpdl)
128: throws IOException {
129:
130: Writer writer = null;
131: try {
132: writer = new FileWriter(fileName);
133: writer.write(xpdl);
134: } finally {
135: if (writer != null)
136: writer.close();
137: }
138: }
139:
140: protected AbstractCLClient(String[] args, String title) {
141: _hostUrl = ClientConfig.getServerHostURL();
142: _userId = CommonConfig.getPrincipal();
143: _password = CommonConfig.getCredentials();
144: if (args.length > 0) {
145: _hostUrl = args[0];
146: if (args.length > 1) {
147: _userId = args[1];
148: if (args.length > 2)
149: _password = args[2];
150: }
151: }
152:
153: // Create an input stream to communicate with the user.
154: _stdin = new BufferedReader(new InputStreamReader(System.in));
155: _stdout = new FormattingPrintWriter(System.out, true);
156:
157: // Display Tool Title
158: _stdout.println("\n--- " + title + " ---");
159: }
160:
161: /**
162: * Displays and executes a menu.
163: *
164: * @param title The menu title
165: * @param menu The menu definition. <em>N.B. action methods provided by
166: * subclasses must be <code>public</code></em>.
167: * @param main <code>true</code> if this is the main menu.
168: */
169: protected void doMenu(String title, Object[][] menu, boolean main) {
170: synchronized (System.in) {
171: Map actions = new HashMap();
172: StringBuffer sb = new StringBuffer(menu.length);
173: for (int i = 0; i < menu.length; i++) {
174: Object mnemonic = menu[i][0];
175: sb.append(mnemonic);
176: Object action = menu[i][2];
177: if (action instanceof String)
178: action = findMethod((String) action);
179: actions.put(mnemonic, action);
180: }
181: String choices = sb.toString();
182:
183: while (true) {
184: try {
185: String mnemonic;
186:
187: _stdout.clearTabs();
188: _stdout.println("\n--- " + title + " ---");
189: _stdout.println("\nEnter choice:");
190: for (int i = 0; i < menu.length; i++)
191: _stdout.println(menu[i][0] + ") " + menu[i][1]);
192:
193: // Get the user's selection.
194: mnemonic = getChoice(choices);
195:
196: for (int i = 0; i < menu.length; i++) {
197: Object[] entry = menu[i];
198: if (entry[0].equals(mnemonic)) {
199: Object action = actions.get(mnemonic);
200: if (action == null) {
201: return;
202: } else if (action instanceof Method) {
203: if (!_connected && !main) {
204: _stdout
205: .println("\007*** Not connected");
206: break;
207: }
208: // Cast required to suppress JDK1.5 varargs compiler warning.
209: ((Method) action).invoke(this ,
210: (Object[]) null);
211: } else {
212: doMenu((String) entry[1],
213: (Object[][]) action, false);
214: }
215: }
216: }
217: } catch (Exception e) {
218: Throwable t = e;
219: if (e instanceof InvocationTargetException)
220: t = ((InvocationTargetException) e)
221: .getTargetException();
222: _lastException = t;
223: _stdout.println("\007*** Caught exception: " + t);
224: }
225: }
226: }
227: }
228:
229: private Method findMethod(String name) {
230: Class cl = getClass();
231: Method method = null;
232: while (method == null) {
233: try {
234: method = cl.getDeclaredMethod(name, null);
235: } catch (NoSuchMethodException e) {
236: cl = cl.getSuperclass();
237: if (cl == null) {
238: e.printStackTrace();
239: System.exit(1);
240: }
241: }
242: }
243: return method;
244: }
245:
246: protected void setLoggingLevel() throws IOException {
247: _logger = prompt("Enter logger name", _logger);
248: Logger logger = Logger.getLogger(_logger);
249: Level level = logger.getLevel();
250: String logLevel = prompt(
251: "Enter log level (DEBUG|INFO|WARNING|ERROR|FATAL)",
252: (level == null ? Level.DEBUG : level).toString());
253: level = Level.toLevel(logLevel);
254: logger.setLevel(level);
255: _stdout.println("*** Level for logger " + _logger + " set to "
256: + level);
257:
258: if (!_protocol.equals(WMClientFactory.LOCAL)) {
259: _stdout
260: .println("\007*** WARNING: these changes will not affect logging level on remote server.");
261: }
262: }
263:
264: protected void showLastException() {
265: if (_lastException != null)
266: _lastException.printStackTrace(_stdout);
267: }
268:
269: protected void redisplayMenu() {
270: // This is just a no-op method used when redisplaying the menu.
271: }
272:
273: protected void setClientProtocol() throws IOException {
274: if (_connected) {
275: _stdout
276: .println("\007*** Can only set protocol when disconnected.");
277: return;
278: }
279:
280: String protocol = prompt("Enter protocol", _protocol);
281: if (protocol.equals(WMClientFactory.LOCAL)
282: || protocol.equals(WMClientFactory.RMI)
283: || protocol.equals(WMClientFactory.XML_RPC)) {
284:
285: if (protocol.equals(WMClientFactory.RMI)) {
286: String jndiFactory = System.getProperty(
287: JNDI_FACTORY_PROPERTY, JNDI_FACTORY_DEFAULT);
288: jndiFactory = prompt("Enter JNDI factory", jndiFactory);
289: System.setProperty(JNDI_FACTORY_PROPERTY, jndiFactory);
290: }
291:
292: _client = null;
293: _protocol = protocol;
294: } else {
295: _stdout
296: .println("\007*** Invalid protocol: must be local, rmi, or xml-rpc");
297: }
298: }
299:
300: protected void connect() {
301: if (_connected) {
302: _stdout.println("\007*** Already connected.");
303: return;
304: }
305:
306: _connect();
307: if (_connected) {
308: _stdout.println("- Connected");
309: } else {
310: _stdout.println("\007*** Unable to connect\n");
311: }
312: }
313:
314: protected void disconnect() {
315: if (!_connected) {
316: _stdout.println("\007*** Not connected.");
317: return;
318: }
319:
320: _stdout.println("\nDisconnecting user '" + _userId
321: + "' from host '" + _hostUrl + '\'');
322: _disconnect();
323: _stdout.println("- Disconnected");
324: }
325:
326: protected void listProcessDefinitions() throws WMWorkflowException {
327: WMProcessDefinitionIterator procs = _client
328: .listProcessDefinitions(null, false);
329: String[] values = new String[4];
330: _stdout.setTabs(PROC_DEF_TABS);
331: _stdout.println("Process Definitions:");
332: println(PROC_DEF_FIELDS);
333: _stdout.println(UNDERLINE);
334: while (procs.hasNext()) {
335: WMProcessDefinition proc = procs.tsNext();
336: values[0] = proc.getId();
337: values[1] = proc.getPackageId();
338: values[2] = proc.getName();
339: values[3] = proc.getState().stringValue();
340: println(values);
341: }
342: }
343:
344: protected void startProcessInstance() throws IOException {
345: _procInstId = prompt("\nEnter process instance ID", _procInstId);
346: if ("".equals(_procInstId)) {
347: _stdout.println("\007*** Cancelled");
348: return;
349: }
350:
351: try {
352: _client.startProcess(_procInstId);
353: _stdout
354: .println("- Successfully started process instance # "
355: + _procInstId + '\'');
356: } catch (WMWorkflowException e) {
357: _lastException = e;
358: _stdout
359: .println("\007*** Failed to start process instance [ID: "
360: + _procInstId + "] (" + e + ')');
361: }
362: }
363:
364: protected void createProcessInstance() throws IOException {
365: _procDefId = prompt("\nEnter process definition ID", _procDefId);
366: if ("".equals(_procDefId)) {
367: _stdout.println("\007*** Cancelled");
368: return;
369: }
370:
371: try {
372: _procInstId = _client.createProcessInstance(_procDefId,
373: null);
374:
375: _stdout.println("- Successfully created process '"
376: + _procDefId + "' instance # " + _procInstId);
377:
378: setActualParameters(_procDefId, _procInstId);
379: } catch (Exception e) {
380: _lastException = e;
381: _stdout
382: .println("\007*** Failed to instantiate workflow [ID: "
383: + _procDefId + "] (" + e + ')');
384: }
385: }
386:
387: protected void listProcessInstanceAuditEntries()
388: throws IOException, WMWorkflowException {
389:
390: _procInstId = prompt("\nEnter process instance ID", _procInstId);
391: if ("".equals(_procInstId)) {
392: _stdout.println("\007*** Cancelled");
393: return;
394: }
395:
396: // Retrieve process instance attributes.
397: WMAAuditEntryIterator entries = _client
398: .listAuditEntries(new WMFilter(
399: WMAAuditEntryAttributes.INITIAL_PROCESS_INSTANCE_ID,
400: WMFilter.EQ, _procInstId));
401:
402: // Format the results.
403: listAuditEntries("Process Instance", entries);
404: }
405:
406: protected void listProcessInstanceAttributes() throws IOException,
407: WMWorkflowException {
408:
409: _procInstId = prompt("\nEnter process instance ID", _procInstId);
410: if ("".equals(_procInstId)) {
411: _stdout.println("\007*** Cancelled");
412: return;
413: }
414:
415: // Retrieve process instance attributes.
416: WMAttributeIterator attrs = _client
417: .listProcessInstanceAttributes(_procInstId, null, false);
418:
419: // Format the results.
420: listAttributes("Process Instance", attrs);
421: }
422:
423: protected void showProcessInstanceAttribute() throws IOException {
424: _procInstId = prompt("\nEnter process instance ID", _procInstId);
425: if ("".equals(_procInstId)) {
426: _stdout.println("\007*** Cancelled");
427: return;
428: }
429: _attrName = prompt("\nAttribute Name", _attrName);
430: if ("".equals(_attrName)) {
431: _stdout.println("\007*** Cancelled");
432: return;
433: }
434: try {
435: WMAttribute attr = _client
436: .getProcessInstanceAttributeValue(_procInstId,
437: _attrName);
438: _stdout.println("Attribute value: " + attr);
439: } catch (WMWorkflowException e) {
440: _lastException = e;
441: _stdout
442: .println("\007*** Failed to get process instance attribute [ID: "
443: + _procInstId + "] (" + e + ')');
444: }
445: }
446:
447: protected void executeWorkItem() throws IOException {
448: _workItemId = prompt("\nEnter work item ID", _workItemId);
449: if ("".equals(_workItemId)) {
450: _stdout.println("\007*** Cancelled");
451: return;
452: }
453: try {
454: WMWorkItem workItem = _client
455: .getWorkItem(null, _workItemId);
456: _procInstId = workItem.getProcessInstanceId();
457: ToolInvocation[] ti = _client.executeWorkItem(_procInstId,
458: _workItemId);
459: if (ti == null || ti.length == 0) {
460: _stdout
461: .println("\007*** Work item does not have an associated application");
462: } else {
463: // Invoke the tools asynchronously so that PARALLEL tools
464: // execute concurrently.
465: for (int i = 0, n = ti.length; i < n; i++)
466: ti[i].invokeTool(_client, false);
467:
468: // Give other threads a chance to grab STDIO before we return.
469: // N.B. This delay must be long enough to ensure that threads
470: // started by invoked tool agents have enough time to acquire
471: // the monitor.
472: synchronized (System.in) {
473: System.in.wait(SYSTEM_IN_WAIT);
474: }
475: }
476: } catch (Exception e) {
477: _lastException = e;
478: _stdout.println("\007*** Failed to execute work item [ID: "
479: + _workItemId + "] (" + e + ')');
480: }
481: }
482:
483: protected void changeWorkItemState() throws IOException {
484: _workItemId = prompt("\nEnter work item ID", _workItemId);
485: if ("".equals(_workItemId)) {
486: _stdout.println("\007*** Cancelled");
487: return;
488: }
489: _newState = prompt("\nEnter new state", _newState);
490: if ("".equals(_newState)) {
491: _stdout.println("\007*** Cancelled");
492: return;
493: }
494:
495: try {
496: WMWorkItem workItem = _client
497: .getWorkItem(null, _workItemId);
498: _procInstId = workItem.getProcessInstanceId();
499: _client.changeWorkItemState(_procInstId, _workItemId,
500: WMWorkItemState.valueOf(_newState));
501:
502: _stdout.println("- Successfully changed work item # "
503: + _workItemId + " state to '" + _newState + '\'');
504: } catch (Exception e) {
505: _lastException = e;
506: _stdout
507: .println("\007*** Failed to change work item state [ID: "
508: + _workItemId + "] (" + e + ')');
509: }
510: }
511:
512: protected void showWorkItemAttribute() throws IOException {
513: _workItemId = prompt("\nEnter work item ID", _workItemId);
514: if ("".equals(_workItemId)) {
515: _stdout.println("\007*** Cancelled");
516: return;
517: }
518: _attrName = prompt("\nAttribute Name", _attrName);
519: if ("".equals(_attrName)) {
520: _stdout.println("\007*** Cancelled");
521: return;
522: }
523: try {
524: WMAttribute attr = _client.getWorkItemAttributeValue(null,
525: _workItemId, _attrName);
526: _stdout.println("Attribute value: " + attr);
527: } catch (WMWorkflowException e) {
528: _lastException = e;
529: _stdout
530: .println("\007*** Failed to get work item attribute [ID: "
531: + _workItemId + "] (" + e + ')');
532: }
533: }
534:
535: protected void listWorkItemAttributes() throws IOException,
536: WMWorkflowException {
537:
538: _workItemId = prompt("\nEnter work item ID", _workItemId);
539: if ("".equals(_workItemId)) {
540: _stdout.println("\007*** Cancelled");
541: return;
542: }
543:
544: // Retrieve work item attributes.
545: WMAttributeIterator attrs = _client.listWorkItemAttributes(
546: null, _workItemId, null, false);
547:
548: // Format the results.
549: listAttributes("Work Item", attrs);
550: }
551:
552: protected void listWorkItemsByProcessInstance() throws IOException,
553: WMWorkflowException {
554:
555: _procInstId = prompt("List work items for processInstanceId",
556: _procInstId);
557:
558: // Get the work items.
559: WMFilter filter = new WMFilter("processInstanceId",
560: WMFilter.EQ, _procInstId);
561: listWorkItems(filter);
562: }
563:
564: protected void listWorkItemsByUser() throws IOException,
565: WMWorkflowException {
566:
567: _userId = prompt("List work items for UserId", _userId);
568:
569: // Get the work items.
570: WMFilter filter = new WMFilter("participant", WMFilter.EQ,
571: _userId);
572: listWorkItems(filter);
573: }
574:
575: protected void listWorkItemsByPerformer() throws IOException,
576: WMWorkflowException {
577:
578: _performerId = prompt("List work items for PerformerId",
579: _performerId);
580:
581: // Get the work items.
582: WMFilter filter = new WMFilter("performer", WMFilter.EQ,
583: _performerId);
584: listWorkItems(filter);
585: }
586:
587: protected void listWorkItemsbyActivityInstance()
588: throws IOException, WMWorkflowException {
589:
590: _actInstId = prompt("List work items for activityInstanceId",
591: _actInstId);
592:
593: // Get the work items.
594: WMFilter filter = new WMFilter("activityInstanceId",
595: WMFilter.EQ, _actInstId);
596: listWorkItems(filter);
597: }
598:
599: protected void setActualParameters(String procDefId,
600: String procInstId) throws WMWorkflowException, IOException {
601:
602: WMProcessDefinitionIterator iter = _client
603: .listProcessDefinitions(new WMFilter(
604: "processDefinitionId", WMFilter.EQ, procDefId),
605: false);
606: WMProcessDefinition procDef = iter.tsNext();
607: XPDLPackage pkg = _client.getPackage(procDef.getPackageId());
608: WorkflowProcess workflow = pkg.getWorkflowProcess(procDefId);
609: if (workflow == null) {
610: _stdout.println("\007*** Process definition '" + procDefId
611: + "' not found");
612: } else {
613: FormalParameter[] formalParms = workflow
614: .getFormalParameter();
615: try {
616: for (int k = 0, n = formalParms.length; k < n; k++) {
617: FormalParameter fp = formalParms[k];
618: if (fp.getMode() != ParameterMode.OUT
619: && !assignProcessInstanceAttribute(
620: procInstId, fp.getId())) {
621:
622: break;
623: }
624: }
625: } catch (WMWorkflowException e) {
626: _lastException = e;
627: _stdout
628: .println("\007*** Failed to set formal parameters ("
629: + e + ')');
630: return;
631: }
632: _stdout.print("Do you wish to start the process?");
633: if ("Y".equals(getChoice("YN"))) {
634: try {
635: _client.startProcess(procInstId);
636: _stdout
637: .println("- Successfully started process instance '"
638: + procInstId + '\'');
639: } catch (WMWorkflowException e) {
640: _lastException = e;
641: _stdout
642: .println("\007*** Failed to set start process ("
643: + e + ')');
644: }
645: }
646: }
647: }
648:
649: protected boolean assignProcessInstanceAttribute(String procInstId,
650: String attrName) throws IOException, WMWorkflowException {
651:
652: try {
653: WMAttribute attr = _client
654: .getProcessInstanceAttributeValue(procInstId,
655: attrName);
656: Object value = attr.getValue();
657: String attrValue = value == null ? null : value.toString();
658: if (attrValue == null)
659: attrValue = (String) _attrValues.get(attrName);
660: attrValue = prompt("Enter value for parameter '" + attrName
661: + '\'', attrValue);
662: if (attrValue == null) {
663: _stdout.println("\007*** Cancelled");
664: return false;
665: }
666: _attrValues.put(attrName, attrValue);
667: _client.assignProcessInstanceAttribute(procInstId,
668: attrName, attrValue);
669: _stdout
670: .println("- Successfully assigned value to attribute '"
671: + attrName + '\'');
672: return true;
673: } catch (WMWorkflowException e) {
674: _lastException = e;
675: _stdout
676: .println("\007*** Failed to set process instance attribute [ID: "
677: + _procInstId + "] (" + e + ')');
678: throw e;
679: }
680: }
681:
682: protected void listAttributes(String owner,
683: WMAttributeIterator attrs) {
684: // Format the list.
685: _stdout.setTabs(ATTR_INST_TABS);
686: _stdout.println(owner + " Attributes:");
687: println(ATTR_INST_FIELDS);
688: _stdout.println(UNDERLINE);
689: Object[] values = new Object[3];
690: List list = iteratorToList(attrs);
691: Collections.sort(list, new AttributeComparator());
692: for (Iterator iter = list.iterator(); iter.hasNext();) {
693: WMAttribute attr = (WMAttribute) iter.next();
694: values[0] = attr.getName();
695: values[1] = String.valueOf(attr.getType());
696: values[2] = attr.getValue();
697: println(values);
698: }
699: }
700:
701: protected void listAuditEntries(String owner,
702: WMAAuditEntryIterator entries) throws WMNoMoreDataException {
703:
704: // Format the list.
705: _stdout.setTabs(AUDIT_ENTRY_TABS);
706: _stdout.println(owner + " Audit Entries:");
707: println(AUDIT_ENTRY_FIELDS);
708: _stdout.println(UNDERLINE);
709: Object[] values = new Object[7];
710: while (entries.hasNext()) {
711: WMAAuditEntry entry = entries.tsNext();
712: values[0] = entry.getProcessDefinitionId();
713: values[1] = entry.getActivityDefinitionId();
714: values[2] = entry.getProcessState();
715: values[3] = entry.getEventCode();
716: values[4] = entry.getInitialProcessInstanceId();
717: values[5] = entry.getCurrentProcessInstanceId();
718: values[6] = entry.getActivityInstanceId();
719: println(values);
720: }
721: }
722:
723: protected void listWorkItems(WMFilter filter)
724: throws WMWorkflowException {
725: WMWorkItemIterator workItems = _client.listWorkItems(filter,
726: false);
727:
728: // Format the results.
729: _stdout.setTabs(WORKITEM_TABS);
730: _stdout.println("Work Items:");
731: println(WORKITEM_FIELDS);
732: _stdout.println(UNDERLINE);
733: Object[] values = new Object[6];
734: while (workItems.hasNext()) {
735: OBEWorkItem workItem = (OBEWorkItem) workItems.next();
736: values[0] = workItem.getId();
737: values[1] = workItem.getName();
738: values[2] = String.valueOf(workItem.getPriority());
739: values[3] = workItem.getState().stringValue();
740: values[4] = workItem.getParticipant().getName();
741: values[5] = workItem.getPerformer();
742: println(values);
743: }
744: }
745:
746: private boolean _connect() {
747: try {
748: if (_client == null) {
749: _client = WMClientFactory.createClient(_protocol);
750: _stdout.println("Client protocol: "
751: + _client.getProtocol());
752: } else if (_connected) {
753: _client.disconnect();
754: _connected = false;
755: }
756: WMConnectInfo ci = null;
757: if (!_client.getProtocol().equals(WMClientFactory.LOCAL)) {
758: _hostUrl = prompt("Host URL", _hostUrl);
759: _userId = prompt("User ID", _userId);
760: _password = prompt("Password", _password);
761:
762: _stdout.println("\nConnecting user '" + _userId
763: + "' to host '" + _hostUrl + '\'');
764: ci = new WMConnectInfo(_userId, _password, _hostUrl,
765: null);
766: }
767: _client.connect(ci);
768: _connected = true;
769: } catch (Exception e) {
770: _lastException = e;
771: _stdout.println("\007*** Caught exception: " + e);
772: }
773: return _connected;
774: }
775:
776: protected void _disconnect() {
777: if (_client != null && _connected) {
778: try {
779: _client.disconnect();
780: } catch (WMWorkflowException e) {
781: _lastException = e;
782: _client = null;
783: } finally {
784: _connected = false;
785: }
786: }
787: }
788:
789: protected String prompt(String prompt, String defaultValue)
790: throws IOException {
791:
792: prompt += defaultValue == null ? ": " : " [" + defaultValue
793: + "]: ";
794: _stdout.print(prompt);
795: _stdout.flush();
796: String value = _stdin.readLine().trim();
797: if ("".equals(value))
798: value = defaultValue;
799: return value;
800: }
801:
802: // Checks whether a file exists, and if so confirms overwriting it is okay.
803: protected boolean checkFile(String filename) throws IOException {
804: boolean okay = true;
805: File file = new File(filename);
806: if (file.exists()) {
807: _stdout
808: .print("That file already exists, and will be overwritten. OK [Y/N]");
809: if (!"Y".equals(getChoice("YN"))) {
810: _stdout.println("\007*** Cancelled");
811: okay = false;
812: }
813: }
814: return okay;
815: }
816:
817: protected String getChoice(String choices) throws IOException {
818: while (true) {
819: _stdout.print("> ");
820: _stdout.flush();
821: String line = _stdin.readLine().trim();
822: if (line.length() == 1) {
823: int choice = Character.toUpperCase(line.charAt(0));
824: int index = choices.indexOf(choice);
825: if (index != -1)
826: return choices.substring(index, index + 1);
827: }
828: _stdout
829: .println("\007*** Choice must be one of: "
830: + choices);
831: }
832: }
833:
834: private int columnWidth(int col) {
835: int[] tabs = _stdout.getTabs();
836: int start = col == 0 ? 0 : tabs[col - 1];
837: return tabs[col] - start - 1;
838: }
839:
840: protected void println(Object[] values) {
841: for (int i = 0; i < values.length; i++) {
842: if (values[i] instanceof Object[])
843: values[i] = Arrays.asList((Object[]) values[i]);
844: String value = values[i] == null ? "(null)" : String
845: .valueOf(values[i]);
846: _stdout.print(truncate(value, columnWidth(i)));
847: _stdout.print('\t');
848: }
849: _stdout.println();
850: }
851:
852: protected void quit() {
853: _disconnect();
854: System.exit(0);
855: }
856: }
|