summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/isode/stroke/elements')
-rw-r--r--src/com/isode/stroke/elements/Command.java473
-rw-r--r--src/com/isode/stroke/elements/Form.java242
-rw-r--r--src/com/isode/stroke/elements/FormField.java634
3 files changed, 1349 insertions, 0 deletions
diff --git a/src/com/isode/stroke/elements/Command.java b/src/com/isode/stroke/elements/Command.java
new file mode 100644
index 0000000..75f3bf2
--- /dev/null
+++ b/src/com/isode/stroke/elements/Command.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2012 Isode Limited, London, England.
+ * All rights reserved.
+ */
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * All rights reserved.
+ */
+
+package com.isode.stroke.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Ad-Hoc Command (XEP-0050).
+ */
+public class Command extends Payload {
+ /**
+ * Attribute "node"
+ */
+ public static final String COMMAND_ATTRIBUTE_NODE = "node";
+
+ /**
+ * Attribute "sessionid"
+ */
+ public static final String COMMAND_ATTRIBUTE_SESSION_ID = "sessionid";
+
+ /**
+ * Attribute "status"
+ */
+ public static final String COMMAND_ATTRIBUTE_STATUS = "status";
+
+ /**
+ * Attribute "action"
+ */
+ public static final String COMMAND_ATTRIBUTE_ACTION = "action";
+
+ /**
+ * Element "actions"
+ */
+ public static final String COMMAND_ELEMENT_ACTIONS = "actions";
+
+ /**
+ * Attribute "execute"
+ */
+ public static final String COMMAND_ATTRIBUTE_EXECUTE = "execute";
+
+ /**
+ * Element "note"
+ */
+ public static final String COMMAND_ELEMENT_NOTE = "note";
+
+ /**
+ * Attribute "type"
+ */
+ public static final String COMMAND_ATTRIBUTE_TYPE = "type";
+
+ /**
+ * Current status of the command.
+ */
+ public enum Status {
+ /**
+ * The command is being executed.
+ */
+ EXECUTING("executing"),
+ /**
+ * The command has completed. The command session has ended.
+ */
+ COMPLETED("completed"),
+ /**
+ * The command has been cancelled. The command session has ended.
+ */
+ CANCELED("canceled"),
+ /**
+ * No status has been set for the command.
+ */
+ NO_STATUS("");
+
+ private String stringForm_;
+
+ private Status(String stringForm) {
+ stringForm_ = stringForm;
+ }
+
+ /**
+ * Get status from its string form.
+ *
+ * @param stringForm String form of status, can be null
+ *
+ * @return Corresponding status if match found, otherwise
+ * {@link #NO_STATUS}. Will never be null.
+ */
+ public static Status getStatus(String stringForm) {
+ if (stringForm != null) {
+ for (Status status : Status.values()) {
+ if (status.stringForm_.equals(stringForm)) {
+ return status;
+ }
+ }
+ }
+
+ return NO_STATUS;
+ }
+
+ /**
+ * @return String form of status, will never be null
+ */
+ public String getStringForm() {
+ return stringForm_;
+ }
+ };
+
+ /**
+ * The action to undertake with the given command.
+ */
+ public enum Action {
+ /**
+ * The command should be cancelled.
+ */
+ CANCEL("cancel"),
+ /**
+ * The command should be executed or continue to be executed.
+ */
+ EXECUTE("execute"),
+ /**
+ * The command should be completed (if possible).
+ */
+ COMPLETE("complete"),
+ /**
+ * The command should digress to the previous stage of execution.
+ */
+ PREV("prev"),
+ /**
+ * The command should progress to the next stage of execution.
+ */
+ NEXT("next"),
+ /**
+ * No action is available for the command.
+ */
+ NO_ACTION("");
+
+ private String stringForm_;
+
+ private Action(String stringForm) {
+ stringForm_ = stringForm;
+ }
+
+ /**
+ * Get action from its string form.
+ *
+ * @param stringForm String form of action, can be null
+ *
+ * @return Corresponding action if match found, otherwise
+ * {@link Action#NO_ACTION}. Will never be null.
+ */
+ public static Action getAction(String stringForm) {
+ if (stringForm != null) {
+ for (Action action : Action.values()) {
+ if (action.stringForm_.equals(stringForm)) {
+ return action;
+ }
+ }
+ }
+
+ return NO_ACTION;
+ }
+
+ /**
+ * @return String form of action, will never be null
+ */
+ public String getStringForm() {
+ return stringForm_;
+ }
+ };
+
+ /**
+ * This class contains information about the current status of the command.
+ * TODO: I am not sure why this is not an immutable class.
+ */
+ public static class Note {
+ /**
+ * Severity of the note.
+ */
+ public enum Type {
+ /**
+ * The note is informational only. This is not really an exceptional
+ * condition.
+ */
+ INFO("info"),
+ /**
+ * The note indicates a warning. Possibly due to illogical (yet
+ * valid) data.
+ */
+ WARN("warn"),
+ /**
+ * The note indicates an error. The text should indicate the reason
+ * for the error.
+ */
+ ERROR("error");
+
+ private String stringForm_;
+
+ private Type(String stringForm) {
+ stringForm_ = stringForm;
+ }
+
+ /**
+ * Get type from its string form.
+ *
+ * @param stringForm String form of type, can be null
+ *
+ * @return Corresponding type if match found, otherwise
+ * {@link Type#INFO}. Will never be null.
+ */
+ public static Type getType(String stringForm) {
+ if (stringForm != null) {
+ for (Type type : Type.values()) {
+ if (type.stringForm_.equals(stringForm)) {
+ return type;
+ }
+ }
+ }
+
+ return INFO;
+ }
+
+ /**
+ * @return String form of type, will never be null
+ */
+ public String getStringForm() {
+ return stringForm_;
+ }
+ };
+
+ /**
+ * Create a note element for the Ad-Hoc command.
+ *
+ * @param note user-readable text, can be null which will be stored as
+ * an empty string
+ * @param type Severity of the note, can be null which will be stored as
+ * {@link Type#INFO}
+ */
+ public Note(String note, Type type) {
+ this.note = (note != null) ? note : "";
+ this.type = (type != null) ? type : Type.INFO;
+ }
+
+ /**
+ * User-readable text, will never be null
+ */
+ public final String note;
+
+ /**
+ * Severity of the note, will never be null
+ */
+ public final Type type;
+ };
+
+ private String node_;
+ private String sessionID_;
+ private Action action_;
+ private Status status_;
+ private Action executeAction_;
+ private List<Action> availableActions_ = new ArrayList<Action>();
+ private List<Note> notes_ = new ArrayList<Note>();
+ private Form form_ = null;
+
+ private void assignData(String node, String sessionID, Action action,
+ Status status) {
+ setNode(node);
+ setSessionID(sessionID);
+ setAction(action);
+ setStatus(status);
+ setExecuteAction(null);
+ }
+
+ /**
+ * Create an Ad-Hoc command with the given node, session ID, status and
+ * {@link Action#NO_ACTION} action.
+ *
+ * @param node Command identification, can be null which will be stored as
+ * an empty string
+ * @param sessionID The ID of the session within which the command exists,
+ * can be null (which will be stored as an empty string) or empty
+ * if this is the first stage of the command and the client does
+ * not know it yet
+ * @param status Status of the command, can be null which will be stored as
+ * {@link Status#NO_STATUS}
+ */
+ public Command(String node, String sessionID, Status status) {
+ assignData(node, sessionID, Action.NO_ACTION, status);
+ }
+
+ /**
+ * Create an Ad-Hoc command with the given node, session ID, action and
+ * {@link Status#NO_STATUS} status.
+ *
+ * @param node Command identification, can be null which will be stored as
+ * an empty string
+ * @param sessionID The ID of the session within which the command exists,
+ * can be null (which will be stored as an empty string) or empty
+ * if this is the first stage of the command and the client does
+ * not know it yet
+ * @param action action of the command, can be null which will be stored as
+ * {@link Action#EXECUTE}
+ */
+ public Command(String node, String sessionID, Action action) {
+ assignData(node, sessionID, action, null);
+ }
+
+ /**
+ * Create an Ad-Hoc command with an empty node, empty session ID,
+ * {@link Action#EXECUTE} action and {@link Status#NO_STATUS} status.
+ */
+ public Command() {
+ this(null, null, (Action) null);
+ }
+
+ /**
+ * @return The command ID, will never be null
+ */
+ public String getNode() {
+ return node_;
+ }
+
+ /**
+ * Set command ID.
+ *
+ * @param node Command identification, can be null which will be stored as
+ * an empty string
+ */
+ public void setNode(String node) {
+ node_ = (node != null) ? node : "";
+ }
+
+ /**
+ * @return The ID of the session within which the command exists, can be
+ * empty if this is the first stage of the command and the client
+ * does not know it yet, will never be null
+ */
+ public String getSessionID() {
+ return sessionID_;
+ }
+
+ /**
+ * Set session ID.
+ *
+ * @param sessionID The ID of the session within which the command exists,
+ * can be null (which will be stored as an empty string) or empty
+ * if this is the first stage of the command and the client does
+ * not know it yet
+ */
+ public void setSessionID(String sessionID) {
+ sessionID_ = (sessionID != null) ? sessionID : "";
+ }
+
+ /**
+ * @return action of the command, will never be null
+ */
+ public Action getAction() {
+ return action_;
+ }
+
+ /**
+ * Set action of the command.
+ *
+ * @param action action of the command, can be null which will be stored as
+ * {@link Action#EXECUTE}
+ */
+ public void setAction(Action action) {
+ action_ = (action != null) ? action : Action.EXECUTE;
+ }
+
+ /**
+ * @return execute action of the command, will never be null
+ */
+ public Action getExecuteAction() {
+ return executeAction_;
+ }
+
+ /**
+ * Set execute action of the command.
+ *
+ * @param action execute action of the command, can be null which will be
+ * stored as {@link Action#NO_ACTION}
+ */
+ public void setExecuteAction(Action action) {
+ executeAction_ = (action != null) ? action : Action.NO_ACTION;
+ }
+
+ /**
+ * @return status of the command, will never be null
+ */
+ public Status getStatus() {
+ return status_;
+ }
+
+ /**
+ * Set status of the command.
+ *
+ * @param status Status of the command, can be null which will be stored as
+ * {@link Status#NO_STATUS}
+ */
+ public void setStatus(Status status) {
+ status_ = (status != null) ? status : Status.NO_STATUS;
+ }
+
+ /**
+ * @return List of allowed actions for this stage of execution, will never
+ * be null
+ */
+ public List<Action> getAvailableActions() {
+ return new ArrayList<Action>(availableActions_);
+ }
+
+ /**
+ * Add to the list of allowed actions for this stage of execution.
+ *
+ * @param action Action to add, can be null in which case it will be ignored
+ */
+ public void addAvailableAction(Action action) {
+ if (action != null) {
+ availableActions_.add(action);
+ }
+ }
+
+ /**
+ * @return List of information elements for the current status of the
+ * command, will never be null
+ */
+ public List<Note> getNotes() {
+ return new ArrayList<Note>(notes_);
+ }
+
+ /**
+ * Add to the list of information elements for the current status of the
+ * command.
+ *
+ * @param note Note to add, can be null in which case it will be ignored
+ */
+ public void addNote(Note note) {
+ if (note != null) {
+ notes_.add(note);
+ }
+ }
+
+ /**
+ * @return form of the command, can be null. The instance of the form stored
+ * in the object is returned, a copy is not made.
+ */
+ public Form getForm() {
+ return form_;
+ }
+
+ /**
+ * Set form for the command.
+ *
+ * @param payload Form for the command, can be null. The instance of the
+ * form is stored in the object, a copy is not made.
+ */
+ public void setForm(Form payload) {
+ form_ = payload;
+ }
+
+ @Override
+ public String toString() {
+ return Command.class.getSimpleName() + "\nnode: " + node_
+ + "\nsession ID: " + sessionID_ + "\naction: " + action_
+ + "\nstatus: " + status_ + "\nexecute action: "
+ + executeAction_;
+ }
+}
diff --git a/src/com/isode/stroke/elements/Form.java b/src/com/isode/stroke/elements/Form.java
new file mode 100644
index 0000000..1c2e830
--- /dev/null
+++ b/src/com/isode/stroke/elements/Form.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2012 Isode Limited, London, England.
+ * All rights reserved.
+ */
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * All rights reserved.
+ */
+
+package com.isode.stroke.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.isode.stroke.elements.FormField.HiddenFormField;
+
+/**
+ * XEP-0004 Data form. For the relevant Fields, the parsers and serialisers
+ * protect the API user against the strange multi-value instead of newline thing
+ * by transforming them.
+ */
+public class Form extends Payload {
+ /**
+ * Attribute "type"
+ */
+ public static final String FORM_ATTRIBUTE_TYPE = "type";
+
+ /**
+ * Element "title"
+ */
+ public static final String FORM_ELEMENT_TITLE = "title";
+
+ /**
+ * Element "instructions"
+ */
+ public static final String FORM_ELEMENT_INSTRUCTIONS = "instructions";
+
+ /**
+ * Element "field"
+ */
+ public static final String FORM_ELEMENT_FIELD = "field";
+
+ /**
+ * Type of form
+ */
+ public enum Type {
+ /**
+ * The form-processing entity is asking the form-submitting entity to
+ * complete a form.
+ */
+ FORM_TYPE("form"),
+ /**
+ * The form-submitting entity is submitting data to the form-processing
+ * entity.
+ */
+ SUBMIT_TYPE("submit"),
+ /**
+ * The form-submitting entity has cancelled submission of data to the
+ * form-processing entity.
+ */
+ CANCEL_TYPE("cancel"),
+ /**
+ * The form-processing entity is returning data (e.g., search results)
+ * to the form-submitting entity, or the data is a generic data set.
+ */
+ RESULT_TYPE("result");
+
+ private String stringForm_;
+
+ private Type(String stringForm) {
+ stringForm_ = stringForm;
+ }
+
+ /**
+ * Get type from its string form.
+ *
+ * @param stringForm String form of type, can be null
+ *
+ * @return Corresponding type if match found, otherwise
+ * {@link Type#FORM_TYPE}. Will never be null.
+ */
+ public static Type getType(String stringForm) {
+ if (stringForm != null) {
+ for (Type type : Type.values()) {
+ if (type.stringForm_.equals(stringForm)) {
+ return type;
+ }
+ }
+ }
+
+ return FORM_TYPE;
+ }
+
+ /**
+ * @return String form of type, will never be null
+ */
+ public String getStringForm() {
+ return stringForm_;
+ }
+ };
+
+ private List<FormField> fields_ = new ArrayList<FormField>();
+ private String title_ = "";
+ private String instructions_ = "";
+ private Type type_;
+
+ /**
+ * Create a form of the given type.
+ *
+ * @param type Form type, if null then {@link Type#FORM_TYPE} is assumed
+ */
+ public Form(Type type) {
+ setType(type);
+ }
+
+ /**
+ * Create a form of {@link Type#FORM_TYPE}.
+ */
+ public Form() {
+ this(null);
+ }
+
+ /**
+ * Add to the list of fields for the form.
+ *
+ * @param field Field to add, can be null in which case it will be ignored.
+ * The instance of the form field is stored in the object, a copy
+ * is not made.
+ */
+ public void addField(FormField field) {
+ if (field != null) {
+ fields_.add(field);
+ }
+ }
+
+ /**
+ * @return List of fields for the form, will never be null. The instances of
+ * the form fields stored in the object is returned, a copy is not
+ * made.
+ */
+ public List<FormField> getFields() {
+ return new ArrayList<FormField>(fields_);
+ }
+
+ /**
+ * Set title of the form.
+ *
+ * @param title title of the form, can be null in which case an empty string
+ * will be stored
+ */
+ public void setTitle(String title) {
+ title_ = (title != null) ? title : "";
+ }
+
+ /**
+ * @return title of the form, will never be null
+ */
+ public String getTitle() {
+ return title_;
+ }
+
+ /**
+ * Set natural-language instructions for the form.
+ *
+ * @param instructions instructions for the form, can be null in which case
+ * an empty string will be stored
+ */
+ public void setInstructions(String instructions) {
+ instructions_ = (instructions != null) ? instructions : "";
+ }
+
+ /**
+ * @return natural-language instructions for the form, will never be null
+ */
+ public String getInstructions() {
+ return instructions_;
+ }
+
+ /**
+ * Set type of the form.
+ *
+ * @param type Form type, if null then {@link Type#FORM_TYPE} is assumed
+ */
+ public void setType(Type type) {
+ type_ = (type != null) ? type : Type.FORM_TYPE;
+ }
+
+ /**
+ * @return type of the form, will never be null
+ */
+ public Type getType() {
+ return type_;
+ }
+
+ /**
+ * @return Value of the "FORM_TYPE" hidden form field if it is present in
+ * the form, an empty string otherwise, will never be null
+ */
+ public String getFormType() {
+ String value = null;
+
+ FormField field = getField("FORM_TYPE");
+ try {
+ HiddenFormField f = (HiddenFormField) field;
+ if (f != null) {
+ value = f.getValue();
+ }
+ } catch (ClassCastException e) {
+ // value remains null
+ }
+
+ return ((value != null) ? value : "");
+ }
+
+ /**
+ * Get form field for the given name.
+ *
+ * @param name Name of form field to retrieve, can be null in which case
+ * null will be returned
+ *
+ * @return Form field with the given name if it is present in the form, null
+ * otherwise. The instance of the form field stored in the object is
+ * returned, a copy is not made.
+ */
+ public FormField getField(String name) {
+ if (name != null) {
+ for (FormField field : fields_) {
+ if (field.getName().equals(name)) {
+ return field;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return Form.class.getSimpleName() + "\ntitle: " + title_
+ + "\ninstructions: " + instructions_ + "\ntype: " + type_;
+ }
+}
diff --git a/src/com/isode/stroke/elements/FormField.java b/src/com/isode/stroke/elements/FormField.java
new file mode 100644
index 0000000..06b2ce6
--- /dev/null
+++ b/src/com/isode/stroke/elements/FormField.java
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2012 Isode Limited, London, England.
+ * All rights reserved.
+ */
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * All rights reserved.
+ */
+
+package com.isode.stroke.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.isode.stroke.elements.Form.Type;
+import com.isode.stroke.jid.JID;
+
+/**
+ * This class implements the field element of a form.
+ *
+ * <p>
+ * Data validation is the responsibility of the form-processing entity (commonly
+ * a server, service, or bot) rather than the form-submitting entity (commonly a
+ * client controlled by a human user). This helps to meet the requirement for
+ * keeping client implementations simple. If the form-processing entity
+ * determines that the data provided is not valid, it SHOULD return a
+ * "Not Acceptable" error, optionally providing a textual explanation.
+ */
+public class FormField {
+ /**
+ * Attribute "var"
+ */
+ public static final String FORM_FIELD_ATTRIBUTE_VAR = "var";
+
+ /**
+ * Attribute "label"
+ */
+ public static final String FORM_FIELD_ATTRIBUTE_LABEL = "label";
+
+ /**
+ * Element "required"
+ */
+ public static final String FORM_FIELD_ELEMENT_REQUIRED = "required";
+
+ /**
+ * Element "desc"
+ */
+ public static final String FORM_FIELD_ELEMENT_DESC = "desc";
+
+ /**
+ * Element "value"
+ */
+ public static final String FORM_FIELD_ELEMENT_VALUE = "value";
+
+ /**
+ * Attribute "type"
+ */
+ public static final String FORM_FIELD_ATTRIBUTE_TYPE = "type";
+
+ /**
+ * Element "option"
+ */
+ public static final String FORM_FIELD_ELEMENT_OPTION = "option";
+
+ /**
+ * Attribute option "label"
+ */
+ public static final String FORM_FIELD_ATTRIBUTE_OPTION_LABEL = "label";
+
+ /**
+ * Element option "value"
+ */
+ public static final String FORM_FIELD_ELEMENT_OPTION_VALUE = "value";
+
+ /**
+ * Type "boolean"
+ */
+ public static final String FORM_FIELD_TYPE_BOOLEAN = "boolean";
+
+ /**
+ * Type "fixed"
+ */
+ public static final String FORM_FIELD_TYPE_FIXED = "fixed";
+
+ /**
+ * Type "hidden"
+ */
+ public static final String FORM_FIELD_TYPE_HIDDEN = "hidden";
+
+ /**
+ * Type "list-single"
+ */
+ public static final String FORM_FIELD_TYPE_LIST_SINGLE = "list-single";
+
+ /**
+ * Type "text-private"
+ */
+ public static final String FORM_FIELD_TYPE_TEXT_PRIVATE = "text-private";
+
+ /**
+ * Type "text-single"
+ */
+ public static final String FORM_FIELD_TYPE_TEXT_SINGLE = "text-single";
+
+ /**
+ * Type "jid-multi"
+ */
+ public static final String FORM_FIELD_TYPE_JID_MULTI = "jid-multi";
+
+ /**
+ * Type "jid-single"
+ */
+ public static final String FORM_FIELD_TYPE_JID_SINGLE = "jid-single";
+
+ /**
+ * Type "list-multi"
+ */
+ public static final String FORM_FIELD_TYPE_LIST_MULTI = "list-multi";
+
+ /**
+ * Type "text-multi"
+ */
+ public static final String FORM_FIELD_TYPE_TEXT_MULTI = "text-multi";
+
+ /**
+ * This class defines the option element that can be used in
+ * {@link ListSingleFormField} and {@link ListMultiFormField}. TODO: This
+ * class should be immutable.
+ */
+ public static class Option {
+ /**
+ * Human-readable name for the option, must not be null
+ */
+ public String label;
+
+ /**
+ * Option value, must not be null
+ */
+ public String value;
+
+ /**
+ * Create an option element.
+ *
+ * @param label Human-readable name for the option, can be null in which
+ * case an empty string will be stored
+ * @param value Option value, must not be null
+ */
+ public Option(String label, String value) {
+ if (value == null) {
+ throw new NullPointerException("'value' must not be null");
+ }
+
+ this.label = (label != null) ? label : "";
+ this.value = value;
+ }
+ }
+
+ private String name = "";
+ private String label = "";
+ private String description = "";
+ private boolean required;
+ private List<Option> options = new ArrayList<Option>();
+ private List<String> rawValues = new ArrayList<String>();
+
+ protected FormField() {
+ required = false;
+ }
+
+ /**
+ * Set the unique identifier for the field in the form.
+ *
+ * @param name unique identifier for the field in the form, can be null in
+ * which case an empty string will be stored
+ */
+ public void setName(String name) {
+ this.name = (name != null) ? name : "";
+ }
+
+ /**
+ * @return unique identifier for the field, will never be null
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Set the human-readable name for the field.
+ *
+ * @param label human-readable name for the field, can be null in which case
+ * an empty string will be stored
+ */
+ public void setLabel(String label) {
+ this.label = (label != null) ? label : "";
+ }
+
+ /**
+ * @return human-readable name for the field, will never be null
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Set the natural-language description for the field.
+ *
+ * @param description natural-language description for the field, can be
+ * null in which case an empty string will be stored
+ */
+ public void setDescription(String description) {
+ this.description = (description != null) ? description : "";
+ }
+
+ /**
+ * @return natural-language description for the field, will never be null
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Set if the field is required for the form to be considered valid.
+ *
+ * @param required true if the field is required for the form to be
+ * considered valid
+ */
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+
+ /**
+ * @return true if the field is required for the form to be considered valid
+ */
+ public boolean getRequired() {
+ return required;
+ }
+
+ /**
+ * Add to the list of options for this form field.
+ *
+ * @param option Option to add, can be null in which case it will be ignored
+ */
+ public void addOption(Option option) {
+ if (option != null) {
+ options.add(option);
+ }
+ }
+
+ /**
+ * @return List of options for this form, will never be null
+ */
+ public List<Option> getOptions() {
+ return new ArrayList<Option>(options);
+ }
+
+ /**
+ * Add to values for this field. The values can be the defaults suggested in
+ * a form of {@link Type#FORM_TYPE} or results provided in a form of
+ * {@link Type#RESULT_TYPE} or values submitted in a form of
+ * {@link Type#SUBMIT_TYPE}.
+ *
+ * @param value Value to add, can be null
+ */
+ public void addRawValue(String value) {
+ rawValues.add(value);
+ }
+
+ /**
+ * @return List of values for this field, will never be null
+ */
+ public List<String> getRawValues() {
+ return new ArrayList<String>(rawValues);
+ }
+
+ /**
+ * Template for creating a form field.
+ *
+ * @param <T> Type of form field.
+ */
+ public static class GenericFormField<T> extends FormField {
+ private T value;
+
+ /**
+ * @return Values for this field. The values can be the defaults
+ * suggested in a form of {@link Type#FORM_TYPE} or results
+ * provided in a form of {@link Type#RESULT_TYPE} or values
+ * submitted in a form of {@link Type#SUBMIT_TYPE}. Will never be
+ * null.
+ */
+ public T getValue() {
+ return value;
+ }
+
+ /**
+ * Set values for this field. The values can be the defaults suggested
+ * in a form of {@link Type#FORM_TYPE} or results provided in a form of
+ * {@link Type#RESULT_TYPE} or values submitted in a form of
+ * {@link Type#SUBMIT_TYPE}.
+ *
+ * @param value Value to set, must not be null
+ */
+ public void setValue(T value) {
+ if (value == null) {
+ throw new NullPointerException("'value' must not be null");
+ }
+
+ this.value = value;
+ }
+
+ protected GenericFormField(T value) {
+ setValue(value);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide an either-or choice
+ * between two options. The default value is "false".
+ */
+ public static class BooleanFormField extends GenericFormField<Boolean> {
+ private BooleanFormField(Boolean value) {
+ super((value == null) ? Boolean.FALSE : value);
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be assumed
+ * as FALSE.
+ *
+ * @return new object, will never be null
+ */
+ public static BooleanFormField create(Boolean value) {
+ return new BooleanFormField(value);
+ }
+
+ /**
+ * Create an object with value FALSE.
+ *
+ * @return new object, will never be null
+ */
+ public static BooleanFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field is intended for data description (e.g., human-readable text
+ * such as "section" headers) rather than data gathering or provision.
+ */
+ public static class FixedFormField extends GenericFormField<String> {
+ private FixedFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static FixedFormField create(String value) {
+ return new FixedFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static FixedFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field is not shown to the form-submitting entity, but instead is
+ * returned with the form.
+ */
+ public static class HiddenFormField extends GenericFormField<String> {
+ private HiddenFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static HiddenFormField create(String value) {
+ return new HiddenFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static HiddenFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide one option from among
+ * many.
+ */
+ public static class ListSingleFormField extends GenericFormField<String> {
+ private ListSingleFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static ListSingleFormField create(String value) {
+ return new ListSingleFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static ListSingleFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide multiple lines of text
+ * (i.e. containing newlines).
+ */
+ public static class TextMultiFormField extends GenericFormField<String> {
+ private TextMultiFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextMultiFormField create(String value) {
+ return new TextMultiFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextMultiFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide a single line or word
+ * of text, which shall be obscured in an interface (e.g., with multiple
+ * instances of the asterisk character).
+ */
+ public static class TextPrivateFormField extends GenericFormField<String> {
+ private TextPrivateFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextPrivateFormField create(String value) {
+ return new TextPrivateFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextPrivateFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide a single line or word
+ * of text, which may be shown in an interface.
+ */
+ public static class TextSingleFormField extends GenericFormField<String> {
+ private TextSingleFormField(String value) {
+ super((value != null) ? value : "");
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextSingleFormField create(String value) {
+ return new TextSingleFormField(value);
+ }
+
+ /**
+ * Create an object with value as an empty string.
+ *
+ * @return new object, will never be null
+ */
+ public static TextSingleFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide a single Jabber ID.
+ */
+ public static class JIDSingleFormField extends GenericFormField<JID> {
+ private JIDSingleFormField(JID value) {
+ super((value != null) ? value : new JID());
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be stored
+ * as an invalid JID.
+ *
+ * @return new object, will never be null
+ */
+ public static JIDSingleFormField create(JID value) {
+ return new JIDSingleFormField(value);
+ }
+
+ /**
+ * Create an object with value as an invalid JID.
+ *
+ * @return new object, will never be null
+ */
+ public static JIDSingleFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide multiple Jabber IDs.
+ */
+ public static class JIDMultiFormField extends GenericFormField<List<JID>> {
+ private JIDMultiFormField(List<JID> value) {
+ super((value == null) ? new ArrayList<JID>() : new ArrayList<JID>(
+ value));
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be assumed
+ * to be an empty list. A copy of the given list will be kept
+ * by this object.
+ *
+ * @return new object, will never be null
+ */
+ public static JIDMultiFormField create(List<JID> value) {
+ return new JIDMultiFormField(value);
+ }
+
+ /**
+ * Create an object with an empty list.
+ *
+ * @return new object, will never be null
+ */
+ public static JIDMultiFormField create() {
+ return create(null);
+ }
+ }
+
+ /**
+ * This field enables an entity to gather or provide one or more options
+ * from among many. The order of items MAY be significant.
+ */
+ public static class ListMultiFormField extends
+ GenericFormField<List<String>> {
+ private ListMultiFormField(List<String> value) {
+ super((value == null) ? new ArrayList<String>()
+ : new ArrayList<String>(value));
+ }
+
+ /**
+ * Create an object with given value.
+ *
+ * @param value Value for this field, can be null which will be assumed
+ * to be an empty list. A copy of the given list will be kept
+ * by this object.
+ *
+ * @return new object, will never be null
+ */
+ public static ListMultiFormField create(List<String> value) {
+ return new ListMultiFormField(value);
+ }
+
+ /**
+ * Create an object with an empty list.
+ *
+ * @return new object, will never be null
+ */
+ public static ListMultiFormField create() {
+ return create(null);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return FormField.class.getSimpleName() + "\nname: " + name
+ + "\nlabel: " + label + "\ndescription: " + description
+ + "\nrequired: " + required;
+ }
+}