blob: f6fe1409af4dfa266b96a527b8f9ed141665b847 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
2 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14package org.jivesoftware.smackx.pubsub;
15
16import java.util.ArrayList;
17import java.util.Iterator;
18import java.util.List;
19
20import org.jivesoftware.smackx.Form;
21import org.jivesoftware.smackx.FormField;
22import org.jivesoftware.smackx.packet.DataForm;
23
24/**
25 * A decorator for a {@link Form} to easily enable reading and updating
26 * of node configuration. All operations read or update the underlying {@link DataForm}.
27 *
28 * <p>Unlike the {@link Form}.setAnswer(XXX)} methods, which throw an exception if the field does not
29 * exist, all <b>ConfigureForm.setXXX</b> methods will create the field in the wrapped form
30 * if it does not already exist.
31 *
32 * @author Robin Collier
33 */
34public class ConfigureForm extends Form
35{
36 /**
37 * Create a decorator from an existing {@link DataForm} that has been
38 * retrieved from parsing a node configuration request.
39 *
40 * @param configDataForm
41 */
42 public ConfigureForm(DataForm configDataForm)
43 {
44 super(configDataForm);
45 }
46
47 /**
48 * Create a decorator from an existing {@link Form} for node configuration.
49 * Typically, this can be used to create a decorator for an answer form
50 * by using the result of {@link #createAnswerForm()} as the input parameter.
51 *
52 * @param nodeConfigForm
53 */
54 public ConfigureForm(Form nodeConfigForm)
55 {
56 super(nodeConfigForm.getDataFormToSend());
57 }
58
59 /**
60 * Create a new form for configuring a node. This would typically only be used
61 * when creating and configuring a node at the same time via {@link PubSubManager#createNode(String, Form)}, since
62 * configuration of an existing node is typically accomplished by calling {@link LeafNode#getNodeConfiguration()} and
63 * using the resulting form to create a answer form. See {@link #ConfigureForm(Form)}.
64 * @param formType
65 */
66 public ConfigureForm(FormType formType)
67 {
68 super(formType.toString());
69 }
70
71 /**
72 * Get the currently configured {@link AccessModel}, null if it is not set.
73 *
74 * @return The current {@link AccessModel}
75 */
76 public AccessModel getAccessModel()
77 {
78 String value = getFieldValue(ConfigureNodeFields.access_model);
79
80 if (value == null)
81 return null;
82 else
83 return AccessModel.valueOf(value);
84 }
85
86 /**
87 * Sets the value of access model.
88 *
89 * @param accessModel
90 */
91 public void setAccessModel(AccessModel accessModel)
92 {
93 addField(ConfigureNodeFields.access_model, FormField.TYPE_LIST_SINGLE);
94 setAnswer(ConfigureNodeFields.access_model.getFieldName(), getListSingle(accessModel.toString()));
95 }
96
97 /**
98 * Returns the URL of an XSL transformation which can be applied to payloads in order to
99 * generate an appropriate message body element.
100 *
101 * @return URL to an XSL
102 */
103 public String getBodyXSLT()
104 {
105 return getFieldValue(ConfigureNodeFields.body_xslt);
106 }
107
108 /**
109 * Set the URL of an XSL transformation which can be applied to payloads in order to
110 * generate an appropriate message body element.
111 *
112 * @param bodyXslt The URL of an XSL
113 */
114 public void setBodyXSLT(String bodyXslt)
115 {
116 addField(ConfigureNodeFields.body_xslt, FormField.TYPE_TEXT_SINGLE);
117 setAnswer(ConfigureNodeFields.body_xslt.getFieldName(), bodyXslt);
118 }
119
120 /**
121 * The id's of the child nodes associated with a collection node (both leaf and collection).
122 *
123 * @return Iterator over the list of child nodes.
124 */
125 public Iterator<String> getChildren()
126 {
127 return getFieldValues(ConfigureNodeFields.children);
128 }
129
130 /**
131 * Set the list of child node ids that are associated with a collection node.
132 *
133 * @param children
134 */
135 public void setChildren(List<String> children)
136 {
137 addField(ConfigureNodeFields.children, FormField.TYPE_TEXT_MULTI);
138 setAnswer(ConfigureNodeFields.children.getFieldName(), children);
139 }
140
141 /**
142 * Returns the policy that determines who may associate children with the node.
143 *
144 * @return The current policy
145 */
146 public ChildrenAssociationPolicy getChildrenAssociationPolicy()
147 {
148 String value = getFieldValue(ConfigureNodeFields.children_association_policy);
149
150 if (value == null)
151 return null;
152 else
153 return ChildrenAssociationPolicy.valueOf(value);
154 }
155
156 /**
157 * Sets the policy that determines who may associate children with the node.
158 *
159 * @param policy The policy being set
160 */
161 public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy)
162 {
163 addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE);
164 List<String> values = new ArrayList<String>(1);
165 values.add(policy.toString());
166 setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), values);
167 }
168
169 /**
170 * Iterator of JID's that are on the whitelist that determines who can associate child nodes
171 * with the collection node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to
172 * {@link ChildrenAssociationPolicy#whitelist}.
173 *
174 * @return Iterator over whitelist
175 */
176 public Iterator<String> getChildrenAssociationWhitelist()
177 {
178 return getFieldValues(ConfigureNodeFields.children_association_whitelist);
179 }
180
181 /**
182 * Set the JID's in the whitelist of users that can associate child nodes with the collection
183 * node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to
184 * {@link ChildrenAssociationPolicy#whitelist}.
185 *
186 * @param whitelist The list of JID's
187 */
188 public void setChildrenAssociationWhitelist(List<String> whitelist)
189 {
190 addField(ConfigureNodeFields.children_association_whitelist, FormField.TYPE_JID_MULTI);
191 setAnswer(ConfigureNodeFields.children_association_whitelist.getFieldName(), whitelist);
192 }
193
194 /**
195 * Gets the maximum number of child nodes that can be associated with the collection node.
196 *
197 * @return The maximum number of child nodes
198 */
199 public int getChildrenMax()
200 {
201 return Integer.parseInt(getFieldValue(ConfigureNodeFields.children_max));
202 }
203
204 /**
205 * Set the maximum number of child nodes that can be associated with a collection node.
206 *
207 * @param max The maximum number of child nodes.
208 */
209 public void setChildrenMax(int max)
210 {
211 addField(ConfigureNodeFields.children_max, FormField.TYPE_TEXT_SINGLE);
212 setAnswer(ConfigureNodeFields.children_max.getFieldName(), max);
213 }
214
215 /**
216 * Gets the collection node which the node is affiliated with.
217 *
218 * @return The collection node id
219 */
220 public String getCollection()
221 {
222 return getFieldValue(ConfigureNodeFields.collection);
223 }
224
225 /**
226 * Sets the collection node which the node is affiliated with.
227 *
228 * @param collection The node id of the collection node
229 */
230 public void setCollection(String collection)
231 {
232 addField(ConfigureNodeFields.collection, FormField.TYPE_TEXT_SINGLE);
233 setAnswer(ConfigureNodeFields.collection.getFieldName(), collection);
234 }
235
236 /**
237 * Gets the URL of an XSL transformation which can be applied to the payload
238 * format in order to generate a valid Data Forms result that the client could
239 * display using a generic Data Forms rendering engine.
240 *
241 * @return The URL of an XSL transformation
242 */
243 public String getDataformXSLT()
244 {
245 return getFieldValue(ConfigureNodeFields.dataform_xslt);
246 }
247
248 /**
249 * Sets the URL of an XSL transformation which can be applied to the payload
250 * format in order to generate a valid Data Forms result that the client could
251 * display using a generic Data Forms rendering engine.
252 *
253 * @param url The URL of an XSL transformation
254 */
255 public void setDataformXSLT(String url)
256 {
257 addField(ConfigureNodeFields.dataform_xslt, FormField.TYPE_TEXT_SINGLE);
258 setAnswer(ConfigureNodeFields.dataform_xslt.getFieldName(), url);
259 }
260
261 /**
262 * Does the node deliver payloads with event notifications.
263 *
264 * @return true if it does, false otherwise
265 */
266 public boolean isDeliverPayloads()
267 {
268 return parseBoolean(getFieldValue(ConfigureNodeFields.deliver_payloads));
269 }
270
271 /**
272 * Sets whether the node will deliver payloads with event notifications.
273 *
274 * @param deliver true if the payload will be delivered, false otherwise
275 */
276 public void setDeliverPayloads(boolean deliver)
277 {
278 addField(ConfigureNodeFields.deliver_payloads, FormField.TYPE_BOOLEAN);
279 setAnswer(ConfigureNodeFields.deliver_payloads.getFieldName(), deliver);
280 }
281
282 /**
283 * Determines who should get replies to items
284 *
285 * @return Who should get the reply
286 */
287 public ItemReply getItemReply()
288 {
289 String value = getFieldValue(ConfigureNodeFields.itemreply);
290
291 if (value == null)
292 return null;
293 else
294 return ItemReply.valueOf(value);
295 }
296
297 /**
298 * Sets who should get the replies to items
299 *
300 * @param reply Defines who should get the reply
301 */
302 public void setItemReply(ItemReply reply)
303 {
304 addField(ConfigureNodeFields.itemreply, FormField.TYPE_LIST_SINGLE);
305 setAnswer(ConfigureNodeFields.itemreply.getFieldName(), getListSingle(reply.toString()));
306 }
307
308 /**
309 * Gets the maximum number of items to persisted to this node if {@link #isPersistItems()} is
310 * true.
311 *
312 * @return The maximum number of items to persist
313 */
314 public int getMaxItems()
315 {
316 return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_items));
317 }
318
319 /**
320 * Set the maximum number of items to persisted to this node if {@link #isPersistItems()} is
321 * true.
322 *
323 * @param max The maximum number of items to persist
324 */
325 public void setMaxItems(int max)
326 {
327 addField(ConfigureNodeFields.max_items, FormField.TYPE_TEXT_SINGLE);
328 setAnswer(ConfigureNodeFields.max_items.getFieldName(), max);
329 }
330
331 /**
332 * Gets the maximum payload size in bytes.
333 *
334 * @return The maximum payload size
335 */
336 public int getMaxPayloadSize()
337 {
338 return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_payload_size));
339 }
340
341 /**
342 * Sets the maximum payload size in bytes
343 *
344 * @param max The maximum payload size
345 */
346 public void setMaxPayloadSize(int max)
347 {
348 addField(ConfigureNodeFields.max_payload_size, FormField.TYPE_TEXT_SINGLE);
349 setAnswer(ConfigureNodeFields.max_payload_size.getFieldName(), max);
350 }
351
352 /**
353 * Gets the node type
354 *
355 * @return The node type
356 */
357 public NodeType getNodeType()
358 {
359 String value = getFieldValue(ConfigureNodeFields.node_type);
360
361 if (value == null)
362 return null;
363 else
364 return NodeType.valueOf(value);
365 }
366
367 /**
368 * Sets the node type
369 *
370 * @param type The node type
371 */
372 public void setNodeType(NodeType type)
373 {
374 addField(ConfigureNodeFields.node_type, FormField.TYPE_LIST_SINGLE);
375 setAnswer(ConfigureNodeFields.node_type.getFieldName(), getListSingle(type.toString()));
376 }
377
378 /**
379 * Determines if subscribers should be notified when the configuration changes.
380 *
381 * @return true if they should be notified, false otherwise
382 */
383 public boolean isNotifyConfig()
384 {
385 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_config));
386 }
387
388 /**
389 * Sets whether subscribers should be notified when the configuration changes.
390 *
391 * @param notify true if subscribers should be notified, false otherwise
392 */
393 public void setNotifyConfig(boolean notify)
394 {
395 addField(ConfigureNodeFields.notify_config, FormField.TYPE_BOOLEAN);
396 setAnswer(ConfigureNodeFields.notify_config.getFieldName(), notify);
397 }
398
399 /**
400 * Determines whether subscribers should be notified when the node is deleted.
401 *
402 * @return true if subscribers should be notified, false otherwise
403 */
404 public boolean isNotifyDelete()
405 {
406 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_delete));
407 }
408
409 /**
410 * Sets whether subscribers should be notified when the node is deleted.
411 *
412 * @param notify true if subscribers should be notified, false otherwise
413 */
414 public void setNotifyDelete(boolean notify)
415 {
416 addField(ConfigureNodeFields.notify_delete, FormField.TYPE_BOOLEAN);
417 setAnswer(ConfigureNodeFields.notify_delete.getFieldName(), notify);
418 }
419
420 /**
421 * Determines whether subscribers should be notified when items are deleted
422 * from the node.
423 *
424 * @return true if subscribers should be notified, false otherwise
425 */
426 public boolean isNotifyRetract()
427 {
428 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_retract));
429 }
430
431 /**
432 * Sets whether subscribers should be notified when items are deleted
433 * from the node.
434 *
435 * @param notify true if subscribers should be notified, false otherwise
436 */
437 public void setNotifyRetract(boolean notify)
438 {
439 addField(ConfigureNodeFields.notify_retract, FormField.TYPE_BOOLEAN);
440 setAnswer(ConfigureNodeFields.notify_retract.getFieldName(), notify);
441 }
442
443 /**
444 * Determines whether items should be persisted in the node.
445 *
446 * @return true if items are persisted
447 */
448 public boolean isPersistItems()
449 {
450 return parseBoolean(getFieldValue(ConfigureNodeFields.persist_items));
451 }
452
453 /**
454 * Sets whether items should be persisted in the node.
455 *
456 * @param persist true if items should be persisted, false otherwise
457 */
458 public void setPersistentItems(boolean persist)
459 {
460 addField(ConfigureNodeFields.persist_items, FormField.TYPE_BOOLEAN);
461 setAnswer(ConfigureNodeFields.persist_items.getFieldName(), persist);
462 }
463
464 /**
465 * Determines whether to deliver notifications to available users only.
466 *
467 * @return true if users must be available
468 */
469 public boolean isPresenceBasedDelivery()
470 {
471 return parseBoolean(getFieldValue(ConfigureNodeFields.presence_based_delivery));
472 }
473
474 /**
475 * Sets whether to deliver notifications to available users only.
476 *
477 * @param presenceBased true if user must be available, false otherwise
478 */
479 public void setPresenceBasedDelivery(boolean presenceBased)
480 {
481 addField(ConfigureNodeFields.presence_based_delivery, FormField.TYPE_BOOLEAN);
482 setAnswer(ConfigureNodeFields.presence_based_delivery.getFieldName(), presenceBased);
483 }
484
485 /**
486 * Gets the publishing model for the node, which determines who may publish to it.
487 *
488 * @return The publishing model
489 */
490 public PublishModel getPublishModel()
491 {
492 String value = getFieldValue(ConfigureNodeFields.publish_model);
493
494 if (value == null)
495 return null;
496 else
497 return PublishModel.valueOf(value);
498 }
499
500 /**
501 * Sets the publishing model for the node, which determines who may publish to it.
502 *
503 * @param publish The enum representing the possible options for the publishing model
504 */
505 public void setPublishModel(PublishModel publish)
506 {
507 addField(ConfigureNodeFields.publish_model, FormField.TYPE_LIST_SINGLE);
508 setAnswer(ConfigureNodeFields.publish_model.getFieldName(), getListSingle(publish.toString()));
509 }
510
511 /**
512 * Iterator over the multi user chat rooms that are specified as reply rooms.
513 *
514 * @return The reply room JID's
515 */
516 public Iterator<String> getReplyRoom()
517 {
518 return getFieldValues(ConfigureNodeFields.replyroom);
519 }
520
521 /**
522 * Sets the multi user chat rooms that are specified as reply rooms.
523 *
524 * @param replyRooms The multi user chat room to use as reply rooms
525 */
526 public void setReplyRoom(List<String> replyRooms)
527 {
528 addField(ConfigureNodeFields.replyroom, FormField.TYPE_LIST_MULTI);
529 setAnswer(ConfigureNodeFields.replyroom.getFieldName(), replyRooms);
530 }
531
532 /**
533 * Gets the specific JID's for reply to.
534 *
535 * @return The JID's
536 */
537 public Iterator<String> getReplyTo()
538 {
539 return getFieldValues(ConfigureNodeFields.replyto);
540 }
541
542 /**
543 * Sets the specific JID's for reply to.
544 *
545 * @param replyTos The JID's to reply to
546 */
547 public void setReplyTo(List<String> replyTos)
548 {
549 addField(ConfigureNodeFields.replyto, FormField.TYPE_LIST_MULTI);
550 setAnswer(ConfigureNodeFields.replyto.getFieldName(), replyTos);
551 }
552
553 /**
554 * Gets the roster groups that are allowed to subscribe and retrieve items.
555 *
556 * @return The roster groups
557 */
558 public Iterator<String> getRosterGroupsAllowed()
559 {
560 return getFieldValues(ConfigureNodeFields.roster_groups_allowed);
561 }
562
563 /**
564 * Sets the roster groups that are allowed to subscribe and retrieve items.
565 *
566 * @param groups The roster groups
567 */
568 public void setRosterGroupsAllowed(List<String> groups)
569 {
570 addField(ConfigureNodeFields.roster_groups_allowed, FormField.TYPE_LIST_MULTI);
571 setAnswer(ConfigureNodeFields.roster_groups_allowed.getFieldName(), groups);
572 }
573
574 /**
575 * Determines if subscriptions are allowed.
576 *
577 * @return true if subscriptions are allowed, false otherwise
578 */
579 public boolean isSubscibe()
580 {
581 return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe));
582 }
583
584 /**
585 * Sets whether subscriptions are allowed.
586 *
587 * @param subscribe true if they are, false otherwise
588 */
589 public void setSubscribe(boolean subscribe)
590 {
591 addField(ConfigureNodeFields.subscribe, FormField.TYPE_BOOLEAN);
592 setAnswer(ConfigureNodeFields.subscribe.getFieldName(), subscribe);
593 }
594
595 /**
596 * Gets the human readable node title.
597 *
598 * @return The node title
599 */
600 public String getTitle()
601 {
602 return getFieldValue(ConfigureNodeFields.title);
603 }
604
605 /**
606 * Sets a human readable title for the node.
607 *
608 * @param title The node title
609 */
610 public void setTitle(String title)
611 {
612 addField(ConfigureNodeFields.title, FormField.TYPE_TEXT_SINGLE);
613 setAnswer(ConfigureNodeFields.title.getFieldName(), title);
614 }
615
616 /**
617 * The type of node data, usually specified by the namespace of the payload (if any).
618 *
619 * @return The type of node data
620 */
621 public String getDataType()
622 {
623 return getFieldValue(ConfigureNodeFields.type);
624 }
625
626 /**
627 * Sets the type of node data, usually specified by the namespace of the payload (if any).
628 *
629 * @param type The type of node data
630 */
631 public void setDataType(String type)
632 {
633 addField(ConfigureNodeFields.type, FormField.TYPE_TEXT_SINGLE);
634 setAnswer(ConfigureNodeFields.type.getFieldName(), type);
635 }
636
637 @Override
638 public String toString()
639 {
640 StringBuilder result = new StringBuilder(getClass().getName() + " Content [");
641
642 Iterator<FormField> fields = getFields();
643
644 while (fields.hasNext())
645 {
646 FormField formField = fields.next();
647 result.append('(');
648 result.append(formField.getVariable());
649 result.append(':');
650
651 Iterator<String> values = formField.getValues();
652 StringBuilder valuesBuilder = new StringBuilder();
653
654 while (values.hasNext())
655 {
656 if (valuesBuilder.length() > 0)
657 result.append(',');
658 String value = (String)values.next();
659 valuesBuilder.append(value);
660 }
661
662 if (valuesBuilder.length() == 0)
663 valuesBuilder.append("NOT SET");
664 result.append(valuesBuilder);
665 result.append(')');
666 }
667 result.append(']');
668 return result.toString();
669 }
670
671 static private boolean parseBoolean(String fieldValue)
672 {
673 return ("1".equals(fieldValue) || "true".equals(fieldValue));
674 }
675
676 private String getFieldValue(ConfigureNodeFields field)
677 {
678 FormField formField = getField(field.getFieldName());
679
680 return (formField.getValues().hasNext()) ? formField.getValues().next() : null;
681 }
682
683 private Iterator<String> getFieldValues(ConfigureNodeFields field)
684 {
685 FormField formField = getField(field.getFieldName());
686
687 return formField.getValues();
688 }
689
690 private void addField(ConfigureNodeFields nodeField, String type)
691 {
692 String fieldName = nodeField.getFieldName();
693
694 if (getField(fieldName) == null)
695 {
696 FormField field = new FormField(fieldName);
697 field.setType(type);
698 addField(field);
699 }
700 }
701
702 private List<String> getListSingle(String value)
703 {
704 List<String> list = new ArrayList<String>(1);
705 list.add(value);
706 return list;
707 }
708
709}