1 /* 2 Copyright 2007-2014 Fraunhofer IGD, http://www.igd.fraunhofer.de 3 Fraunhofer-Gesellschaft - Institute for Computer Graphics Research 4 5 See the NOTICE file distributed with this work for additional 6 information regarding copyright ownership 7 8 Licensed under the Apache License, Version 2.0 (the "License"); 9 you may not use this file except in compliance with the License. 10 You may obtain a copy of the License at 11 12 http://www.apache.org/licenses/LICENSE-2.0 13 14 Unless required by applicable law or agreed to in writing, software 15 distributed under the License is distributed on an "AS IS" BASIS, 16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 See the License for the specific language governing permissions and 18 limitations under the License. 19 */ 20 package org.universAAL.middleware.ui.rdf; 21 22 import java.util.List; 23 24 import javax.xml.datatype.XMLGregorianCalendar; 25 26 import org.universAAL.middleware.owl.ManagedIndividual; 27 import org.universAAL.middleware.owl.MergedRestriction; 28 import org.universAAL.middleware.rdf.Resource; 29 import org.universAAL.middleware.rdf.TypeMapper; 30 import org.universAAL.middleware.ui.UICaller; 31 import org.universAAL.middleware.ui.owl.DialogType; 32 33 /** 34 * Forms can be used to describe dialogs in a modality- & layout-neutral way. A 35 * Form is a container of a set of {@link FormControl}s that specify the 36 * structure of the dialog as it should be presented to human users. This 37 * implementation organizes the {@link FormControl}s in three standard 38 * {@link Group}s: 39 * <dl> 40 * <dt>The submits group</dt> 41 * <dd>"buttons" that finish the whole dialog should be added to this group.</dd> 42 * <dt>The ioControls group</dt> 43 * <dd>all other form controls, no matter if input or output controls, or 44 * subgroups or even submits that trigger a sub-dialog should be added to this 45 * group.</dd> 46 * <dt>The stdButton group</dt> 47 * <dd>this group is reserved for a dialog management solution that has access 48 * to all dialogs and may be willing to add standard buttons beyond the 49 * application logic to reflect a system-wide behavior.</dd> 50 * </dl> 51 * Forms support four dialog types: 52 * <dl> 53 * <dt>Message</dt> 54 * <dd>The simplest dialog type that can be used to specify a text message to be 55 * presented as a notification. No standard buttons in the above sense are 56 * allowed. The text message will be used to construct a {@link SimpleOutput} 57 * object that is added as the single child to the ioControls group. The submits 58 * group will be constructed automatically with two buttons based on the 59 * constants {@link #ACK_MESSAGE_DELET} resp. {@link #ACK_MESSAGE_KEEP} and 60 * {@link #LABEL_MESSAGE_DELET} resp. {@link #LABEL_MESSAGE_KEEP}. These two 61 * buttons can be used by a user to state either 62 * "ok, I got it, you can delete the message" or "please preserve the message 63 * for later check", respectively. Normally, applications do not need to 64 * subscribe for user decision in this regard, but if they want, then they must 65 * use the value returned by the method {@link #getDialogID()} of the created 66 * form object, for subscribing to the UI bus.</dd> 67 * <dt>System Menu</dt> 68 * <dd>Reserved for a dialog management solution to present the system main 69 * menu. No submits group is allowed in this type of dialog.</dd> 70 * <dt>Subdialog</dt> 71 * <dd>A dialog related to a running dialog that must be "popped up" when the 72 * user presses a button in the originally running dialog without ending that 73 * running dialog. No standard buttons in the above sense are allowed. 74 * Applications must use instances of {@link SubdialogTrigger} for placing 75 * buttons that pop up a subdialog, instead of instances of {@link Submit} that 76 * should be used only for finishing the whole dialog. {@link Submit} instances 77 * must be added to the group returned by Form.getSubmits(), whereas 78 * {@link SubdialogTrigger} instances should be added to appropriate subgroups 79 * of the group returned by Form.getIOControls(). Subdialogs may affect the data 80 * to be used within the main dialog and hence the main dialog must be frozen 81 * until the application requests to continue with it. For this purpose, 82 * applications must call the method 83 * {@link UICaller#resumeDialog(String,org.universAAL.middleware.rdf.Resource)} 84 * of their output publisher after the subdialog finishes and they have 85 * processed its data and updated the form data of the main dialog. UI handlers 86 * may decide to render instances of {@link SubdialogTrigger} and {@link Submit} 87 * differently. Additionally, they may differentiate between events from these 88 * two types of buttons (and e.g. keep the parent dialog open until the 89 * subdialog loop is closed) or not. In any case, the middleware will 90 * re-dispatch the main dialog by calling 91 * {@link org.universAAL.middleware.ui.UIHandler#handleUICall(org.universAAL.middleware.ui.UIRequest)} 92 * of the output subscriber of the selected UI handler, as soon as the 93 * application requests to resume the dialog. In this way, the freezing and 94 * re-activating the main dialog is forced by the middleware even if the UI 95 * handler does not differentiate between events from instances of 96 * {@link SubdialogTrigger} and {@link Submit}.</dd> 97 * <dt>Standard Dialog</dt> 98 * <dd>All other forms must be constructed with this dialog type. All the three 99 * standard groups will be created automatically. Applications can get the 100 * standard groups "ioControls" and "submits" by calling the 101 * {@link #getIOControls()} and {@link #getSubmits()} methods respectively and 102 * construct their dialogs using these two groups as parent for their real form 103 * controls.</dd> 104 * </dl> 105 * 106 * @see <a 107 * href="ftp://ftp.igd.fraunhofer.de/outgoing/mtazari/persona/dialogPackage.jpg"> 108 * ftp://ftp.igd.fraunhofer.de/outgoing/mtazari/persona/dialogPackage.jpg</a> 109 * @author mtazari 110 * @author Carsten Stockloew 111 * @navassoc - "IOControlls\n Submits\n StandardButtons" - Group 112 * @navassoc - "parentDialog" 1 Form 113 */ 114 public class Form extends FormElement { 115 public static final String uAAL_DIALOG_NAMESPACE = uAAL_NAMESPACE_PREFIX 116 + "Dialog.owl#"; 117 public static final String MY_URI = uAAL_DIALOG_NAMESPACE + "Form"; 118 119 /** 120 * The submission ID if a user acknowledges that a dialog of type Message 121 * can be deleted. 122 */ 123 public static final String ACK_MESSAGE_DELET = "deleteMessage"; 124 125 /** 126 * The submission ID if a user acknowledges that a dialog of type Message 127 * must be preserved for later check. 128 */ 129 public static final String ACK_MESSAGE_KEEP = "preserveMessage"; 130 131 /** 132 * The label of a button associated with {@link #ACK_MESSAGE_DELET} as 133 * submission ID that is automatically added to dialogs of type Message. 134 */ 135 public static final Label LABEL_MESSAGE_DELET = new Label("Delete", null); 136 137 /** 138 * The label of a button associated with {@link #ACK_MESSAGE_KEEP} as 139 * submission ID that is automatically added to dialogs of type Message. 140 */ 141 public static final Label LABEL_MESSAGE_KEEP = new Label("Preserve", null); 142 143 /** 144 * An optional property of form objects that can be associated with a string 145 * representing the name of the component that created the form. 146 */ 147 public static final String PROP_DIALOG_CREATED_BY = uAAL_DIALOG_NAMESPACE 148 + "createdBy"; 149 150 /** 151 * The point of time in which a form object is instantiated. This property 152 * is set automatically with the value returned by 153 * {@link org.universAAL.middleware.rdf.TypeMapper#getCurrentDateTime()}. 154 */ 155 public static final String PROP_DIALOG_CREATION_TIME = uAAL_DIALOG_NAMESPACE 156 + "creationTimestamp"; 157 158 /** 159 * An optional property of form objects to indicate which form control 160 * should receive the focus when UI handlers start to present the dialog. It 161 * will be set automatically by the middleware whenever a running dialog is 162 * cut so that a seamless resumption of the dialog at a later point in time 163 * is guaranteed. UI handlers should check if this property is set. If yes, 164 * then they must simulate their logic of presenting the form until they 165 * reach the form control given as value of this property. At this point 166 * they can prompt the user for the next data entry. 167 */ 168 public static final String PROP_DIALOG_CURRENT_FOCUSED_CONTROL = uAAL_DIALOG_NAMESPACE 169 + "currentFocus"; 170 171 /** 172 * The {@link org.universAAL.middleware.rdf.Resource} containing the form 173 * data. Form data can be accessed using property paths; UI handlers, 174 * however, do not need to explicitly access this data normally, because 175 * they normally deal only with data associated with form controls that can 176 * be retrieved by calling {@link FormControl#getValue()} or set by calling 177 * {@link Input#storeUserInput(Object)}. Applications may create an instance 178 * of {@link org.universAAL.middleware.rdf.Resource} and set both their 179 * hidden data and initial data associated with the form controls using 180 * {@link org.universAAL.middleware.rdf.Resource#setPropertyPath(String[], Object)} 181 * . They can retrieve the form data from ui responses by calling 182 * {@link org.universAAL.middleware.ui.UIResponse#getUserInput(String[])} . 183 * Note: initial data to be associated with form controls can be set through 184 * their constructors, as well. 185 */ 186 public static final String PROP_DIALOG_DATA_ROOT = uAAL_DIALOG_NAMESPACE 187 + "dialogDataRoot"; 188 189 /** 190 * The type of the dialog represented by a form object as an instance of 191 * {@link DialogType}. See the above documentation of this class regarding 192 * the types of dialogs supported. 193 */ 194 public static final String PROP_DIALOG_TYPE = uAAL_DIALOG_NAMESPACE 195 + "dialogType"; 196 197 /** 198 * Applications must set this property for those form objects representing a 199 * dialog of type Subdialog using the value returned by 200 * {@link #getDialogID()} on the parent form from which the subdialog was 201 * triggered. 202 */ 203 public static final String PROP_PARENT_DIALOG_URI = uAAL_DIALOG_NAMESPACE 204 + "parentDialogURI"; 205 206 protected static final String PROP_ROOT_GROUP = uAAL_DIALOG_NAMESPACE 207 + "rootGroup"; 208 209 private static final String STD_BUTTONS_DIALOG_ID_SUFFIX = "stdButtons"; 210 211 static MergedRestriction getPPathRestriction(String[] pp, Resource pr) { 212 if (pp == null || pp.length == 0 || pr == null) 213 return null; 214 for (int i = 0; i < pp.length - 1; i++) { 215 Object o = pr.getProperty(pp[i]); 216 if (o == null) 217 return getPPathRestriction(pp, i, pr.getType()); 218 else if (o instanceof Resource) 219 pr = (Resource) o; 220 else 221 return null; 222 } 223 return ManagedIndividual.getClassRestrictionsOnProperty(pr.getType(), 224 pp[pp.length - 1]); 225 } 226 227 static MergedRestriction getPPathRestriction(String[] pp, int i, 228 String typeURI) { 229 if (typeURI == null) 230 return null; 231 232 MergedRestriction r = ManagedIndividual.getClassRestrictionsOnProperty( 233 typeURI, pp[i]); 234 if (i == pp.length - 1) 235 return r; 236 237 return (r == null) ? null : getPPathRestriction(pp, i + 1, r 238 .getPropTypeURI()); 239 } 240 241 static Object getValue(String[] pp, Resource pr) { 242 if (pp == null || pp.length == 0 || pr == null) 243 return null; 244 245 Object o = pr.getProperty(pp[0]); 246 for (int i = 1; o != null && i < pp.length; i++) { 247 if (!(o instanceof Resource)) 248 return null; 249 pr = (Resource) o; 250 o = pr.getProperty(pp[i]); 251 } 252 253 return o; 254 } 255 256 /** 257 * Constructs and returns a new form object representing an empty dialog of 258 * type {@link DialogType#stdDialog Standard Dialog} with proper initial 259 * configuration. See also the discussion of dialog types in the above 260 * documentation of this class. 261 * 262 * @param formTitle 263 * The form title giving the intent of the dialog. 264 * @param dataRoot 265 * The Resource containing the form data. It can be null, if no 266 * hidden data was prepared by the application and any initial 267 * value to be associated with form controls is going to be set 268 * through their constructors. See also 269 * {@link #PROP_DIALOG_DATA_ROOT}. 270 * @return A newly constructed form object representing an empty dialog of 271 * type {@link DialogType#stdDialog Standard Dialog} with proper 272 * initial configuration. 273 */ 274 public static Form newDialog(String formTitle, Resource dataRoot) { 275 Form f = new Form(formTitle, dataRoot); 276 f.props.put(PROP_DIALOG_TYPE, DialogType.stdDialog); 277 Group root = (Group) f.props.get(PROP_ROOT_GROUP); 278 new Group(root, new Label(Group.STD_IO_CONTROLS, null), null, null, 279 null); 280 new Group(root, new Label(Group.STD_SUBMITS, null), null, null, null); 281 new Group(root, new Label(Group.STD_STD_BUTTONS, null), null, null, 282 null); 283 return f; 284 } 285 286 /** 287 * An alternative for {@link #newDialog(String, Resource)} to be used if no 288 * specific data root is going to be specified but only the URI of its type. 289 */ 290 public static Form newDialog(String formTitle, String dataRootType) { 291 Form f = new Form(formTitle, dataRootType); 292 f.props.put(PROP_DIALOG_TYPE, DialogType.stdDialog); 293 Group root = (Group) f.props.get(PROP_ROOT_GROUP); 294 new Group(root, new Label(Group.STD_IO_CONTROLS, null), null, null, 295 null); 296 new Group(root, new Label(Group.STD_SUBMITS, null), null, null, null); 297 new Group(root, new Label(Group.STD_STD_BUTTONS, null), null, null, 298 null); 299 return f; 300 } 301 302 /** 303 * Constructs and returns a new form object representing a 304 * {@link DialogType#message Message} dialog that is ready to publish within 305 * an {@link org.universAAL.middleware.ui.UIRequest}. See also the 306 * discussion of dialog types in the above documentation of this class. 307 * 308 * @param formTitle 309 * The form title giving the intent of the dialog. 310 * @param message 311 * The text of the message. 312 * @return A newly constructed form object representing a 313 * {@link DialogType#message Message} dialog that is ready to 314 * publish within an {@link org.universAAL.middleware.ui.UIRequest}. 315 */ 316 public static Form newMessage(String formTitle, String message) { 317 Form f = new Form(formTitle, (Resource) null); 318 f.props.put(PROP_DIALOG_TYPE, DialogType.message); 319 Group root = (Group) f.props.get(PROP_ROOT_GROUP); 320 Group ctrls = new Group(root, new Label(Group.STD_IO_CONTROLS, null), 321 null, null, null); 322 new SimpleOutput(ctrls, null, null, message); 323 Group submits = new Group(root, new Label(Group.STD_SUBMITS, null), 324 null, null, null); 325 new Submit(submits, LABEL_MESSAGE_DELET, ACK_MESSAGE_DELET); 326 new Submit(submits, LABEL_MESSAGE_KEEP, ACK_MESSAGE_KEEP); 327 return f; 328 } 329 330 /** 331 * Constructs and returns a new form object representing an empty dialog of 332 * type {@link DialogType#subdialog Subdialog} with proper initial 333 * configuration. See also the discussion of dialog types in the above 334 * documentation of this class. To set hidden form data, you must first get 335 * the data root using {@link #getData()} and then add your data calling its 336 * method 337 * {@link org.universAAL.middleware.rdf.Resource#setPropertyPath(String[], Object)} 338 * . 339 * 340 * @param formTitle 341 * The form title giving the intent of the dialog. 342 * @param parentDialogURI 343 * The ID of the parent dialog. See also 344 * {@link #PROP_PARENT_DIALOG_URI}. 345 * @return A newly constructed form object representing an empty dialog of 346 * type {@link DialogType#subdialog Subdialog} with proper initial 347 * configuration. 348 */ 349 public static Form newSubdialog(String formTitle, String parentDialogURI) { 350 Form f = new Form(formTitle, (Resource) null); 351 f.props.put(PROP_DIALOG_TYPE, DialogType.subdialog); 352 f.props.put(PROP_PARENT_DIALOG_URI, new Resource(parentDialogURI)); 353 Group root = (Group) f.props.get(PROP_ROOT_GROUP); 354 new Group(root, new Label(Group.STD_IO_CONTROLS, null), null, null, 355 null); 356 new Group(root, new Label(Group.STD_SUBMITS, null), null, null, null); 357 return f; 358 } 359 360 public static Form newSystemMenu(String formTitle) { 361 Form f = new Form(formTitle, (Resource) null); 362 f.props.put(PROP_DIALOG_TYPE, DialogType.sysMenu); 363 Group root = (Group) f.props.get(PROP_ROOT_GROUP); 364 new Group(root, new Label(Group.STD_IO_CONTROLS, null), null, null, 365 null); 366 new Group(root, new Label(Group.STD_STD_BUTTONS, null), null, null, 367 null); 368 return f; 369 } 370 371 static boolean setValue(Resource pr, String[] pp, Object value, 372 MergedRestriction valueRestrictions) { 373 if (pp == null || pp.length == 0) 374 return false; 375 376 if (value instanceof List && ((List) value).isEmpty()) 377 value = null; 378 else if (value != null && valueRestrictions != null) { 379 Resource dummy = new Resource(); 380 dummy.setProperty(pp[pp.length - 1], value); 381 if (!valueRestrictions.hasMember(dummy)) 382 return false; 383 } 384 385 return pr.setPropertyPathFromOffset(pp, 0, value, true); 386 } 387 388 /** 389 * For usage by de-serializers only. 390 */ 391 public Form(String uri) { 392 super(uri); 393 addType(MY_URI, true); 394 } 395 396 /** 397 * @param uriPrefix 398 * @param numProps 399 */ 400 protected Form(String uriPrefix, int numProps) { 401 super(uriPrefix, numProps); 402 } 403 404 private Form(String formTitle, Resource dataRoot) { 405 super(uAAL_DIALOG_NAMESPACE, 5); 406 addType(MY_URI, true); 407 props.put(PROP_DIALOG_CREATION_TIME, TypeMapper.getCurrentDateTime()); 408 props.put(PROP_ROOT_GROUP, new Group(formTitle, this)); 409 props.put(PROP_DIALOG_DATA_ROOT, (dataRoot == null) ? new Resource() 410 : dataRoot); 411 } 412 413 private Form(String formTitle, String dataRootType) { 414 super(uAAL_DIALOG_NAMESPACE, 5); 415 addType(MY_URI, true); 416 props.put(PROP_DIALOG_CREATION_TIME, TypeMapper.getCurrentDateTime()); 417 props.put(PROP_ROOT_GROUP, new Group(formTitle, this)); 418 Resource root = ManagedIndividual.getInstance(dataRootType, null); 419 if (root == null) 420 root = new Resource(); 421 props.put(PROP_DIALOG_DATA_ROOT, root); 422 } 423 424 void finalizeGroupStructure() { 425 FormControl[] children = getRootGroup().getChildren(); 426 if (children != null) 427 for (int i = 0; i < children.length; i++) 428 if (children[i] instanceof Group) 429 ((Group) children[i]).setStructuralProps(0); 430 } 431 432 /** 433 * Returns the time at which the first time the form was created by an 434 * application. 435 * 436 * @see #PROP_DIALOG_CREATION_TIME 437 */ 438 public XMLGregorianCalendar getCreationTime() { 439 return (XMLGregorianCalendar) props.get(PROP_DIALOG_CREATION_TIME); 440 } 441 442 /** 443 * @see #PROP_DIALOG_CURRENT_FOCUSED_CONTROL 444 */ 445 public FormControl getCurrentFocusedControl() { 446 return (FormControl) props.get(PROP_DIALOG_CURRENT_FOCUSED_CONTROL); 447 } 448 449 /** 450 * @see #PROP_DIALOG_DATA_ROOT 451 */ 452 public Resource getData() { 453 return (Resource) props.get(PROP_DIALOG_DATA_ROOT); 454 } 455 456 /** 457 * @see #PROP_DIALOG_CREATED_BY 458 */ 459 public String getDialogCreator() { 460 return (String) props.get(PROP_DIALOG_CREATED_BY); 461 } 462 463 /** 464 * Returns the URI of this form object as its global unique ID. 465 */ 466 public String getDialogID() { 467 return uri; 468 } 469 470 /** 471 * @see #PROP_DIALOG_TYPE 472 */ 473 public DialogType getDialogType() { 474 return (DialogType) props.get(PROP_DIALOG_TYPE); 475 } 476 477 // private int getIndex(String index) { 478 // try { return Integer.parseInt(index); } catch (Exception e) { return -1; 479 // } 480 // } 481 482 /** 483 * Returns the standard group for UI controls in this form. See also the 484 * above documentation of this class concerning the standard groups within 485 * forms. 486 */ 487 public Group getIOControls() { 488 FormControl[] children = getRootGroup().getChildren(); 489 for (int i = 0; i < children.length; i++) 490 if (children[i] instanceof Group 491 && Group.STD_IO_CONTROLS.equals(children[i].getLabel() 492 .getText())) 493 return (Group) children[i]; 494 return null; 495 } 496 497 /** 498 * Returns the text message originally set if this form was created by 499 * {@link #newMessage(String, String)}. Otherwise, it returns null. 500 */ 501 public String getMessageContent() { 502 if (isMessage()) { 503 Group main = getIOControls(); 504 try { 505 return (String) ((SimpleOutput) main.getChildren()[0]) 506 .getContent(); 507 } catch (Exception e) { 508 } 509 } 510 return null; 511 } 512 513 /** 514 * Returns the parent dialog as an empty resource with 515 * {@link #PROP_PARENT_DIALOG_URI} as its URI. 516 */ 517 public Resource getParentDialogResource() { 518 return isSubdialog() ? (Resource) props.get(PROP_PARENT_DIALOG_URI) 519 : null; 520 } 521 522 /** 523 * @see #PROP_PARENT_DIALOG_URI 524 */ 525 public String getParentDialogURI() { 526 return isSubdialog() ? props.get(PROP_PARENT_DIALOG_URI).toString() 527 : null; 528 } 529 530 MergedRestriction getPPathRestriction(String[] pp) { 531 return getPPathRestriction(pp, getData()); 532 } 533 534 Group getRootGroup() { 535 return (Group) props.get(PROP_ROOT_GROUP); 536 } 537 538 /** 539 * Returns all the {@link Output} controls contained in the ioControls group 540 * (see the above documentation of this class concerning the standard groups 541 * within forms) that are likely to be relevant for human users in order to 542 * decide what to do with this dialog. The assumption is that there may be 543 * other {@link Output} controls specific to certain submissions possible 544 * within this dialog, which will be ignored by this method as they do not 545 * represent shared info. 546 */ 547 public Output[] getSharedOutputs() { 548 return getIOControls().getFirstLevelOutputs(); 549 } 550 551 /** 552 * Returns the pre-defined group of standard buttons in this form. See also 553 * the above documentation of this class concerning the standard groups 554 * within forms. 555 */ 556 public Group getStandardButtons() { 557 FormControl[] children = getRootGroup().getChildren(); 558 for (int i = 0; i < children.length; i++) 559 if (children[i] instanceof Group 560 && Group.STD_STD_BUTTONS.equals(children[i].getLabel() 561 .getText())) 562 return (Group) children[i]; 563 return null; 564 } 565 566 /** 567 * Reserved for use by a dialog management solution that has access to all 568 * dialogs and adds standard buttons beyond the application logic to reflect 569 * a system-wide behavior. 570 */ 571 public String getStandardButtonsDialogID() { 572 return uri + STD_BUTTONS_DIALOG_ID_SUFFIX; 573 } 574 575 /** 576 * Returns the standard group for submit buttons in this form. See also the 577 * above documentation of this class concerning the standard groups within 578 * forms. 579 */ 580 public Group getSubmits() { 581 FormControl[] children = getRootGroup().getChildren(); 582 for (int i = 0; i < children.length; i++) 583 if (children[i] instanceof Group 584 && Group.STD_SUBMITS.equals(children[i].getLabel() 585 .getText())) 586 return (Group) children[i]; 587 return null; 588 } 589 590 /** 591 * Returns the form title reflecting the intent of this dialog and 592 * originally set when constructing this form object. 593 */ 594 public String getTitle() { 595 try { 596 return getRootGroup().getLabel().getText(); 597 } catch (NullPointerException npe) { 598 return null; 599 } 600 } 601 602 String getTypeURI(String[] pp) { 603 MergedRestriction r = getPPathRestriction(pp); 604 return (r == null) ? null : r.getPropTypeURI(); 605 } 606 607 Object getValue(String[] pp) { 608 return getValue(pp, getData()); 609 } 610 611 /** 612 * Answers if this form object is created by 613 * {@link #newDialog(String, Resource)}. 614 * 615 * @see #PROP_DIALOG_TYPE 616 */ 617 public boolean isStandardDialog() { 618 return DialogType.stdDialog.equals(props.get(PROP_DIALOG_TYPE)); 619 } 620 621 /** 622 * Answers if this form object is created by 623 * {@link #newMessage(String, String)}. 624 * 625 * @see #PROP_DIALOG_TYPE 626 */ 627 public boolean isMessage() { 628 return DialogType.message.equals(props.get(PROP_DIALOG_TYPE)); 629 } 630 631 /** 632 * Answers if this form object is created by 633 * {@link #newSubdialog(String, String)}. 634 * 635 * @see #PROP_DIALOG_TYPE 636 */ 637 public boolean isSubdialog() { 638 return DialogType.subdialog.equals(props.get(PROP_DIALOG_TYPE)); 639 } 640 641 /** 642 * Answers if this form object is created by {@link #newSystemMenu(String)}. 643 * 644 * @see #PROP_DIALOG_TYPE 645 */ 646 public boolean isSystemMenu() { 647 return DialogType.sysMenu.equals(props.get(PROP_DIALOG_TYPE)); 648 } 649 650 /** 651 * @see #PROP_DIALOG_CURRENT_FOCUSED_CONTROL 652 */ 653 public void setCurrentFocusedControl(FormControl fc) { 654 if (fc != null) 655 props.put(PROP_DIALOG_CURRENT_FOCUSED_CONTROL, fc); 656 else 657 props.remove(PROP_DIALOG_CURRENT_FOCUSED_CONTROL); 658 } 659 660 /** 661 * @see #PROP_DIALOG_CREATED_BY 662 */ 663 public void setDialogCreator(String creator) { 664 if (creator != null) 665 props.put(PROP_DIALOG_CREATED_BY, creator); 666 } 667 668 boolean setValue(String[] pp, Object value, 669 MergedRestriction valueRestrictions) { 670 return setValue(getData(), pp, value, valueRestrictions); 671 } 672 673 /** 674 * Reserved for usage by the middleware. 675 */ 676 public void substituteData(Resource pr) { 677 Resource cur = getData(); 678 if (pr != null && pr != cur) { 679 String t0 = cur.getType(), t1 = pr.getType(); 680 if (t0 == t1 || (t0 != null && t0.equals(t1))) 681 props.put(PROP_DIALOG_DATA_ROOT, pr); 682 } 683 } 684 685 /** 686 * look for a FormControl within the form with the given URI. 687 * @param formControlURI 688 * @return the {@link FormControl} or null if not found. 689 */ 690 public FormControl searchFormControl(String formControlURI){ 691 FormControl[] children = getRootGroup().getChildren(); 692 boolean found = false; 693 int i = 0; 694 FormControl result = null; 695 while (!found 696 && i < children.length){ 697 found = children[i].getURI().equals(formControlURI); 698 if (found){ 699 result = children[i]; 700 } 701 else if (children[i] instanceof Group){ 702 result = ((Group)children[i]).searchFormControl(formControlURI); 703 found = (result != null); 704 } 705 i++; 706 } 707 return result; 708 } 709 }