/* Copyright (c) 2008 Bluendo S.r.L. * See about.html for details about license. * * $Id: CommandExecutor.java 1579 2009-06-16 15:55:25Z luca $ */ package it.yup.xmpp; import java.util.Date; import javax.microedition.lcdui.AlertType; // #ifndef UI import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Displayable; //#endif import it.yup.xml.Element; import it.yup.xmlstream.BasicXmlStream; import it.yup.xmlstream.EventQuery; import it.yup.xmlstream.PacketListener; import it.yup.xmpp.XMPPClient.XmppListener; import it.yup.xmpp.packets.DataForm; import it.yup.xmpp.packets.Iq; public class CommandExecutor implements PacketListener, DataFormListener, Task { private static final String STATUS_EXECUTING = "executing"; private static final String STATUS_COMPLETED = "completed"; private static final String STATUS_CANCELED = "canceled"; // private static ResourceManager rm = ResourceManager.getManager("common", // "en"); public static final int MSG_BROKEN_DF = 1101; /** the command information (node, label) */ private String[] cmd; /** the sid associated with this command iteration */ private String sid; /** the data form associated with this command */ private DataForm df; /** the status of this command */ private byte status; private Element current_element = null; private Object screen; private String note = null; private Date last_modify; private int step; private String chosenResource; public CommandExecutor(String[] cmd, String chosenResource) { init(cmd, chosenResource); } private void init(String[] cmd, String chosenResource) { this.cmd = cmd; this.chosenResource = chosenResource; this.status = Task.CMD_EXECUTING; step = 1; last_modify = new Date(); Iq iq = new Iq(chosenResource, Iq.T_SET); Element cel = iq.addElement(XMPPClient.NS_COMMANDS, "command"); cel.setAttribute("node", cmd[0]); cel.setAttribute("action", "execute"); sendPacket(iq); XMPPClient.getInstance().updateTask(this); } private void sendPacket(Iq iq) { XMPPClient xmpp = XMPPClient.getInstance(); EventQuery eq = new EventQuery(Iq.IQ, new String[] { "id" }, new String[] { iq.getAttribute(Iq.ATT_ID) }); BasicXmlStream.addOnetimeEventListener(eq, this); xmpp.sendPacket(iq); } public void packetReceived(Element el) { current_element = el; XMPPClient client = XMPPClient.getInstance(); Element command = (Element) el.getChildByName(XMPPClient.NS_COMMANDS, "command"); if (command == null) { /* ? possible ? */ return; } /* every time this is copied, not a problem, SHOULD stay the same */ sid = command.getAttribute("sessionid"); /* Parse the dataform if present */ Element form = command.getChildByName(DataForm.NAMESPACE, DataForm.X); if (form != null) { df = new DataForm(form); } else { df = null; } /* * Some implementations seem to send the result of a completed form * using a DataForm of type "form" instead of "result", so let's check * the "status" and not the type of the form */ String el_status = command.getAttribute("status"); if (STATUS_CANCELED.equals(el_status)) { /* * the server has canceled the command. could this happen? yes, as * aswer of a cancel */ this.status = Task.CMD_CANCELED; } else if (STATUS_COMPLETED.equals(el_status)) { this.status = Task.CMD_FINISHED; // the command is finished } else if (STATUS_EXECUTING.equals(el_status)) { this.status = Task.CMD_INPUT; } else { // unexpexted status, discard the message, and notify? this.status = Task.CMD_ERROR; // XXX is this enough? } if (el.getAttribute(Iq.ATT_TYPE).equals(Iq.T_ERROR)) this.status = Task.CMD_ERROR; if (df == null) { if (this.status != Task.CMD_FINISHED) { this.status = Task.CMD_FORM_LESS; } else { this.status = Task.CMD_DESTROY; } } Element note_element = command.getChildByName( "http://jabber.org/protocol/commands", "note"); if (note_element != null) { this.note = note_element.getText(); } else { this.note = null; } client.updateTask(this); } public boolean execute(int cmd) { /* * not checking if the cmd is in the allowed ones, as I have built the * screen accordingly... */ boolean setWaiting = false; last_modify = new Date(); switch (cmd) { case DataFormListener.CMD_CANCEL: status = Task.CMD_CANCELING; sendReply("cancel", null); break; case DataFormListener.CMD_PREV: step--; status = Task.CMD_EXECUTING; sendReply("prev", null); setWaiting = true; break; case DataFormListener.CMD_NEXT: step++; status = Task.CMD_EXECUTING; df.type = DataForm.TYPE_SUBMIT; sendReply("next", df.getResultElement()); setWaiting = true; break; case DataFormListener.CMD_SUBMIT: step++; status = Task.CMD_EXECUTING; df.type = DataForm.TYPE_SUBMIT; sendReply("execute", df.getResultElement()); setWaiting = true; break; case DataFormListener.CMD_DELAY: // do nothing, just display the next screen setWaiting = true; break; case DataFormListener.CMD_DESTROY: status = Task.CMD_DESTROY; } // update commad status XMPPClient instance = XMPPClient.getInstance(); instance.updateTask(this); if (instance.getXmppListener() != null) { if (screen != null) { /* close the screen */ instance.getXmppListener().commandExecuted(screen); screen = null; } else { instance.getXmppListener().commandExecuted(null); } } return setWaiting; } void sendReply(String action, Element dfel) { Iq iq = new Iq(chosenResource, Iq.T_SET); Element cel = iq.addElement("http://jabber.org/protocol/commands", "command"); cel.setAttribute("node", cmd[0]); if (sid != null) { cel.setAttribute("sessionid", sid); } if (action != null) { cel.setAttribute("action", action); } if (dfel != null) { cel.addElement(dfel); } sendPacket(iq); } // #ifdef UI public void display() {display_internal();} // #endif // #ifndef UI public void display(Display disp, Displayable next_screen) {display_internal();} // #endif public void display_internal() { Object screen = null; XMPPClient client = XMPPClient.getInstance(); client = XMPPClient.getInstance(); switch (status) { case Task.CMD_INPUT: Element command = (Element) current_element.getChildByName( XMPPClient.NS_COMMANDS, "command"); Element actions = command.getChildByName( XMPPClient.NS_COMMANDS, "actions"); if (actions == null) { actions = new Element(XMPPClient.NS_COMMANDS, "actions"); actions.addElement(null, "complete"); } // add the available actions if (df.type == DataForm.TYPE_FORM) { int cmds = 0; Element[] children = actions.getChildren(); for (int i = 0; i < children.length; i++) { Element iel = children[i]; if ("next".equals(iel.name)) { cmds |= DataFormListener.CMD_NEXT; } else if ("prev".equals(iel.name)) { cmds |= DataFormListener.CMD_PREV; } else if ("complete".equals(iel.name)) { cmds |= DataFormListener.CMD_SUBMIT; } } XmppListener xmppListener = XMPPClient.getInstance() .getXmppListener(); if (xmppListener != null) { this.screen = xmppListener.handleDataForm(df, Task.CMD_INPUT, this, cmds); } /* screen = new DataFormScreen(df, this); DataFormScreen dfs = (DataFormScreen) screen; dfs.setActions(cmds); */ } break; case Task.CMD_EXECUTING: client.showAlert(AlertType.INFO, "Command Info", "Data submitted: awaiting a response from the server", null); break; case Task.CMD_CANCELING: client .showAlert( AlertType.INFO, "Command Info", "Command canceled: awaiting a response from the server", null); break; case Task.CMD_CANCELED: client.showAlert(AlertType.INFO, "Task canceled", "The task " + getLabel() + " has been succesfully canceled", null); break; case Task.CMD_FINISHED: if (df != null) { /* screen = new DataResultScreen(df, this); */ XmppListener xmppListener = XMPPClient.getInstance() .getXmppListener(); if (xmppListener != null) { screen = xmppListener.handleDataForm(df, Task.CMD_FINISHED, this, -1); } } else { // XXX handle note here, if present client.showAlert(AlertType.INFO, "Task finished", "Task finished", null); status = Task.CMD_DESTROY; client.updateTask(this); } break; case Task.CMD_ERROR: String errorText = "An error occurred while executing the task"; Element error = (Element) current_element.getChildByName(null, "error"); if (error != null) { String code = error.getAttribute("code"); if (code != null) errorText += (": " + XMPPClient .getErrorString(code)); } client.showAlert(AlertType.INFO, "Task error", errorText, null); break; } if (status != Task.CMD_ERROR) { if (note != null) { client.showAlert(AlertType.INFO, "Note", note, screen); } if (screen != null) { XmppListener xmppListener = client.getXmppListener(); xmppListener.showCommand(screen); } } } public String getLabel() { return "[" + last_modify.toString().substring(11, 16) + "][" + step + "] " + cmd[1]; } public byte getStatus() { return status; } public String getFrom() { return this.chosenResource; } }