001/** 002 * 003 * Copyright 2005-2008 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smackx.commands.packet; 019 020import java.util.ArrayList; 021import java.util.EnumSet; 022import java.util.List; 023import java.util.Set; 024 025import org.jivesoftware.smack.XMPPConnection; 026import org.jivesoftware.smack.packet.IQ; 027import org.jivesoftware.smack.packet.IqData; 028import org.jivesoftware.smack.packet.XmlElement; 029 030import org.jivesoftware.smackx.commands.AdHocCommandNote; 031import org.jivesoftware.smackx.commands.SpecificErrorCondition; 032import org.jivesoftware.smackx.xdata.packet.DataForm; 033 034/** 035 * Represents the state and the request of the execution of an adhoc command. 036 * 037 * @author Gabriel Guardincerri 038 * @author Florian Schmaus 039 */ 040public class AdHocCommandData extends IQ implements AdHocCommandDataView { 041 042 public static final String ELEMENT = "command"; 043 public static final String NAMESPACE = "http://jabber.org/protocol/commands"; 044 045 private final String node; 046 047 private final String name; 048 049 private final String sessionId; 050 051 private final List<AdHocCommandNote> notes = new ArrayList<>(); 052 053 private final DataForm form; 054 055 private final Action action; 056 057 private final Status status; 058 059 private final Set<AllowedAction> actions = EnumSet.noneOf(AllowedAction.class); 060 061 private final AllowedAction executeAction; 062 063 public AdHocCommandData(AdHocCommandDataBuilder builder) { 064 super(builder, ELEMENT, NAMESPACE); 065 node = builder.getNode(); 066 name = builder.getName(); 067 sessionId = builder.getSessionId(); 068 notes.addAll(builder.getNotes()); 069 form = builder.getForm(); 070 action = builder.getAction(); 071 status = builder.getStatus(); 072 actions.addAll(builder.getActions()); 073 executeAction = builder.getExecuteAction(); 074 075 if (executeAction != null && !actions.contains(executeAction)) { 076 throw new IllegalArgumentException("Execute action " + executeAction + " is not part of allowed actions: " + actions); 077 } 078 } 079 080 @Override 081 public String getNode() { 082 return node; 083 } 084 085 @Override 086 public String getName() { 087 return name; 088 } 089 090 @Override 091 public String getSessionId() { 092 return sessionId; 093 } 094 095 @Override 096 public List<AdHocCommandNote> getNotes() { 097 return notes; 098 } 099 100 @Override 101 public DataForm getForm() { 102 return form; 103 } 104 105 @Override 106 public Action getAction() { 107 return action; 108 } 109 110 @Override 111 public Status getStatus() { 112 return status; 113 } 114 115 @Override 116 public Set<AllowedAction> getActions() { 117 return actions; 118 } 119 120 @Override 121 public AllowedAction getExecuteAction() { 122 return executeAction; 123 } 124 125 @Override 126 protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { 127 xml.attribute("node", node); 128 xml.optAttribute("sessionid", sessionId); 129 xml.optAttribute("status", status); 130 xml.optAttribute("action", action); 131 xml.rightAngleBracket(); 132 133 if (getType() == Type.result) { 134 xml.halfOpenElement("actions"); 135 xml.optAttribute("execute", executeAction); 136 if (actions.size() == 0) { 137 xml.closeEmptyElement(); 138 } else { 139 xml.rightAngleBracket(); 140 141 for (AdHocCommandData.AllowedAction action : actions) { 142 xml.emptyElement(action); 143 } 144 xml.closeElement("actions"); 145 } 146 } 147 148 xml.optAppend(form); 149 150 for (AdHocCommandNote note : notes) { 151 xml.halfOpenElement("note") 152 .attribute("type", note.getType().toString()) 153 .rightAngleBracket(); 154 xml.append(note.getValue()); 155 xml.closeElement("note"); 156 } 157 158 // TODO ERRORS 159// if (getError() != null) { 160// buf.append(getError().toXML()); 161// } 162 163 return xml; 164 } 165 166 public static AdHocCommandDataBuilder builder(String node, IqData iqCommon) { 167 return new AdHocCommandDataBuilder(node, iqCommon); 168 } 169 170 public static AdHocCommandDataBuilder builder(String node, String stanzaId) { 171 return new AdHocCommandDataBuilder(node, stanzaId); 172 } 173 174 public static AdHocCommandDataBuilder builder(String node, XMPPConnection connection) { 175 return new AdHocCommandDataBuilder(node, connection); 176 } 177 178 public static class SpecificError implements XmlElement { 179 180 public static final String namespace = "http://jabber.org/protocol/commands"; 181 182 public SpecificErrorCondition condition; 183 184 public SpecificError(SpecificErrorCondition condition) { 185 this.condition = condition; 186 } 187 188 @Override 189 public String getElementName() { 190 return condition.toString(); 191 } 192 @Override 193 public String getNamespace() { 194 return namespace; 195 } 196 197 public SpecificErrorCondition getCondition() { 198 return condition; 199 } 200 201 @Override 202 public String toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) { 203 StringBuilder buf = new StringBuilder(); 204 buf.append('<').append(getElementName()); 205 buf.append(" xmlns=\"").append(getNamespace()).append("\"/>"); 206 return buf.toString(); 207 } 208 } 209 210 /** 211 * The status of the stage in the adhoc command. 212 */ 213 public enum Status { 214 215 /** 216 * The command is being executed. 217 */ 218 executing, 219 220 /** 221 * The command has completed. The command session has ended. 222 */ 223 completed, 224 225 /** 226 * The command has been canceled. The command session has ended. 227 */ 228 canceled 229 } 230 231 public enum AllowedAction { 232 233 /** 234 * The command should be digress to the previous stage of execution. 235 */ 236 prev(Action.prev), 237 238 /** 239 * The command should progress to the next stage of execution. 240 */ 241 next(Action.next), 242 243 /** 244 * The command should be completed (if possible). 245 */ 246 complete(Action.complete), 247 ; 248 249 public final Action action; 250 251 AllowedAction(Action action) { 252 this.action = action; 253 } 254 } 255 256 public enum Action { 257 /** 258 * The command should be executed or continue to be executed. This is 259 * the default value. 260 */ 261 execute(null), 262 263 /** 264 * The command should be canceled. 265 */ 266 cancel(null), 267 268 /** 269 * The command should be digress to the previous stage of execution. 270 */ 271 prev(AllowedAction.prev), 272 273 /** 274 * The command should progress to the next stage of execution. 275 */ 276 next(AllowedAction.next), 277 278 /** 279 * The command should be completed (if possible). 280 */ 281 complete(AllowedAction.complete), 282 ; 283 284 public final AllowedAction allowedAction; 285 286 Action(AllowedAction allowedAction) { 287 this.allowedAction = allowedAction; 288 } 289 290 } 291}