001/** 002 * 003 * Copyright the original author or authors 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 */ 017package org.jivesoftware.smackx.pubsub; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.jivesoftware.smackx.xdata.Form; 023import org.jivesoftware.smackx.xdata.FormField; 024import org.jivesoftware.smackx.xdata.packet.DataForm; 025 026/** 027 * A decorator for a {@link Form} to easily enable reading and updating 028 * of node configuration. All operations read or update the underlying {@link DataForm}. 029 * 030 * <p>Unlike the {@link Form}.setAnswer(XXX)} methods, which throw an exception if the field does not 031 * exist, all <b>ConfigureForm.setXXX</b> methods will create the field in the wrapped form 032 * if it does not already exist. 033 * 034 * @author Robin Collier 035 */ 036public class ConfigureForm extends Form 037{ 038 /** 039 * Create a decorator from an existing {@link DataForm} that has been 040 * retrieved from parsing a node configuration request. 041 * 042 * @param configDataForm 043 */ 044 public ConfigureForm(DataForm configDataForm) 045 { 046 super(configDataForm); 047 } 048 049 /** 050 * Create a decorator from an existing {@link Form} for node configuration. 051 * Typically, this can be used to create a decorator for an answer form 052 * by using the result of {@link #createAnswerForm()} as the input parameter. 053 * 054 * @param nodeConfigForm 055 */ 056 public ConfigureForm(Form nodeConfigForm) 057 { 058 super(nodeConfigForm.getDataFormToSend()); 059 } 060 061 /** 062 * Create a new form for configuring a node. This would typically only be used 063 * when creating and configuring a node at the same time via {@link PubSubManager#createNode(String, Form)}, since 064 * configuration of an existing node is typically accomplished by calling {@link LeafNode#getNodeConfiguration()} and 065 * using the resulting form to create a answer form. See {@link #ConfigureForm(Form)}. 066 * @param formType 067 */ 068 public ConfigureForm(FormType formType) 069 { 070 super(formType.toString()); 071 } 072 073 /** 074 * Get the currently configured {@link AccessModel}, null if it is not set. 075 * 076 * @return The current {@link AccessModel} 077 */ 078 public AccessModel getAccessModel() 079 { 080 String value = getFieldValue(ConfigureNodeFields.access_model); 081 082 if (value == null) 083 return null; 084 else 085 return AccessModel.valueOf(value); 086 } 087 088 /** 089 * Sets the value of access model. 090 * 091 * @param accessModel 092 */ 093 public void setAccessModel(AccessModel accessModel) 094 { 095 addField(ConfigureNodeFields.access_model, FormField.TYPE_LIST_SINGLE); 096 setAnswer(ConfigureNodeFields.access_model.getFieldName(), getListSingle(accessModel.toString())); 097 } 098 099 /** 100 * Returns the URL of an XSL transformation which can be applied to payloads in order to 101 * generate an appropriate message body element. 102 * 103 * @return URL to an XSL 104 */ 105 public String getBodyXSLT() 106 { 107 return getFieldValue(ConfigureNodeFields.body_xslt); 108 } 109 110 /** 111 * Set the URL of an XSL transformation which can be applied to payloads in order to 112 * generate an appropriate message body element. 113 * 114 * @param bodyXslt The URL of an XSL 115 */ 116 public void setBodyXSLT(String bodyXslt) 117 { 118 addField(ConfigureNodeFields.body_xslt, FormField.TYPE_TEXT_SINGLE); 119 setAnswer(ConfigureNodeFields.body_xslt.getFieldName(), bodyXslt); 120 } 121 122 /** 123 * The id's of the child nodes associated with a collection node (both leaf and collection). 124 * 125 * @return list of child nodes. 126 */ 127 public List<String> getChildren() 128 { 129 return getFieldValues(ConfigureNodeFields.children); 130 } 131 132 /** 133 * Set the list of child node ids that are associated with a collection node. 134 * 135 * @param children 136 */ 137 public void setChildren(List<String> children) 138 { 139 addField(ConfigureNodeFields.children, FormField.TYPE_TEXT_MULTI); 140 setAnswer(ConfigureNodeFields.children.getFieldName(), children); 141 } 142 143 /** 144 * Returns the policy that determines who may associate children with the node. 145 * 146 * @return The current policy 147 */ 148 public ChildrenAssociationPolicy getChildrenAssociationPolicy() 149 { 150 String value = getFieldValue(ConfigureNodeFields.children_association_policy); 151 152 if (value == null) 153 return null; 154 else 155 return ChildrenAssociationPolicy.valueOf(value); 156 } 157 158 /** 159 * Sets the policy that determines who may associate children with the node. 160 * 161 * @param policy The policy being set 162 */ 163 public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy) 164 { 165 addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE); 166 List<String> values = new ArrayList<String>(1); 167 values.add(policy.toString()); 168 setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), values); 169 } 170 171 /** 172 * List of JID's that are on the whitelist that determines who can associate child nodes 173 * with the collection node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to 174 * {@link ChildrenAssociationPolicy#whitelist}. 175 * 176 * @return List of the whitelist 177 */ 178 public List<String> getChildrenAssociationWhitelist() 179 { 180 return getFieldValues(ConfigureNodeFields.children_association_whitelist); 181 } 182 183 /** 184 * Set the JID's in the whitelist of users that can associate child nodes with the collection 185 * node. This is only relevant if {@link #getChildrenAssociationPolicy()} is set to 186 * {@link ChildrenAssociationPolicy#whitelist}. 187 * 188 * @param whitelist The list of JID's 189 */ 190 public void setChildrenAssociationWhitelist(List<String> whitelist) 191 { 192 addField(ConfigureNodeFields.children_association_whitelist, FormField.TYPE_JID_MULTI); 193 setAnswer(ConfigureNodeFields.children_association_whitelist.getFieldName(), whitelist); 194 } 195 196 /** 197 * Gets the maximum number of child nodes that can be associated with the collection node. 198 * 199 * @return The maximum number of child nodes 200 */ 201 public int getChildrenMax() 202 { 203 return Integer.parseInt(getFieldValue(ConfigureNodeFields.children_max)); 204 } 205 206 /** 207 * Set the maximum number of child nodes that can be associated with a collection node. 208 * 209 * @param max The maximum number of child nodes. 210 */ 211 public void setChildrenMax(int max) 212 { 213 addField(ConfigureNodeFields.children_max, FormField.TYPE_TEXT_SINGLE); 214 setAnswer(ConfigureNodeFields.children_max.getFieldName(), max); 215 } 216 217 /** 218 * Gets the collection node which the node is affiliated with. 219 * 220 * @return The collection node id 221 */ 222 public String getCollection() 223 { 224 return getFieldValue(ConfigureNodeFields.collection); 225 } 226 227 /** 228 * Sets the collection node which the node is affiliated with. 229 * 230 * @param collection The node id of the collection node 231 */ 232 public void setCollection(String collection) 233 { 234 addField(ConfigureNodeFields.collection, FormField.TYPE_TEXT_SINGLE); 235 setAnswer(ConfigureNodeFields.collection.getFieldName(), collection); 236 } 237 238 /** 239 * Gets the URL of an XSL transformation which can be applied to the payload 240 * format in order to generate a valid Data Forms result that the client could 241 * display using a generic Data Forms rendering engine. 242 * 243 * @return The URL of an XSL transformation 244 */ 245 public String getDataformXSLT() 246 { 247 return getFieldValue(ConfigureNodeFields.dataform_xslt); 248 } 249 250 /** 251 * Sets the URL of an XSL transformation which can be applied to the payload 252 * format in order to generate a valid Data Forms result that the client could 253 * display using a generic Data Forms rendering engine. 254 * 255 * @param url The URL of an XSL transformation 256 */ 257 public void setDataformXSLT(String url) 258 { 259 addField(ConfigureNodeFields.dataform_xslt, FormField.TYPE_TEXT_SINGLE); 260 setAnswer(ConfigureNodeFields.dataform_xslt.getFieldName(), url); 261 } 262 263 /** 264 * Does the node deliver payloads with event notifications. 265 * 266 * @return true if it does, false otherwise 267 */ 268 public boolean isDeliverPayloads() 269 { 270 return parseBoolean(getFieldValue(ConfigureNodeFields.deliver_payloads)); 271 } 272 273 /** 274 * Sets whether the node will deliver payloads with event notifications. 275 * 276 * @param deliver true if the payload will be delivered, false otherwise 277 */ 278 public void setDeliverPayloads(boolean deliver) 279 { 280 addField(ConfigureNodeFields.deliver_payloads, FormField.TYPE_BOOLEAN); 281 setAnswer(ConfigureNodeFields.deliver_payloads.getFieldName(), deliver); 282 } 283 284 /** 285 * Determines who should get replies to items 286 * 287 * @return Who should get the reply 288 */ 289 public ItemReply getItemReply() 290 { 291 String value = getFieldValue(ConfigureNodeFields.itemreply); 292 293 if (value == null) 294 return null; 295 else 296 return ItemReply.valueOf(value); 297 } 298 299 /** 300 * Sets who should get the replies to items 301 * 302 * @param reply Defines who should get the reply 303 */ 304 public void setItemReply(ItemReply reply) 305 { 306 addField(ConfigureNodeFields.itemreply, FormField.TYPE_LIST_SINGLE); 307 setAnswer(ConfigureNodeFields.itemreply.getFieldName(), getListSingle(reply.toString())); 308 } 309 310 /** 311 * Gets the maximum number of items to persisted to this node if {@link #isPersistItems()} is 312 * true. 313 * 314 * @return The maximum number of items to persist 315 */ 316 public int getMaxItems() 317 { 318 return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_items)); 319 } 320 321 /** 322 * Set the maximum number of items to persisted to this node if {@link #isPersistItems()} is 323 * true. 324 * 325 * @param max The maximum number of items to persist 326 */ 327 public void setMaxItems(int max) 328 { 329 addField(ConfigureNodeFields.max_items, FormField.TYPE_TEXT_SINGLE); 330 setAnswer(ConfigureNodeFields.max_items.getFieldName(), max); 331 } 332 333 /** 334 * Gets the maximum payload size in bytes. 335 * 336 * @return The maximum payload size 337 */ 338 public int getMaxPayloadSize() 339 { 340 return Integer.parseInt(getFieldValue(ConfigureNodeFields.max_payload_size)); 341 } 342 343 /** 344 * Sets the maximum payload size in bytes 345 * 346 * @param max The maximum payload size 347 */ 348 public void setMaxPayloadSize(int max) 349 { 350 addField(ConfigureNodeFields.max_payload_size, FormField.TYPE_TEXT_SINGLE); 351 setAnswer(ConfigureNodeFields.max_payload_size.getFieldName(), max); 352 } 353 354 /** 355 * Gets the node type 356 * 357 * @return The node type 358 */ 359 public NodeType getNodeType() 360 { 361 String value = getFieldValue(ConfigureNodeFields.node_type); 362 363 if (value == null) 364 return null; 365 else 366 return NodeType.valueOf(value); 367 } 368 369 /** 370 * Sets the node type 371 * 372 * @param type The node type 373 */ 374 public void setNodeType(NodeType type) 375 { 376 addField(ConfigureNodeFields.node_type, FormField.TYPE_LIST_SINGLE); 377 setAnswer(ConfigureNodeFields.node_type.getFieldName(), getListSingle(type.toString())); 378 } 379 380 /** 381 * Determines if subscribers should be notified when the configuration changes. 382 * 383 * @return true if they should be notified, false otherwise 384 */ 385 public boolean isNotifyConfig() 386 { 387 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_config)); 388 } 389 390 /** 391 * Sets whether subscribers should be notified when the configuration changes. 392 * 393 * @param notify true if subscribers should be notified, false otherwise 394 */ 395 public void setNotifyConfig(boolean notify) 396 { 397 addField(ConfigureNodeFields.notify_config, FormField.TYPE_BOOLEAN); 398 setAnswer(ConfigureNodeFields.notify_config.getFieldName(), notify); 399 } 400 401 /** 402 * Determines whether subscribers should be notified when the node is deleted. 403 * 404 * @return true if subscribers should be notified, false otherwise 405 */ 406 public boolean isNotifyDelete() 407 { 408 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_delete)); 409 } 410 411 /** 412 * Sets whether subscribers should be notified when the node is deleted. 413 * 414 * @param notify true if subscribers should be notified, false otherwise 415 */ 416 public void setNotifyDelete(boolean notify) 417 { 418 addField(ConfigureNodeFields.notify_delete, FormField.TYPE_BOOLEAN); 419 setAnswer(ConfigureNodeFields.notify_delete.getFieldName(), notify); 420 } 421 422 /** 423 * Determines whether subscribers should be notified when items are deleted 424 * from the node. 425 * 426 * @return true if subscribers should be notified, false otherwise 427 */ 428 public boolean isNotifyRetract() 429 { 430 return parseBoolean(getFieldValue(ConfigureNodeFields.notify_retract)); 431 } 432 433 /** 434 * Sets whether subscribers should be notified when items are deleted 435 * from the node. 436 * 437 * @param notify true if subscribers should be notified, false otherwise 438 */ 439 public void setNotifyRetract(boolean notify) 440 { 441 addField(ConfigureNodeFields.notify_retract, FormField.TYPE_BOOLEAN); 442 setAnswer(ConfigureNodeFields.notify_retract.getFieldName(), notify); 443 } 444 445 /** 446 * Determines whether items should be persisted in the node. 447 * 448 * @return true if items are persisted 449 */ 450 public boolean isPersistItems() 451 { 452 return parseBoolean(getFieldValue(ConfigureNodeFields.persist_items)); 453 } 454 455 /** 456 * Sets whether items should be persisted in the node. 457 * 458 * @param persist true if items should be persisted, false otherwise 459 */ 460 public void setPersistentItems(boolean persist) 461 { 462 addField(ConfigureNodeFields.persist_items, FormField.TYPE_BOOLEAN); 463 setAnswer(ConfigureNodeFields.persist_items.getFieldName(), persist); 464 } 465 466 /** 467 * Determines whether to deliver notifications to available users only. 468 * 469 * @return true if users must be available 470 */ 471 public boolean isPresenceBasedDelivery() 472 { 473 return parseBoolean(getFieldValue(ConfigureNodeFields.presence_based_delivery)); 474 } 475 476 /** 477 * Sets whether to deliver notifications to available users only. 478 * 479 * @param presenceBased true if user must be available, false otherwise 480 */ 481 public void setPresenceBasedDelivery(boolean presenceBased) 482 { 483 addField(ConfigureNodeFields.presence_based_delivery, FormField.TYPE_BOOLEAN); 484 setAnswer(ConfigureNodeFields.presence_based_delivery.getFieldName(), presenceBased); 485 } 486 487 /** 488 * Gets the publishing model for the node, which determines who may publish to it. 489 * 490 * @return The publishing model 491 */ 492 public PublishModel getPublishModel() 493 { 494 String value = getFieldValue(ConfigureNodeFields.publish_model); 495 496 if (value == null) 497 return null; 498 else 499 return PublishModel.valueOf(value); 500 } 501 502 /** 503 * Sets the publishing model for the node, which determines who may publish to it. 504 * 505 * @param publish The enum representing the possible options for the publishing model 506 */ 507 public void setPublishModel(PublishModel publish) 508 { 509 addField(ConfigureNodeFields.publish_model, FormField.TYPE_LIST_SINGLE); 510 setAnswer(ConfigureNodeFields.publish_model.getFieldName(), getListSingle(publish.toString())); 511 } 512 513 /** 514 * List of the multi user chat rooms that are specified as reply rooms. 515 * 516 * @return The reply room JID's 517 */ 518 public List<String> getReplyRoom() 519 { 520 return getFieldValues(ConfigureNodeFields.replyroom); 521 } 522 523 /** 524 * Sets the multi user chat rooms that are specified as reply rooms. 525 * 526 * @param replyRooms The multi user chat room to use as reply rooms 527 */ 528 public void setReplyRoom(List<String> replyRooms) 529 { 530 addField(ConfigureNodeFields.replyroom, FormField.TYPE_LIST_MULTI); 531 setAnswer(ConfigureNodeFields.replyroom.getFieldName(), replyRooms); 532 } 533 534 /** 535 * Gets the specific JID's for reply to. 536 * 537 * @return The JID's 538 */ 539 public List<String> getReplyTo() 540 { 541 return getFieldValues(ConfigureNodeFields.replyto); 542 } 543 544 /** 545 * Sets the specific JID's for reply to. 546 * 547 * @param replyTos The JID's to reply to 548 */ 549 public void setReplyTo(List<String> replyTos) 550 { 551 addField(ConfigureNodeFields.replyto, FormField.TYPE_LIST_MULTI); 552 setAnswer(ConfigureNodeFields.replyto.getFieldName(), replyTos); 553 } 554 555 /** 556 * Gets the roster groups that are allowed to subscribe and retrieve items. 557 * 558 * @return The roster groups 559 */ 560 public List<String> getRosterGroupsAllowed() 561 { 562 return getFieldValues(ConfigureNodeFields.roster_groups_allowed); 563 } 564 565 /** 566 * Sets the roster groups that are allowed to subscribe and retrieve items. 567 * 568 * @param groups The roster groups 569 */ 570 public void setRosterGroupsAllowed(List<String> groups) 571 { 572 addField(ConfigureNodeFields.roster_groups_allowed, FormField.TYPE_LIST_MULTI); 573 setAnswer(ConfigureNodeFields.roster_groups_allowed.getFieldName(), groups); 574 } 575 576 /** 577 * Determines if subscriptions are allowed. 578 * 579 * @return true if subscriptions are allowed, false otherwise 580 */ 581 public boolean isSubscibe() 582 { 583 return parseBoolean(getFieldValue(ConfigureNodeFields.subscribe)); 584 } 585 586 /** 587 * Sets whether subscriptions are allowed. 588 * 589 * @param subscribe true if they are, false otherwise 590 */ 591 public void setSubscribe(boolean subscribe) 592 { 593 addField(ConfigureNodeFields.subscribe, FormField.TYPE_BOOLEAN); 594 setAnswer(ConfigureNodeFields.subscribe.getFieldName(), subscribe); 595 } 596 597 /** 598 * Gets the human readable node title. 599 * 600 * @return The node title 601 */ 602 public String getTitle() 603 { 604 return getFieldValue(ConfigureNodeFields.title); 605 } 606 607 /** 608 * Sets a human readable title for the node. 609 * 610 * @param title The node title 611 */ 612 public void setTitle(String title) 613 { 614 addField(ConfigureNodeFields.title, FormField.TYPE_TEXT_SINGLE); 615 setAnswer(ConfigureNodeFields.title.getFieldName(), title); 616 } 617 618 /** 619 * The type of node data, usually specified by the namespace of the payload (if any). 620 * 621 * @return The type of node data 622 */ 623 public String getDataType() 624 { 625 return getFieldValue(ConfigureNodeFields.type); 626 } 627 628 /** 629 * Sets the type of node data, usually specified by the namespace of the payload (if any). 630 * 631 * @param type The type of node data 632 */ 633 public void setDataType(String type) 634 { 635 addField(ConfigureNodeFields.type, FormField.TYPE_TEXT_SINGLE); 636 setAnswer(ConfigureNodeFields.type.getFieldName(), type); 637 } 638 639 @Override 640 public String toString() 641 { 642 StringBuilder result = new StringBuilder(getClass().getName() + " Content ["); 643 644 for (FormField formField : getFields()) 645 { 646 result.append('('); 647 result.append(formField.getVariable()); 648 result.append(':'); 649 650 StringBuilder valuesBuilder = new StringBuilder(); 651 652 for (String value : formField.getValues()) 653 { 654 if (valuesBuilder.length() > 0) 655 result.append(','); 656 valuesBuilder.append(value); 657 } 658 659 if (valuesBuilder.length() == 0) 660 valuesBuilder.append("NOT SET"); 661 result.append(valuesBuilder); 662 result.append(')'); 663 } 664 result.append(']'); 665 return result.toString(); 666 } 667 668 static private boolean parseBoolean(String fieldValue) 669 { 670 return ("1".equals(fieldValue) || "true".equals(fieldValue)); 671 } 672 673 private String getFieldValue(ConfigureNodeFields field) 674 { 675 FormField formField = getField(field.getFieldName()); 676 677 return (formField.getValues().isEmpty()) ? null : formField.getValues().get(0); 678 } 679 680 private List<String> getFieldValues(ConfigureNodeFields field) 681 { 682 FormField formField = getField(field.getFieldName()); 683 684 return formField.getValues(); 685 } 686 687 private void addField(ConfigureNodeFields nodeField, String type) 688 { 689 String fieldName = nodeField.getFieldName(); 690 691 if (getField(fieldName) == null) 692 { 693 FormField field = new FormField(fieldName); 694 field.setType(type); 695 addField(field); 696 } 697 } 698 699 private List<String> getListSingle(String value) 700 { 701 List<String> list = new ArrayList<String>(1); 702 list.add(value); 703 return list; 704 } 705 706}