/** * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.smackx.pubsub; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.FormField; import org.jivesoftware.smackx.packet.DataForm; /** * A decorator for a {@link Form} to easily enable reading and updating * of node configuration. All operations read or update the underlying {@link DataForm}. * * <p>Unlike the {@link Form}.setAnswer(XXX)} methods, which throw an exception if the field does not * exist, all <b>ConfigureForm.setXXX</b> methods will create the field in the wrapped form * if it does not already exist. * * @author Robin Collier */ public class ConfigureForm extends Form { /** * Create a decorator from an existing {@link DataForm} that has been * retrieved from parsing a node configuration request. * * @param configDataForm */ public ConfigureForm(DataForm configDataForm) { super(configDataForm); } /** * Create a decorator from an existing {@link Form} for node configuration. * Typically, this can be used to create a decorator for an answer form * by using the result of {@link #createAnswerForm()} as the input parameter. * * @param nodeConfigForm */ public ConfigureForm(Form nodeConfigForm) { super(nodeConfigForm.getDataFormToSend()); } /** * Create a new form for configuring a node. This would typically only be used * when creating and configuring a node at the same time via {@link PubSubManager#createNode(String, Form)}, since * configuration of an existing node is typically accomplished by calling {@link LeafNode#getNodeConfiguration()} and * using the resulting form to create a answer form. See {@link #ConfigureForm(Form)}. * @param formType */ public ConfigureForm(FormType formType) { super(formType.toString()); } /** * Get the currently configured {@link AccessModel}, null if it is not set. * * @return The current {@link AccessModel} */ public AccessModel getAccessModel() { String value = getFieldValue(ConfigureNodeFields.access_model); if (value == null) return null; else return AccessModel.valueOf(value); } /** * Sets the value of access model. * * @param accessModel */ public void setAccessModel(AccessModel accessModel) { addField(ConfigureNodeFields.access_model, FormField.TYPE_LIST_SINGLE); setAnswer(ConfigureNodeFields.access_model.getFieldName(), getListSingle(accessModel.toString())); } /** * Returns the URL of an XSL transformation which can be applied to payloads in order to * generate an appropriate message body element. * * @return URL to an XSL */ public String getBodyXSLT() { return getFieldValue(ConfigureNodeFields.body_xslt); } /** * Set the URL of an XSL transformation which can be applied to payloads in order to * generate an appropriate message body element. * * @param bodyXslt The URL of an XSL */ public void setBodyXSLT(String bodyXslt) { addField(ConfigureNodeFields.body_xslt, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.body_xslt.getFieldName(), bodyXslt); } /** * The id's of the child nodes associated with a collection node (both leaf and collection). * * @return Iterator over the list of child nodes. */ public Iterator<String> getChildren() { return getFieldValues(ConfigureNodeFields.children); } /** * Set the list of child node ids that are associated with a collection node. * * @param children */ public void setChildren(List<String> children) { addField(ConfigureNodeFields.children, FormField.TYPE_TEXT_MULTI); setAnswer(ConfigureNodeFields.children.getFieldName(), children); } /** * Returns the policy that determines who may associate children with the node. * * @return The current policy */ public ChildrenAssociationPolicy getChildrenAssociationPolicy() { String value = getFieldValue(ConfigureNodeFields.children_association_policy); if (value == null) return null; else return ChildrenAssociationPolicy.valueOf(value); } /** * Sets the policy that determines who may associate children with the node. * * @param policy The policy being set */ public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy) { addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE); List<String> values = new ArrayList<String>(1); values.add(policy.toString()); setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), values); } /** * Iterator of JID's that are on the whitelist that determines who can associate child nodes * with the collection node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to * {@link ChildrenAssociationPolicy#whitelist}. * * @return Iterator over whitelist */ public Iterator<String> getChildrenAssociationWhitelist() { return getFieldValues(ConfigureNodeFields.children_association_whitelist); } /** * Set the JID's in the whitelist of users that can associate child nodes with the collection * node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to * {@link ChildrenAssociationPolicy#whitelist}. * * @param whitelist The list of JID's */ public void setChildrenAssociationWhitelist(List<String> whitelist) { addField(ConfigureNodeFields.children_association_whitelist, FormField.TYPE_JID_MULTI); setAnswer(ConfigureNodeFields.children_association_whitelist.getFieldName(), whitelist); } /** * Gets the maximum number of child nodes that can be associated with the collection node. * * @return The maximum number of child nodes */ public int getChildrenMax() { return Integer.parseInt(getFieldValue(ConfigureNodeFields.children_max)); } /** * Set the maximum number of child nodes that can be associated with a collection node. * * @param max The maximum number of child nodes. */ public void setChildrenMax(int max) { addField(ConfigureNodeFields.children_max, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.children_max.getFieldName(), max); } /** * Gets the collection node which the node is affiliated with. * * @return The collection node id */ public String getCollection() { return getFieldValue(ConfigureNodeFields.collection); } /** * Sets the collection node which the node is affiliated with. * * @param collection The node id of the collection node */ public void setCollection(String collection) { addField(ConfigureNodeFields.collection, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.collection.getFieldName(), collection); } /** * Gets the URL of an XSL transformation which can be applied to the payload * format in order to generate a valid Data Forms result that the client could * display using a generic Data Forms rendering engine. * * @return The URL of an XSL transformation */ public String getDataformXSLT() { return getFieldValue(ConfigureNodeFields.dataform_xslt); } /** * Sets the URL of an XSL transformation which can be applied to the payload * format in order to generate a valid Data Forms result that the client could * display using a generic Data Forms rendering engine. * * @param url The URL of an XSL transformation */ public void setDataformXSLT(String url) { addField(ConfigureNodeFields.dataform_xslt, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.dataform_xslt.getFieldName(), url); } /** * Does the node deliver payloads with event notifications. * * @return true if it does, false otherwise */ public boolean isDeliverPayloads() { return parseBoolean(getFieldValue(ConfigureNodeFields.deliver_payloads)); } /** * Sets whether the node will deliver payloads with event notifications. * * @param deliver true if the payload will be delivered, false otherwise */ public void setDeliverPayloads(boolean deliver) { addField(ConfigureNodeFields.deliver_payloads, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.deliver_payloads.getFieldName(), deliver); } /** * Determines who should get replies to items * * @return Who should get the reply */ public ItemReply getItemReply() { String value = getFieldValue(ConfigureNodeFields.itemreply); if (value == null) return null; else return ItemReply.valueOf(value); } /** * Sets who should get the replies to items * * @param reply Defines who should get the reply */ public void setItemReply(ItemReply reply) { addField(ConfigureNodeFields.itemreply, FormField.TYPE_LIST_SINGLE); setAnswer(ConfigureNodeFields.itemreply.getFieldName(), getListSingle(reply.toString())); } /** * Gets the maximum number of items to persisted to this node if {@link #isPersistItems()} is * true. * * @return The maximum number of items to persist */ public int getMaxItems() { return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_items)); } /** * Set the maximum number of items to persisted to this node if {@link #isPersistItems()} is * true. * * @param max The maximum number of items to persist */ public void setMaxItems(int max) { addField(ConfigureNodeFields.max_items, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.max_items.getFieldName(), max); } /** * Gets the maximum payload size in bytes. * * @return The maximum payload size */ public int getMaxPayloadSize() { return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_payload_size)); } /** * Sets the maximum payload size in bytes * * @param max The maximum payload size */ public void setMaxPayloadSize(int max) { addField(ConfigureNodeFields.max_payload_size, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.max_payload_size.getFieldName(), max); } /** * Gets the node type * * @return The node type */ public NodeType getNodeType() { String value = getFieldValue(ConfigureNodeFields.node_type); if (value == null) return null; else return NodeType.valueOf(value); } /** * Sets the node type * * @param type The node type */ public void setNodeType(NodeType type) { addField(ConfigureNodeFields.node_type, FormField.TYPE_LIST_SINGLE); setAnswer(ConfigureNodeFields.node_type.getFieldName(), getListSingle(type.toString())); } /** * Determines if subscribers should be notified when the configuration changes. * * @return true if they should be notified, false otherwise */ public boolean isNotifyConfig() { return parseBoolean(getFieldValue(ConfigureNodeFields.notify_config)); } /** * Sets whether subscribers should be notified when the configuration changes. * * @param notify true if subscribers should be notified, false otherwise */ public void setNotifyConfig(boolean notify) { addField(ConfigureNodeFields.notify_config, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.notify_config.getFieldName(), notify); } /** * Determines whether subscribers should be notified when the node is deleted. * * @return true if subscribers should be notified, false otherwise */ public boolean isNotifyDelete() { return parseBoolean(getFieldValue(ConfigureNodeFields.notify_delete)); } /** * Sets whether subscribers should be notified when the node is deleted. * * @param notify true if subscribers should be notified, false otherwise */ public void setNotifyDelete(boolean notify) { addField(ConfigureNodeFields.notify_delete, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.notify_delete.getFieldName(), notify); } /** * Determines whether subscribers should be notified when items are deleted * from the node. * * @return true if subscribers should be notified, false otherwise */ public boolean isNotifyRetract() { return parseBoolean(getFieldValue(ConfigureNodeFields.notify_retract)); } /** * Sets whether subscribers should be notified when items are deleted * from the node. * * @param notify true if subscribers should be notified, false otherwise */ public void setNotifyRetract(boolean notify) { addField(ConfigureNodeFields.notify_retract, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.notify_retract.getFieldName(), notify); } /** * Determines whether items should be persisted in the node. * * @return true if items are persisted */ public boolean isPersistItems() { return parseBoolean(getFieldValue(ConfigureNodeFields.persist_items)); } /** * Sets whether items should be persisted in the node. * * @param persist true if items should be persisted, false otherwise */ public void setPersistentItems(boolean persist) { addField(ConfigureNodeFields.persist_items, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.persist_items.getFieldName(), persist); } /** * Determines whether to deliver notifications to available users only. * * @return true if users must be available */ public boolean isPresenceBasedDelivery() { return parseBoolean(getFieldValue(ConfigureNodeFields.presence_based_delivery)); } /** * Sets whether to deliver notifications to available users only. * * @param presenceBased true if user must be available, false otherwise */ public void setPresenceBasedDelivery(boolean presenceBased) { addField(ConfigureNodeFields.presence_based_delivery, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.presence_based_delivery.getFieldName(), presenceBased); } /** * Gets the publishing model for the node, which determines who may publish to it. * * @return The publishing model */ public PublishModel getPublishModel() { String value = getFieldValue(ConfigureNodeFields.publish_model); if (value == null) return null; else return PublishModel.valueOf(value); } /** * Sets the publishing model for the node, which determines who may publish to it. * * @param publish The enum representing the possible options for the publishing model */ public void setPublishModel(PublishModel publish) { addField(ConfigureNodeFields.publish_model, FormField.TYPE_LIST_SINGLE); setAnswer(ConfigureNodeFields.publish_model.getFieldName(), getListSingle(publish.toString())); } /** * Iterator over the multi user chat rooms that are specified as reply rooms. * * @return The reply room JID's */ public Iterator<String> getReplyRoom() { return getFieldValues(ConfigureNodeFields.replyroom); } /** * Sets the multi user chat rooms that are specified as reply rooms. * * @param replyRooms The multi user chat room to use as reply rooms */ public void setReplyRoom(List<String> replyRooms) { addField(ConfigureNodeFields.replyroom, FormField.TYPE_LIST_MULTI); setAnswer(ConfigureNodeFields.replyroom.getFieldName(), replyRooms); } /** * Gets the specific JID's for reply to. * * @return The JID's */ public Iterator<String> getReplyTo() { return getFieldValues(ConfigureNodeFields.replyto); } /** * Sets the specific JID's for reply to. * * @param replyTos The JID's to reply to */ public void setReplyTo(List<String> replyTos) { addField(ConfigureNodeFields.replyto, FormField.TYPE_LIST_MULTI); setAnswer(ConfigureNodeFields.replyto.getFieldName(), replyTos); } /** * Gets the roster groups that are allowed to subscribe and retrieve items. * * @return The roster groups */ public Iterator<String> getRosterGroupsAllowed() { return getFieldValues(ConfigureNodeFields.roster_groups_allowed); } /** * Sets the roster groups that are allowed to subscribe and retrieve items. * * @param groups The roster groups */ public void setRosterGroupsAllowed(List<String> groups) { addField(ConfigureNodeFields.roster_groups_allowed, FormField.TYPE_LIST_MULTI); setAnswer(ConfigureNodeFields.roster_groups_allowed.getFieldName(), groups); } /** * Determines if subscriptions are allowed. * * @return true if subscriptions are allowed, false otherwise */ public boolean isSubscibe() { return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe)); } /** * Sets whether subscriptions are allowed. * * @param subscribe true if they are, false otherwise */ public void setSubscribe(boolean subscribe) { addField(ConfigureNodeFields.subscribe, FormField.TYPE_BOOLEAN); setAnswer(ConfigureNodeFields.subscribe.getFieldName(), subscribe); } /** * Gets the human readable node title. * * @return The node title */ public String getTitle() { return getFieldValue(ConfigureNodeFields.title); } /** * Sets a human readable title for the node. * * @param title The node title */ public void setTitle(String title) { addField(ConfigureNodeFields.title, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.title.getFieldName(), title); } /** * The type of node data, usually specified by the namespace of the payload (if any). * * @return The type of node data */ public String getDataType() { return getFieldValue(ConfigureNodeFields.type); } /** * Sets the type of node data, usually specified by the namespace of the payload (if any). * * @param type The type of node data */ public void setDataType(String type) { addField(ConfigureNodeFields.type, FormField.TYPE_TEXT_SINGLE); setAnswer(ConfigureNodeFields.type.getFieldName(), type); } @Override public String toString() { StringBuilder result = new StringBuilder(getClass().getName() + " Content ["); Iterator<FormField> fields = getFields(); while (fields.hasNext()) { FormField formField = fields.next(); result.append('('); result.append(formField.getVariable()); result.append(':'); Iterator<String> values = formField.getValues(); StringBuilder valuesBuilder = new StringBuilder(); while (values.hasNext()) { if (valuesBuilder.length() > 0) result.append(','); String value = (String)values.next(); valuesBuilder.append(value); } if (valuesBuilder.length() == 0) valuesBuilder.append("NOT SET"); result.append(valuesBuilder); result.append(')'); } result.append(']'); return result.toString(); } static private boolean parseBoolean(String fieldValue) { return ("1".equals(fieldValue) || "true".equals(fieldValue)); } private String getFieldValue(ConfigureNodeFields field) { FormField formField = getField(field.getFieldName()); return (formField.getValues().hasNext()) ? formField.getValues().next() : null; } private Iterator<String> getFieldValues(ConfigureNodeFields field) { FormField formField = getField(field.getFieldName()); return formField.getValues(); } private void addField(ConfigureNodeFields nodeField, String type) { String fieldName = nodeField.getFieldName(); if (getField(fieldName) == null) { FormField field = new FormField(fieldName); field.setType(type); addField(field); } } private List<String> getListSingle(String value) { List<String> list = new ArrayList<String>(1); list.add(value); return list; } }