| 1 10 package org.mmbase.applications.editwizard; 11 12 import org.mmbase.bridge.Cloud; 13 import org.mmbase.bridge.util.Queries; 14 import org.mmbase.storage.search.RelationStep; 16 import org.mmbase.cache.Cache; 17 18 import org.mmbase.applications.dove.*; 19 20 import org.mmbase.util.ResourceWatcher; 21 import org.mmbase.util.ResourceLoader; 22 import org.mmbase.util.logging.*; 23 import org.mmbase.util.xml.URIResolver; 24 import org.mmbase.util.XMLEntityResolver; 25 26 import org.w3c.dom.*; 27 28 import java.net.URL ; 29 import java.io.Writer ; 30 31 import java.util.*; 32 33 import javax.servlet.ServletRequest ; 34 35 import javax.xml.transform.TransformerException ; 36 37 38 49 public class Wizard implements org.mmbase.util.SizeMeasurable { 50 private static final Logger log = Logging.getLoggerInstance(Wizard.class); 51 public static final String PUBLIC_ID_EDITWIZARD_1_0 = "-//MMBase//DTD editwizard 1.0//EN"; 52 public static final String PUBLIC_ID_EDITWIZARD_1_0_FAULT = "-//MMBase/DTD editwizard 1.0//EN"; 53 public static final String DTD_EDITWIZARD_1_0 = "wizard-schema_1_0.dtd"; 54 55 56 static { 57 XMLEntityResolver.registerPublicID(PUBLIC_ID_EDITWIZARD_1_0, DTD_EDITWIZARD_1_0, Wizard.class); 58 XMLEntityResolver.registerPublicID(PUBLIC_ID_EDITWIZARD_1_0_FAULT, DTD_EDITWIZARD_1_0, Wizard.class); 59 } 60 61 private static WizardSchemaCache wizardSchemaCache; 63 private static NodeCache nodeCache; 64 65 static { 66 wizardSchemaCache = new WizardSchemaCache(); 67 wizardSchemaCache.putCache(); 68 nodeCache = new NodeCache(); 69 nodeCache.putCache(); 70 } 71 72 75 private Cloud cloud; 76 77 private URIResolver uriResolver = null; 79 80 private String context = null; 82 83 private String name; 85 86 private String objectNumber; 89 90 private String wizardName; 92 93 private String dataId; 95 96 private String currentFormId; 98 99 private URL wizardStylesheetFile; 101 private String sessionId; 102 private String sessionKey = "editwizard"; 103 private String referrer = ""; 104 private String templatesDir = null; 105 private String timezone; 106 107 112 private Document schema; 113 private Document data; 114 private Document originalData; 115 116 private Map binaries = new HashMap(); 118 private Map binaryNames = new HashMap(); 119 private Map binaryPaths = new HashMap(); 120 121 private Map variables = new HashMap(); 123 124 private Document constraints; 126 127 private long listQueryTimeOut = 60 * 60; 129 130 private WizardDatabaseConnector databaseConnector; 132 133 136 private boolean mayBeClosed = false; 137 138 141 private boolean startWizard = false; 142 143 147 private WizardCommand startWizardCmd = null; 148 149 152 private boolean committed = false; 153 154 155 158 private String popupId = ""; 159 private boolean debug = false; 160 161 171 public Wizard(String context, URIResolver uri, String wizardname, String dataid, Cloud cloud) throws WizardException { 172 Config.WizardConfig wizardConfig = new Config.WizardConfig(); 173 wizardConfig.objectNumber = dataid; 174 wizardConfig.wizard = wizardname; 175 initialize(context, uri, wizardConfig, cloud); 176 } 177 178 186 public Wizard(String context, URIResolver uri, 187 Config.WizardConfig wizardConfig, Cloud cloud) throws WizardException { 188 initialize(context, uri, wizardConfig, cloud); 189 } 190 191 public int getByteSize() { 192 return getByteSize(new org.mmbase.util.SizeOf()); 193 } 194 195 public int getByteSize(org.mmbase.util.SizeOf sizeof) { 196 return sizeof.sizeof(cloud) + sizeof.sizeof(uriResolver) + 197 sizeof.sizeof(schema) + sizeof.sizeof(data) + 198 sizeof.sizeof(originalData) + sizeof.sizeof(binaries) + 199 sizeof.sizeof(binaryNames) + sizeof.sizeof(binaryPaths) + 200 sizeof.sizeof(constraints); 201 } 202 203 private void initialize(String c, URIResolver uri, Config.WizardConfig wizardConfig, Cloud cloud) throws WizardException { 204 context = c; 205 uriResolver = uri; 206 constraints = Utils.parseXML("<constraints/>"); 207 208 databaseConnector = new WizardDatabaseConnector(); 210 databaseConnector.setUserInfo(cloud); 211 212 this.cloud = cloud; 214 215 variables.put("username", cloud.getUser().getIdentifier()); 217 218 loadWizard(wizardConfig); 220 } 221 222 public void setSessionId(String s) { 223 sessionId = s; 224 } 225 226 public void setSessionKey(String s) { 227 sessionKey = s; 228 } 229 230 public void setReferrer(String s) { 231 referrer = s; 232 } 233 234 public void setTemplatesDir(String f) { 235 templatesDir = f; 236 } 237 238 public void setTimezone(String s) { 239 timezone = s; 240 } 241 242 public String getObjectNumber() { 243 return objectNumber; 244 } 245 246 public String getDataId() { 247 return dataId; 248 } 249 250 public Document getData() { 251 return data; 252 } 253 254 public Document getSchema() { 255 return schema; 256 } 257 258 public Document getPreForm() throws WizardException { 259 return getPreForm(wizardName); 260 } 261 262 public Document getPreForm(String instanceName) throws WizardException { 263 Node datastart = Utils.selectSingleNode(data, "/data/*"); 264 265 return createPreHtml(schema.getDocumentElement(), currentFormId, 266 datastart, instanceName); 267 } 268 269 270 273 public boolean committed() { 274 return committed; 275 } 276 277 280 public boolean mayBeClosed() { 281 return mayBeClosed; 282 } 283 284 287 public boolean startWizard() { 288 return startWizard; 289 } 290 291 299 protected boolean checkNode(String objectNumber, String operation) throws WizardException { 300 Object nodeObj = nodeCache.get(objectNumber); 301 302 if (nodeObj == null) { 303 NodeList nodes = Utils.selectNodeList(data, ".//*[@number='" + objectNumber + "']"); 304 305 if ((nodes != null) && (nodes.getLength() > 0)) { 306 nodeObj = nodes.item(0); 307 } else { 308 if (objectNumber == null || objectNumber.equals("")) { 309 log.warn("Checking security for objectNumber '" + objectNumber + "' "); return true; 313 } 314 nodeObj = databaseConnector.getDataNode(null, objectNumber, null); 317 } 318 319 nodeCache.put(objectNumber, nodeObj); 320 log.debug("Node loaded: " + nodeObj); 321 } else { 322 log.debug("Node found in cache: " + nodeObj); 323 } 324 325 Node node = (Node) nodeObj; 326 327 return (node != null) && 328 Utils.getAttribute(node, operation, "true").equals("true"); 329 } 330 331 336 protected boolean mayEditNode(String objectNumber) throws WizardException { 337 return checkNode(objectNumber, "maywrite"); 338 } 339 340 345 protected boolean mayDeleteNode(String objectNumber) 346 throws WizardException { 347 return checkNode(objectNumber, "maydelete"); 348 } 349 350 353 public WizardCommand getStartWizardCommand() { 354 return startWizardCmd; 355 } 356 357 361 protected void storeConfigurationAttributes(Config.WizardConfig wizardConfig) { 362 variables.put("wizardname", wizardName); 363 364 variables.putAll(wizardConfig.getAttributes()); 367 } 368 369 374 protected void loadWizard(Config.WizardConfig wizardConfig) throws WizardException { 375 if (wizardConfig.wizard == null) { 376 throw new WizardException("Wizardname may not be null"); 377 } 378 379 wizardName = wizardConfig.wizard; 380 popupId = wizardConfig.popupId; 381 dataId = wizardConfig.objectNumber; 382 debug = wizardConfig.debug; 383 384 URL wizardSchemaFile; 385 try { 386 wizardSchemaFile = uriResolver.resolveToURL(wizardName + ".xml", null); 387 } catch (Exception e) { 388 throw new WizardException(e); 389 } 390 if (wizardSchemaFile == null) { 391 throw new WizardException("Could not resolve wizard " + wizardName + ".xml with " + uriResolver); 392 } 393 try { 394 wizardStylesheetFile = uriResolver.resolveToURL(Config.wizardStyleSheet, null); 395 } catch (Exception e) { 396 throw new WizardException(e); 397 } 398 399 if (wizardStylesheetFile == null) { 400 throw new WizardException("Could not resolve XSL '" + Config.wizardStyleSheet + "' with " + uriResolver); 401 } 402 storeConfigurationAttributes(wizardConfig); 404 405 loadSchema(wizardSchemaFile); 408 409 if (dataId != null) { 414 originalData = Utils.emptyDocument(); 416 417 if (dataId.equals("new")) { 418 log.debug("Creating new xml"); 419 420 Node objectdef = Utils.selectSingleNode(schema, "./wizard-schema/action[@type='create']"); 422 423 if (objectdef == null) { 424 throw new WizardException("You tried to start a create action in the wizard, but no create action was defined in the wizard schema. Please supply a <action type='create' /> section in the wizard."); 425 } 426 427 objectdef = objectdef.cloneNode(true); 428 log.debug("Going to creating a new object " + objectdef.getNodeName() + " type " + Utils.getAttribute(objectdef, "type")); 429 430 data = Utils.parseXML("<data />"); 432 433 Node parent = data.getDocumentElement(); 434 435 Node newobject = databaseConnector.createObject(data, parent, objectdef, variables); 437 438 if (newobject == null) { 439 throw new WizardException("Could not create new object. Did you forget to add an 'object' subtag?"); 440 } 441 442 parent.appendChild(newobject); 443 databaseConnector.tagDataNodes(data); 444 dataId = Utils.getAttribute(newobject, "number"); 445 446 if (log.isDebugEnabled()) { 447 log.debug("Created object " + newobject.getNodeName() + " type " + Utils.getAttribute(newobject, "type") + ", id " + dataId); 448 } 449 } else { 450 loadData(); 451 } 452 } 453 454 if (currentFormId == null) { 456 currentFormId = determineNextForm("first"); 457 } 458 } 459 460 463 protected void loadData() throws WizardException { 464 data = databaseConnector.load(schema.getDocumentElement(), dataId); 467 468 if (data == null) { 469 throw new WizardException("The requested object could not be loaded from MMBase. ObjectNumber:" + dataId + 470 ". Does the object exists and do you have enough rights to load this object."); 471 } 472 originalData = Utils.emptyDocument(); 474 475 476 originalData.appendChild(originalData.importNode(data.getDocumentElement().cloneNode(true), true)); 478 } 479 480 487 public void processRequest(ServletRequest req) throws WizardException { 488 String curform = req.getParameter("curform"); 489 490 if ((curform != null) && !curform.equals("")) { 491 currentFormId = curform; 492 } 493 494 storeValues(req); 495 processCommands(req); 496 } 497 498 507 public void writeHtmlForm(Writer out, String instanceName) throws WizardException, TransformerException { 508 writeHtmlForm(out, instanceName, null); 509 } 510 511 522 public void writeHtmlForm(Writer out, String instanceName, Map externParams) 523 throws WizardException, TransformerException { 524 if (log.isDebugEnabled()) { 525 log.debug("writeHtmlForm for " + instanceName); 526 } 527 528 Node datastart = Utils.selectSingleNode(data, "/data/*"); 529 530 Document preForm = getPreForm(instanceName); 532 Validator.validate(preForm, schema); 533 534 Map params = new HashMap(variables); 535 params.put("ew_context", context); 536 537 params.put("sessionid", sessionId); 539 params.put("sessionkey", sessionKey); 540 params.put("referrer", referrer); 541 params.put("referrer_encoded", java.net.URLEncoder.encode(referrer)); 542 params.put("language", cloud.getLocale().getLanguage()); 543 params.put("timezone", timezone); 544 params.put("cloud", cloud); 545 546 if (templatesDir != null) { 547 params.put("templatedir", templatesDir); 548 } 549 550 if (externParams != null && !externParams.isEmpty()) { 551 params.putAll(externParams); 552 } 553 554 Utils.transformNode(preForm, wizardStylesheetFile, uriResolver, out, params); 555 } 556 557 562 private void storeValues(ServletRequest req) throws WizardException { 563 Enumeration list = req.getParameterNames(); 564 log.debug("Synchronizing editor data, using the request"); 565 566 String formEncoding = req.getCharacterEncoding(); 567 boolean hasEncoding = formEncoding != null; 568 if (!hasEncoding) { 569 log.debug("Request did not mention encoding, supposing UTF-8, as JSP's are"); 570 formEncoding = "UTF-8"; 571 } else { 572 log.debug("found encoding in the request: " + formEncoding); 573 } 574 575 while (list.hasMoreElements()) { 576 String name = (String ) list.nextElement(); 577 578 if (name.startsWith("internal_")) { 579 log.debug("Ignoring parameter " + name); 580 } else { 581 log.debug("Processing parameter " + name); 582 583 String [] ids = processFormName(name); 584 if (log.isDebugEnabled()) { 585 log.debug("found ids: " + ((ids == null) ? "null" : (" " + java.util.Arrays.asList(ids)))); 586 } 587 if (ids != null) { 588 String result; 589 if (!hasEncoding) { 590 try { 591 result = new String (req.getParameter(name).getBytes("ISO-8859-1"), formEncoding); 592 if (log.isDebugEnabled()) { 593 log.debug("Found in post '" + req.getParameter(name) + "' -> '" + result + "'"); 594 } 595 } catch (java.io.UnsupportedEncodingException e) { 596 log.warn(e.toString()); 597 result = req.getParameter(name); 598 } 599 } else { result = req.getParameter(name); 601 } 602 603 if (result.equals("date")) { 604 result = buildDate(req, name); 605 } 606 if (result.equals("time")) { 607 result = buildTime(req, name); 608 } 609 if (result.equals("datetime")) { 610 result = buildDateTime(req, name); 611 } 612 if (result.equals("duration")) { 613 result = buildDuration(req, name); 614 } 615 616 storeValue(ids[0], ids[1], result); 617 } 618 } 619 } 620 } 621 622 625 private Calendar getCalendar() { 626 if (timezone != null) { 627 TimeZone tz = TimeZone.getTimeZone(timezone); 628 if (tz.getID().equals(timezone)) { 629 return Calendar.getInstance(tz); 630 } 631 else { 632 return Calendar.getInstance(); 633 } 634 } 635 else { 636 return Calendar.getInstance(); 637 } 638 } 639 640 private String buildDate(ServletRequest req, String name) { 641 try { 642 int day = Integer.parseInt(req.getParameter("internal_" + name + "_day")); 643 int month = Integer.parseInt(req.getParameter("internal_" + name + "_month")); 644 int year = Integer.parseInt(req.getParameter("internal_" + name + "_year")); 645 646 Calendar cal = getCalendar(); 647 cal.set(year, month - 1, day, 0, 0, 0); 648 return "" + cal.getTimeInMillis() / 1000; 649 } catch (RuntimeException e) { log.debug("Failed to parse date for " + name + " " + e.getMessage()); 651 return ""; 652 } 653 } 654 655 private String buildTime(ServletRequest req, String name) { 656 try { 657 int hours = Integer.parseInt(req.getParameter("internal_" + name + "_hours")); 658 int minutes = Integer.parseInt(req.getParameter("internal_" + name + "_minutes")); 659 660 Calendar cal = getCalendar(); 661 cal.set(1970, 0, 1, hours, minutes, 0); 662 return "" + cal.getTimeInMillis() / 1000; 663 } catch (RuntimeException e) { log.debug("Failed to parse time for " + name + " " 665 + e.getMessage()); 666 return ""; 667 } 668 } 669 670 private String buildDateTime(ServletRequest req, String name) { 671 try { 672 int day = Integer.parseInt(req.getParameter("internal_" + name + "_day")); 673 int month = Integer.parseInt(req.getParameter("internal_" + name + "_month")); 674 int year = Integer.parseInt(req.getParameter("internal_" + name + "_year")); 675 int hours = Integer.parseInt(req.getParameter("internal_" + name + "_hours")); 676 int minutes = Integer.parseInt(req.getParameter("internal_" + name + "_minutes")); 677 678 Calendar cal = getCalendar(); 679 cal.set(year, month - 1, day, hours, minutes, 0); 680 return "" + cal.getTimeInMillis() / 1000; 681 } catch (RuntimeException e) { log.debug("Failed to parse datetime for " + name + " " 683 + e.getMessage()); 684 return ""; 685 } 686 } 687 688 private String buildDuration(ServletRequest req, String name) { 689 try { 690 int hours = Integer.parseInt(req.getParameter("internal_" + name + "_hours")); 691 int minutes = Integer.parseInt(req.getParameter("internal_" + name + "_minutes")); 692 int seconds = Integer.parseInt(req.getParameter("internal_" + name + "_seconds")); 693 694 Calendar cal = getCalendar(); 695 cal.set(1970, 0, 1, hours, minutes, seconds); 696 return "" + cal.getTimeInMillis() / 1000; 697 } catch (RuntimeException e) { log.debug("Failed to parse duration for " + name + " " + e.getMessage()); 699 return ""; 700 } 701 } 702 703 704 705 717 public String determineNextForm(String direction) { 718 String stepDirection = direction; 719 720 if (stepDirection == null) { 721 stepDirection = "first"; 722 } 723 724 String nextformid = "FORM_NOT_FOUND"; 729 Node laststep = Utils.selectSingleNode(schema, 730 "//steps/step[@form-schema='" + currentFormId + "']"); 731 Node nextstep = null; 732 733 if ((laststep == null) || stepDirection.equals("first")) { 736 nextstep = Utils.selectSingleNode(schema, "//steps/step"); 737 nextformid = Utils.getAttribute(nextstep, "form-schema"); 738 } else { 739 if (stepDirection.equals("previous")) { 740 nextstep = Utils.selectSingleNode(laststep, "./preceding-sibling::step"); 741 } else if (stepDirection.equals("last")) { 742 nextstep = Utils.selectSingleNode(laststep, "../step[position()=last()]"); 743 } else { 744 nextstep = Utils.selectSingleNode(laststep, "./following-sibling::step"); 745 } 746 747 if (nextstep == null) { 748 nextformid = "WIZARD_OUT_OF_BOUNDS"; 749 } else { 750 nextformid = Utils.getAttribute(nextstep, "form-schema"); 751 } 752 } 753 754 return nextformid; 755 } 756 757 762 public Document createPreHtml(String instanceName) throws WizardException { 763 Node datastart = Utils.selectSingleNode(data, "/data/*"); 764 765 return createPreHtml(schema.getDocumentElement(), "1", datastart, 766 instanceName); 767 } 768 769 782 public Document createPreHtml(Node wizardSchema, String formid, Node data, 783 String instanceName) throws WizardException { 784 if (log.isDebugEnabled()) { 785 log.debug("Create preHTML of " + instanceName); 786 } 787 788 Document preHtml = Utils.parseXML("<wizard instance=\"" + instanceName + "\" />"); 790 Node wizardnode = preHtml.getDocumentElement(); 791 792 NodeList globals = Utils.selectNodeList(wizardSchema, "title|subtitle|description"); 794 Utils.appendNodeList(globals, wizardnode); 795 796 Utils.createAndAppendNode(wizardnode, "curform", formid); 798 799 Node step = Utils.selectSingleNode(wizardSchema, "./steps/step[@form-schema='" + formid + "']"); 800 801 if (step != null) { 802 String otherformid = ""; 804 Node prevstep = Utils.selectSingleNode(step, "./preceding-sibling::step[1]"); 805 806 if (prevstep != null) { 807 otherformid = Utils.getAttribute(prevstep, "form-schema"); 808 } 809 810 Utils.createAndAppendNode(wizardnode, "prevform", otherformid); 811 812 otherformid = ""; 813 814 Node nextstep = Utils.selectSingleNode(step, "./following-sibling::step[1]"); 815 816 if (nextstep != null) { 817 otherformid = Utils.getAttribute(nextstep, "form-schema"); 818 } 819 820 Utils.createAndAppendNode(wizardnode, "nextform", otherformid); 821 } 822 823 NodeList formlist = Utils.selectNodeList(schema, "/*/form-schema"); 825 826 if (formlist.getLength() == 0) { throw new WizardException("No form-schema was found in the xml. Make sure at least one form-schema node is present."); 828 } 829 830 for (int f = 0; f < formlist.getLength(); f++) { 831 Node form = formlist.item(f); 832 833 Node prehtmlform = preHtml.createElement("form"); 835 Utils.copyAllAttributes(form, prehtmlform); 836 wizardnode.appendChild(prehtmlform); 837 838 NodeList props = Utils.selectNodeList(form, "title|subtitle|description"); 840 Utils.appendNodeList(props, prehtmlform); 841 842 createPreHtmlForm(prehtmlform, form, data); 844 } 845 846 NodeList optionlists = Utils.selectNodeList(wizardnode, ".//field/optionlist"); 850 851 for (int i = 0; i < optionlists.getLength(); i++) { 852 Node optionlist = optionlists.item(i); 853 854 String listname = Utils.getAttribute(optionlist, "select"); 855 856 if (listname != null && !listname.equals("")) { 858 log.debug("Handling optionlist: " + i + ": " + listname); 859 860 Node list = Utils.selectSingleNode(wizardSchema, "/*/lists/optionlist[@name='" + listname + "']"); 861 862 if (list == null) { 863 log.debug("Not found! Proceeding with next list."); 866 867 Element option = optionlist.getOwnerDocument().createElement("option"); 868 option.setAttribute("id", "-"); 869 Utils.storeText(option, 870 "Error: optionlist '" + listname + "' not found"); 871 optionlist.appendChild(option); 872 873 continue; 874 } 875 876 Node query = Utils.selectSingleNode(list, "query"); 878 long currentTime = new Date().getTime(); 879 long queryTimeOut = 1000 * Long.parseLong(Utils.getAttribute(list, 880 "query-timeout", String.valueOf(this.listQueryTimeOut))); 881 long lastExecuted = currentTime - queryTimeOut - 1; 882 883 if (query != null) { 884 String lastExecutedString = Utils.getAttribute(query, "last-executed", "never"); 885 886 if (!lastExecutedString.equals("never")) { 887 lastExecuted = Long.parseLong(lastExecutedString); 888 } 889 } 890 891 if ((query != null) && ((currentTime - lastExecuted) > queryTimeOut)) { 893 log.debug("Performing query for optionlist '" + listname + 894 "'. Cur time " + currentTime + " last executed " + lastExecuted + 895 " timeout " + queryTimeOut + " > " + (currentTime - lastExecuted)); 896 897 Node queryresult = null; 898 899 try { 900 String newWhere = Utils.fillInParams(Utils.getAttribute(query, "where"), variables); 902 Utils.setAttribute(query, "where", newWhere); 903 queryresult = databaseConnector.getList(query); 904 queryresult = Utils.selectSingleNode(queryresult, "/getlist/query"); 905 } catch (Exception e) { 906 log.debug("Error during query, proceeding with next list: " + e.toString()); 908 909 Element option = optionlist.getOwnerDocument().createElement("option"); 910 option.setAttribute("id", "-"); 911 Utils.storeText(option, "Error: query for '" + listname + "' failed"); 912 optionlist.appendChild(option); 913 914 continue; 915 } 916 917 Utils.setAttribute(query, "last-executed", String.valueOf(currentTime)); 919 920 NodeList olditems = Utils.selectNodeList(list, "option"); 922 923 for (int itemindex = 0; itemindex < olditems.getLength(); 924 itemindex++) { 925 list.removeChild(olditems.item(itemindex)); 926 } 927 928 NodeList items = Utils.selectNodeList(queryresult, "*"); 933 String idPath = Utils.getAttribute(list, "optionid", "@number"); 934 String contentPath = Utils.getAttribute(list, "optioncontent", "field"); 935 936 for (int itemindex = 0; itemindex < items.getLength(); 937 itemindex++) { 938 Node item = items.item(itemindex); 939 String optionId = Utils.transformAttribute(item, idPath, true); 940 String optionContent = Utils.transformAttribute(item, 941 contentPath, true); 942 Element option = list.getOwnerDocument().createElement("option"); 943 option.setAttribute("id", optionId); 944 Utils.storeText(option, optionContent); 945 list.appendChild(option); 946 } 947 } 948 949 NodeList items = Utils.selectNodeList(list, "option"); 951 Utils.appendNodeList(items, optionlist); 952 953 } 954 955 String selectedValue = Utils.selectSingleNodeText(optionlist, 957 "../value/text()", ""); log.debug("Trying to preselect the list at value: " + selectedValue); 959 960 Node selectedoption = Utils.selectSingleNode(optionlist, 961 "option[@id='" + selectedValue + "']"); 962 963 if (selectedoption != null) { 964 Utils.setAttribute(selectedoption, "selected", "true"); 966 } 967 } 968 969 return preHtml; 971 } 972 973 980 public void createPreHtmlForm(Node form, Node formdef, Node dataContext) 981 throws WizardException { 982 if (log.isDebugEnabled()) { 983 log.trace("Creating preHTMLForm for form:" + form + " / formdef:" + formdef + " / data:" + dataContext); 984 } 985 986 NodeList fields = Utils.selectNodeList(formdef, "fieldset|field|list|command"); 988 989 for (int i = 0; i < fields.getLength(); i++) { 993 Node field = fields.item(i); 994 995 String nodeName = field.getNodeName(); 997 998 if (nodeName.equals("fieldset")) { 1000 Node newfieldset = form.getOwnerDocument().createElement("fieldset"); 1001 Utils.copyAllAttributes(field, newfieldset); 1002 1003 NodeList itemprops = Utils.selectNodeList(field, "prompt"); 1004 Utils.appendNodeList(itemprops, newfieldset); 1005 1006 form.appendChild(newfieldset); 1008 createPreHtmlForm(newfieldset, field, dataContext); 1009 } else { 1010 Node fieldDataNode = null; 1011 String xpath = Utils.getAttribute(field, "fdatapath", null); 1012 1013 if (xpath == null) { 1014 String ftype = Utils.getAttribute(field, "ftype", null); 1015 1016 if (!("startwizard".equals(ftype) || "wizard".equals(ftype))) { 1017 throw new WizardException("A field tag should contain one of the following attributes: fdatapath or name"); 1018 } 1019 } else { 1020 if (log.isDebugEnabled()) { 1021 log.debug("Doing '" + xpath + "'"); 1022 log.debug("on " + Utils.getXML(dataContext)); 1023 } 1024 1025 if (nodeName.equals("field")) { 1027 fieldDataNode = Utils.selectSingleNode(dataContext, xpath); 1029 1030 if (fieldDataNode != null) { 1031 int endFieldContextXpath = xpath.lastIndexOf("/") > -1 ? xpath.lastIndexOf('/') : 0; 1033 String fieldContextXPath = xpath.substring(0, endFieldContextXpath); 1034 String mayWriteXPath = "".equals(fieldContextXPath) ? "@maywrite" : fieldContextXPath + "/@maywrite"; 1035 Utils.setAttribute(field, "maywrite", Utils.selectSingleNodeText(dataContext, mayWriteXPath, "true")); 1036 mergeConstraints(field, fieldDataNode); 1037 createFormField(form, field, fieldDataNode); 1038 } else { 1039 String ftype = Utils.getAttribute(field, "ftype"); 1040 1041 if ("function".equals(ftype)) { 1042 log.debug("Not an data node, setting number attribute, because it cannot be found with fdatapath"); 1043 1044 Utils.setAttribute(field, "number", Utils.selectSingleNodeText(dataContext, "object/@number", "")); 1046 Utils.setAttribute(field, "maywrite", Utils.selectSingleNodeText(dataContext, "object/@maywrite", "true")); 1047 1048 createFormField(form, field, fieldDataNode); 1050 } else if ("startwizard".equals(ftype) || "wizard".equals(ftype)) { 1051 log.debug("A startwizard!"); 1052 createFormField(form, field, dataContext); 1054 } else { 1055 String fname = Utils.getAttribute(field, "name", null); 1059 1060 if (fname != null) { 1061 throw new WizardException("Perhaps the field with name '" + fname + "' does not exist?"); 1062 } 1063 } 1064 } 1065 } 1066 if (nodeName.equals("list")) { 1068 NodeList fieldInstances = Utils.selectNodeList(dataContext, xpath); 1069 1070 if (fieldInstances == null) { 1071 throw new WizardException("The xpath: " + xpath + 1072 " is not valid. Note: this xpath maybe generated from a <field name='fieldname'> tag. Make sure you use simple valid fieldnames use valid xpath syntax."); 1073 } 1074 createFormList(form, field, fieldInstances, dataContext); 1075 } 1076 } 1077 } 1078 } 1079 } 1080 1081 1086 private void loadSchema(URL wizardSchemaFile) throws WizardException { 1087 schema = wizardSchemaCache.getDocument(wizardSchemaFile); 1088 1089 if (schema == null) { 1090 schema = Utils.loadXMLFile(wizardSchemaFile); 1091 1092 List dependencies = resolveIncludes(schema.getDocumentElement()); 1093 resolveShortcuts(schema.getDocumentElement(), true); 1094 1095 wizardSchemaCache.put(wizardSchemaFile, schema, dependencies); 1096 1097 log.debug("Schema loaded (and resolved): " + wizardSchemaFile); 1098 } else { 1099 log.debug("Schema found in cache: " + wizardSchemaFile); 1100 } 1101 1102 NodeList fields = Utils.selectNodeList(schema, "//field|//list|//item"); 1104 Utils.tagNodeList(fields, "fid", "f", 1); 1105 } 1106 1107 1120 private List resolveIncludes(Node node) throws WizardException { 1121 List result = new ArrayList(); 1122 1123 NodeList externalReferences = Utils.selectNodeList(node, 1126 "//*[@include or @extends]"); 1127 Document targetdoc = node.getOwnerDocument(); 1128 1129 if (externalReferences != null) { 1130 for (int i = 0; i < externalReferences.getLength(); i++) { 1131 Node referer = externalReferences.item(i); 1132 boolean inherits = !Utils.getAttribute(referer, "extends", "") 1133 .equals(""); 1134 String includeUrl = Utils.getAttribute(referer, "include"); 1135 1136 if (inherits) { 1137 includeUrl = Utils.getAttribute(referer, "extends"); 1138 } 1139 1140 try { 1141 String url = includeUrl; 1143 String externalId = "not applicable"; 1144 int hash = includeUrl.indexOf('#'); 1145 1146 if (hash != -1) { 1147 url = includeUrl.substring(0, includeUrl.indexOf('#')); 1148 externalId = includeUrl.substring(includeUrl.indexOf('#') + 1149 1); 1150 } 1151 1152 URL file; 1153 try { 1154 file = uriResolver.resolveToURL(url, null); 1155 } catch (Exception e) { 1156 throw new WizardException(e); 1157 } 1158 result.add(file); 1159 1160 Document externalDocument = Utils.loadXMLFile(file); 1162 1163 if (externalDocument == null) { 1164 throw new WizardException("Could not load and parse included file. Filename:" + file); 1165 } 1166 1167 Node externalPart = null; 1170 1171 if (hash == -1) { 1172 externalPart = externalDocument.getDocumentElement(); 1174 } else if (externalId.startsWith("xpointer(")) { 1175 String xpath = externalId.substring(9, externalId.length() - 1); 1177 externalPart = Utils.selectSingleNode(externalDocument, xpath); 1178 } else { 1179 externalPart = Utils.selectSingleNode(externalDocument, 1181 "//node()[@id='" + externalId + "']"); 1182 } 1183 1184 result.addAll(resolveIncludes(externalPart)); 1186 1187 Node parent = referer.getParentNode(); 1189 externalPart = parent.insertBefore(targetdoc.importNode(externalPart, true), referer); 1190 1191 Utils.copyAllAttributes(referer, externalPart); 1193 1194 if (inherits) { 1196 NodeList overriders = Utils.selectNodeList(referer, "node()"); 1197 1198 for (int k = 0; k < overriders.getLength(); k++) { 1199 externalPart.appendChild(overriders.item(k)); 1201 } 1202 } 1203 1204 parent.removeChild(referer); 1206 } catch (RuntimeException e) { 1207 log.error(Logging.stackTrace(e)); 1208 throw new WizardException("Error resolving external part '" + 1209 includeUrl + "'"); 1210 } 1211 } 1212 } 1213 1214 return result; 1215 } 1216 1217 1227 private void resolveShortcuts(Node schemaNode, boolean recurse) throws WizardException { 1228 String xpath; 1229 1230 if (recurse) { 1231 xpath = ".//field|.//list"; 1232 } else { 1233 xpath = "field|list"; 1234 } 1235 1236 NodeList children = Utils.selectNodeList(schemaNode, xpath); 1237 1238 if (children == null) { 1239 throw new RuntimeException ("could not perform xpath:" + xpath + " for schemanode:\n" + schemaNode); 1240 } 1241 1242 Node node; 1243 1244 for (int i = 0; i < children.getLength(); i++) { 1245 resolveShortcut(children.item(i)); 1246 } 1247 1248 if (Utils.selectSingleNode(schemaNode, "steps") == null) { 1250 Node stepsNode = schemaNode.getOwnerDocument().createElement("steps"); 1251 NodeList forms = Utils.selectNodeList(schemaNode, "form-schema"); 1252 1253 for (int i = 0; i < forms.getLength(); i++) { 1254 Node formStep = schemaNode.getOwnerDocument().createElement("step"); 1255 String formId = Utils.getAttribute(forms.item(i), "id", null); 1256 1257 if (formId == null) { 1258 formId = "tempformid_" + i; 1259 Utils.setAttribute(forms.item(i), "id", formId); 1260 } 1261 1262 Utils.setAttribute(formStep, "form-schema", formId); 1263 stepsNode.appendChild(formStep); 1264 } 1265 1266 schemaNode.appendChild(stepsNode); 1268 } 1269 } 1270 1271 1276 private void resolveShortcut(Node singleNode) throws WizardException { 1277 String nodeName = singleNode.getNodeName(); 1279 1280 if (nodeName.equals("field")) { 1281 String name = Utils.getAttribute(singleNode, "name", null); 1283 String fdatapath = Utils.getAttribute(singleNode, "fdatapath", null); 1284 String ftype = Utils.getAttribute(singleNode, "ftype", null); 1285 1286 if (fdatapath == null) { 1287 if (name == null) { 1289 if ("startwizard".equals(ftype) || "wizard".equals(ftype)) { 1290 fdatapath = "."; 1291 } 1292 } else { 1293 if ("number".equals(name)) { 1294 Utils.setAttribute(singleNode, "ftype", "data"); 1295 1296 fdatapath = "@number"; 1298 } else { 1299 fdatapath = "field[@name='" + name + "']"; 1300 } 1301 1302 Node parentNode = singleNode.getParentNode(); 1304 String parentname = parentNode.getNodeName(); 1305 1306 if (parentname.equals("fieldset")) { 1308 parentname = parentNode.getParentNode().getNodeName(); 1309 } 1310 1311 if (parentname.equals("item")) { 1312 fdatapath = "object/" + fdatapath; 1313 } 1314 } 1315 1316 Utils.setAttribute(singleNode, "fdatapath", fdatapath); 1317 } 1318 } else if (nodeName.equals("list")) { 1319 String role = Utils.getAttribute(singleNode, "role", null); String destination = Utils.getAttribute(singleNode, "destinationtype", null); 1322 1323 if (destination == null) { 1325 destination = Utils.getAttribute(singleNode, "destination", null); 1326 } 1327 1328 String searchString = Utils.getAttribute(singleNode, "searchdir", null); 1329 1330 StringBuffer fdatapath = null; 1331 String tmp = Utils.getAttribute(singleNode, "fdatapath", null); 1332 if (tmp != null) fdatapath = new StringBuffer (tmp); 1333 1334 if (fdatapath != null) { 1335 if (searchString != null || role != null || destination != null) { 1336 log.warn("When 'datapath' is geven, it does not make sense to specify the 'searchdir', role' or 'destinationtype' attributes. These attributes are ignored."); 1337 } 1338 } else { 1339 fdatapath = new StringBuffer (); 1341 1342 if (role != null) { 1343 fdatapath.append("@role='").append(role).append('\''); 1344 } 1345 1346 if (destination != null) { 1348 if (fdatapath.length() != 0) { 1349 fdatapath.append(" and "); 1350 } 1351 1353 Node con = getConstraints(destination); 1354 NodeList descendants = null; 1356 if (con!=null) descendants = Utils.selectNodeList(con,"descendants/descendant"); 1357 1358 if (descendants == null || descendants.getLength() == 0) { 1359 fdatapath.append("object/@type='").append(destination).append('\''); 1360 } else { 1361 1362 fdatapath.append("(object/@type='").append(destination).append('\''); 1363 1364 for (int desci = 0; desci < descendants.getLength();desci++) { 1365 Node descendant = descendants.item(desci); 1366 String descendantName = Utils.getAttribute(descendant, "type", null); 1367 fdatapath.append(" or object/@type='").append(descendantName).append('\''); 1368 } 1369 1370 fdatapath.append(')'); 1371 1372 } 1373 } 1374 1375 int searchDir = RelationStep.DIRECTIONS_BOTH; 1377 1378 if (searchString != null) { 1379 searchDir = Queries.getRelationStepDirection(searchString); 1380 } 1381 1382 if (searchDir == RelationStep.DIRECTIONS_SOURCE) { 1383 if (fdatapath.length() != 0) { 1384 fdatapath.append(" and "); 1385 } 1386 1387 fdatapath.append("@source=object/@number"); 1388 } else if (searchDir == RelationStep.DIRECTIONS_DESTINATION) { 1389 if (fdatapath.length() != 0) { 1390 fdatapath.append(" and "); 1391 } 1392 1393 fdatapath.append("@destination=object/@number"); 1394 } 1395 1396 fdatapath.insert(0, "relation["); 1397 fdatapath.append(']'); 1398 1399 if (singleNode.getParentNode().getNodeName().equals("item")) { 1401 fdatapath.insert(0, "object/"); 1402 } 1403 Utils.setAttribute(singleNode, "fdatapath", fdatapath.toString()); 1404 } 1405 } 1406 } 1407 1408 private void expandAttribute(Node node, String name, String defaultvalue) { 1409 String value = Utils.transformAttribute(data.getDocumentElement(), 1410 Utils.getAttribute(node, name, null), false, variables); 1411 1412 if (value == null) { 1413 value = defaultvalue; 1414 } 1415 1416 if (value != null) { 1417 Utils.setAttribute(node, name, value); 1418 } 1419 } 1420 1421 1425 private void createFormList(Node form, Node fieldlist, NodeList datalist, 1426 Node parentdatanode) throws WizardException { 1427 log.debug("creating form list"); 1429 1430 Node newlist = fieldlist.cloneNode(false); 1431 newlist = form.getOwnerDocument().importNode(newlist, false); 1432 Utils.copyAllAttributes(fieldlist, newlist); 1433 1434 if (parentdatanode != null) { 1436 Utils.setAttribute(newlist, "number", Utils.getAttribute(parentdatanode, "number")); 1437 } 1438 1439 NodeList props = Utils.selectNodeList(fieldlist, 1441 "title|description|action|command"); 1442 1443 Utils.appendNodeList(props, newlist); 1444 1445 NodeList itemTitle = Utils.selectNodeList(fieldlist, "item/title|item/description"); 1447 1448 for (int i=0; i<itemTitle.getLength(); i++) { 1449 Utils.setAttribute(newlist, "item" + itemTitle.item(i).getNodeName(), Utils.getText(itemTitle.item(i))); 1450 } 1451 1452 Node command = Utils.selectSingleNode(newlist, "command[@name='search']"); 1454 1455 1456 if (command != null) { 1457 expandAttribute(command, "startnodes", null); 1458 String cAttribute = Utils.getAttribute(command, "constraints"); 1460 if(cAttribute != null && !cAttribute.equals("")){ 1461 expandAttribute(command, "constraints", dataId); 1462 } 1463 } 1464 1465 NodeList commands = Utils.selectNodeList(newlist, "command[@name='startwizard']"); 1468 if (commands != null) { 1469 for (int i=0; i<commands.getLength(); i++) { 1470 command = commands.item(i); 1471 if (command!=null) { 1472 expandAttribute(command,"objectnumber","new"); 1473 expandAttribute(command,"origin",dataId); 1474 expandAttribute(command,"wizardname",null); 1475 } 1476 } 1477 } 1478 1479 String hiddenCommands = "|" + 1480 Utils.getAttribute(fieldlist, "hidecommand") + "|"; 1481 1482 form.appendChild(newlist); 1484 1485 int minoccurs = Integer.parseInt(Utils.getAttribute(fieldlist, 1487 "minoccurs", "0")); 1488 int nrOfItems = datalist.getLength(); 1489 1490 int maxoccurs = -1; 1491 String maxstr = Utils.getAttribute(fieldlist, "maxoccurs", "*"); 1492 1493 if (!maxstr.equals("*")) { 1494 maxoccurs = Integer.parseInt(maxstr); 1495 } 1496 1497 String orderby = Utils.getAttribute(fieldlist, "orderby", null); 1498 1499 if ((orderby != null) && (orderby.indexOf("@") == -1)) { 1500 orderby = "object/field[@name='" + orderby + "']"; 1501 } 1502 1503 String ordertype = Utils.getAttribute(fieldlist, "ordertype", "string"); 1504 1505 List tempstorage = new ArrayList(datalist.getLength()); 1507 1508 for (int dataIndex = 0; dataIndex < datalist.getLength(); dataIndex++) { 1509 Element datacontext = (Element) datalist.item(dataIndex); 1510 1511 if (orderby != null) { 1512 String orderByValue = Utils.selectSingleNodeText(datacontext, 1513 orderby, ""); 1514 1515 if (ordertype.equals("number")) { 1517 double orderDbl; 1518 1519 try { 1520 orderDbl = Double.parseDouble(orderByValue); 1521 } catch (Exception e) { 1522 log.error("fieldvalue " + orderByValue + " is not numeric"); 1523 orderDbl = -1; 1524 } 1525 1526 orderByValue = "" + orderDbl; 1527 } 1528 1529 datacontext.setAttribute("orderby", orderByValue); 1531 } 1532 1533 datacontext.setAttribute("firstitem", "false"); 1535 1536 datacontext.setAttribute("lastitem", "false"); 1538 tempstorage.add(datacontext); 1539 } 1540 1541 if (orderby != null) { 1543 Collections.sort(tempstorage, new OrderByComparator(ordertype)); 1544 } 1545 1546 int listsize = tempstorage.size(); 1548 1549 for (int dataindex = 0; dataindex < listsize; dataindex++) { 1550 Element datacontext = (Element) tempstorage.get(dataindex); 1551 1552 Node item = Utils.selectSingleNode(fieldlist, "item"); 1554 1555 if (item == null) { 1556 item = Utils.selectSingleNode(fieldlist, "item"); 1557 1558 if (item == null) { 1559 throw new WizardException("Could not find item in a list of " + 1560 wizardName); 1561 } 1562 1563 if (log.isDebugEnabled()) { 1564 log.debug("found an item " + item.toString()); 1565 } 1566 } 1567 1568 Node newitem = item.cloneNode(false); 1569 newitem = form.getOwnerDocument().importNode(newitem, false); 1570 newlist.appendChild(newitem); 1571 1572 Utils.copyAllAttributes(datacontext, newitem); 1574 Utils.copyAllAttributes(item, newitem); 1575 1576 NodeList itemprops = Utils.selectNodeList(item, "title|description"); 1578 Utils.appendNodeList(itemprops, newitem); 1579 1580 createPreHtmlForm(newitem, item, datacontext); 1582 1583 if ( 1585 hiddenCommands.indexOf("|delete-item|") == -1) { 1586 addSingleCommand(newitem, "delete-item", datacontext); 1587 } 1588 1589 if (orderby != null) { 1590 if ((dataindex > 0) && (hiddenCommands.indexOf("|move-up|") == -1)) { 1591 addSingleCommand(newitem, "move-up", datacontext, 1592 (Node) tempstorage.get(dataindex - 1)); 1593 } 1594 1595 if (((dataindex + 1) < listsize) && 1596 (hiddenCommands.indexOf("|move-down|") == -1)) { 1597 addSingleCommand(newitem, "move-down", datacontext, 1598 (Node) tempstorage.get(dataindex + 1)); 1599 } 1600 } 1601 1602 if (dataindex == 0) { 1603 datacontext.setAttribute("firstitem", "true"); 1604 } 1605 1606 if (dataindex == (tempstorage.size() - 1)) { 1607 datacontext.setAttribute("lastitem", "true"); 1608 } 1609 } 1610 1611 if (log.isDebugEnabled()) { 1620 log.debug("minoccurs:" + minoccurs + " maxoccurs: " + maxoccurs + 1621 " items: " + nrOfItems); 1622 } 1623 1624 if (((nrOfItems > maxoccurs) && (maxoccurs != -1)) || 1625 (nrOfItems < minoccurs)) { ((Element) newlist).setAttribute("status", "invalid"); 1627 1628 String listTitle = Utils.selectSingleNodeText(fieldlist, "title", 1630 "some list"); 1631 ((Element) form).setAttribute("invalidlist", listTitle); 1632 } else { 1633 ((Element) newlist).setAttribute("status", "valid"); 1634 } 1635 1636 log.debug("can we place an add-button?"); 1637 1638 if ((hiddenCommands.indexOf("|add-item|") == -1) && 1639 ((maxoccurs == -1) || (maxoccurs > nrOfItems)) && 1640 ( Utils.selectSingleNode(fieldlist, "action[@type='create']") != null || 1641 Utils.selectSingleNode(fieldlist, "action[@type='add']") != null )) { 1642 String defaultpath = "."; 1643 1644 if (fieldlist.getParentNode().getNodeName().equals("item")) { 1645 defaultpath = "object"; 1647 } 1648 1649 String fparentdatapath = Utils.getAttribute(fieldlist, 1650 "fparentdatapath", defaultpath); 1651 Node chosenparent = Utils.selectSingleNode(parentdatanode, 1652 fparentdatapath); 1653 1654 if ((datalist.getLength() > 0) && fparentdatapath.equals(".")) { 1656 addSingleCommand(newlist, "add-item", 1658 datalist.item(0).getParentNode()); 1659 } else { 1660 addSingleCommand(newlist, "add-item", chosenparent); 1662 } 1663 } 1664 1665 log.debug("end"); 1666 } 1667 1668 1675 private void createFormField(Node form, Node field, Node dataNode) 1676 throws WizardException { 1677 if (log.isDebugEnabled()) { 1678 log.debug("Creating form field for " + field + " wizard for obj: " + objectNumber); 1679 } 1680 1681 Node newField = form.getOwnerDocument().createElement("field"); 1683 1684 Utils.copyAllAttributes(field, newField); 1685 1686 form.appendChild(newField); 1688 1689 List exceptAttrs = new ArrayList(); exceptAttrs.add("fid"); 1691 1692 if ((dataNode != null) && (dataNode.getNodeType() != Node.ATTRIBUTE_NODE)) { 1694 Utils.copyAllAttributes(dataNode, newField, exceptAttrs); 1695 } 1696 1697 String ftype = Utils.getAttribute(newField, "ftype"); 1698 String dttype = Utils.getAttribute(newField, "dttype"); 1699 1700 String htmlFieldName = calculateFormName(newField); 1702 Utils.setAttribute(newField, "fieldname", htmlFieldName); 1703 1704 if ((dataNode != null) && (Utils.getAttribute(dataNode, "number", null) == null)) { 1706 Utils.setAttribute(newField, "number", Utils.getAttribute(dataNode.getParentNode(), "number")); 1707 } 1708 1709 if (ftype.equals("startwizard")) { 1711 String wizardObjectNumber = Utils.getAttribute(newField, "objectnumber", null); 1712 1713 if (wizardObjectNumber == null) { 1718 if (form.getNodeName().equals("form")) { 1719 wizardObjectNumber = "new"; 1720 } else { 1721 wizardObjectNumber = "{object/@number}"; 1722 } 1723 } 1724 1725 wizardObjectNumber = Utils.transformAttribute(dataNode, wizardObjectNumber); 1727 1728 boolean mayEdit = true; 1729 1730 if ("new".equals(wizardObjectNumber)) { 1731 mayEdit = true; 1737 } else { 1738 mayEdit = mayEditNode(wizardObjectNumber); 1740 } 1741 1742 if (!mayEdit) { 1743 form.removeChild(newField); 1745 } 1746 1747 Utils.setAttribute(newField, "objectnumber", wizardObjectNumber); 1748 1749 String wizardPath = Utils.getAttribute(newField, "wizardname", null); 1750 if (wizardPath != null) { 1751 wizardPath = Utils.transformAttribute(dataNode, wizardPath); 1752 Utils.setAttribute(newField, "wizardname", wizardPath); 1753 } 1754 1755 String wizardOrigin = Utils.getAttribute(newField, "origin", null); 1756 1757 if (wizardOrigin == null) { 1758 wizardOrigin = dataId; 1759 } else { 1760 wizardOrigin = Utils.transformAttribute(dataNode, wizardOrigin); 1761 } 1762 1763 Utils.setAttribute(newField, "origin", wizardOrigin); 1764 } else if (!ftype.equals("function")) { 1765 if (!mayEditNode(Utils.getAttribute(newField, "number"))) { 1767 ftype = "data"; 1768 Utils.getAttribute(newField, "ftype", ftype); 1769 } 1770 } 1771 1772 if ("binary".equals(dttype)) { 1774 addBinaryData(newField); 1775 } 1776 1777 NodeList list = Utils.selectNodeList(field, "optionlist|prompt|description|action|prefix|postfix"); 1778 Utils.appendNodeList(list, newField); 1779 1780 String theValue = ""; 1783 1784 try { 1785 if (dataNode == null) { 1786 if (ftype.equals("function")) { 1787 theValue = Utils.getAttribute(field, "name"); 1788 log.debug("Found a function field " + theValue); 1789 } else if (ftype.equals("startwizard") || ftype.equals("wizard")) { 1790 log.debug("found a wizard field"); 1791 } else { 1792 log.debug("Probably a new node"); 1793 throw new WizardException("No datanode given for field " + 1794 theValue + " and ftype does not equal 'function' or 'startwizard'(but " + ftype + ")"); 1795 } 1796 } else if (dataNode.getNodeType() == Node.ATTRIBUTE_NODE) { 1797 theValue = dataNode.getNodeValue(); 1798 } else { 1799 theValue = dataNode.getFirstChild().getNodeValue(); 1800 } 1801 } catch (RuntimeException e) { 1802 log.error(Logging.stackTrace(e)); 1803 } 1804 1805 if (ftype.equals("relation")) { 1807 theValue = Utils.getAttribute(newField, "destination"); 1808 } 1809 1810 if (theValue == null) { 1811 theValue = ""; 1812 } 1813 1814 Node value = form.getOwnerDocument().createElement("value"); 1815 Utils.storeText(value, theValue); 1816 newField.appendChild(value); 1817 } 1818 1819 private void addSingleCommand(Node field, String commandname, Node datanode) { 1820 addSingleCommand(field, commandname, datanode, null); 1821 } 1822 1823 private void addSingleCommand(Node field, String commandname, Node datanode, 1824 Node otherdatanode) { 1825 String otherdid = ""; 1826 1827 if (otherdatanode != null) { 1828 otherdid = Utils.getAttribute(otherdatanode, "did"); 1829 } 1830 1831 Element command = field.getOwnerDocument().createElement("command"); 1832 command.setAttribute("name", commandname); 1833 command.setAttribute("cmd", "cmd/" + commandname + "/" + Utils.getAttribute(field, "fid") + "/" + 1834 Utils.getAttribute(datanode, "did") + "/" + otherdid + "/"); 1835 command.setAttribute("value", Utils.getAttribute(datanode, "did")); 1836 field.appendChild(command); 1837 } 1838 1839 1845 private String calculateFormName(Node preHtmlFormField) { 1846 try { 1847 String fid = Utils.getAttribute(preHtmlFormField, "fid"); 1848 String did = Utils.getAttribute(preHtmlFormField, "did"); 1849 1850 return "field/" + fid + "/" + did; 1851 } catch (RuntimeException e) { 1852 return "field/fid_or_did_missed_a_tag"; 1853 } 1854 } 1855 1856 1861 private String [] processFormName(String formName) { 1862 String [] res = { "", "" }; 1863 1864 boolean isafield = (formName.indexOf("field/") > -1); 1865 int nr1 = formName.indexOf("/") + 1; 1866 int nr2 = formName.indexOf("/", nr1) + 1; 1867 1868 if ((nr1 < 1) || (nr2 < 1) || !isafield) { 1869 return null; 1871 } 1872 1873 String fid = formName.substring(nr1, nr2 - 1); 1874 String did = formName.substring(nr2); 1875 res[0] = did; 1876 res[1] = fid; 1877 1878 return res; 1879 } 1880 1881 1892 private void storeValue(String did, String fid, String value) throws WizardException { 1893 if (log.isDebugEnabled()) { 1894 log.debug("String value " + value + " in " + did + " for field " + fid); 1895 log.trace("Using data: " + 1896 Utils.getSerializedXML(Utils.selectSingleNode(schema, 1897 ".//*[@fid='" + fid + "']"))); 1898 } 1899 1900 String xpath = ".//*[@fid='" + fid + "']/@dttype"; 1901 Node dttypeNode = Utils.selectSingleNode(schema, xpath); 1902 1903 if (dttypeNode == null) { 1904 String msg = "No node with fid=" + fid + " could be found"; 1905 1906 if (schema != null) { 1907 msg += "\nxpath was:" + xpath + " on:\n" + schema.getDocumentElement(); 1908 } 1909 1910 throw new WizardException(msg); 1911 } 1912 1913 String dttype = dttypeNode.getNodeValue(); 1914 xpath = ".//*[@did='" + did + "']"; 1915 1916 Node datanode = Utils.selectSingleNode(data, xpath); 1917 1918 if (datanode == null) { 1919 String msg = "Unable to store value for field with dttype " + dttype + ". fid=" + fid + ", did=" + did + ", value=" + value + ", wizard:" + wizardName; 1920 1921 if (data != null) { 1922 msg += "\nxpath was:" + xpath + " on:\n" + data.getDocumentElement(); 1923 } 1924 1925 log.warn(msg); 1926 1927 return; 1928 } 1929 1930 if (dttype.equals("binary")) { 1932 if (getBinary(did) != null) { 1934 Utils.setAttribute(datanode, "href", did); 1935 Utils.storeText(datanode, getBinaryName(did)); 1936 } 1937 } else { Utils.storeText(datanode, value); 1939 } 1940 } 1941 1942 1950 public void storeFieldValue(String did, String fieldName, String value) throws WizardException { 1951 if (log.isDebugEnabled()) { 1952 log.debug("String value " + value + " in " + did + " for field " + fieldName); 1953 } 1954 1955 String xpath = ".//*[@did='" + did + "']"; 1956 Node objectNode = Utils.selectSingleNode(data, xpath); 1957 1958 xpath = "./field[@name='" + fieldName + "']"; 1959 Node fieldNode = Utils. selectSingleNode(objectNode, xpath); 1960 1961 if (fieldNode == null) { 1962 throw new WizardException("Unable to store value for field with name " + fieldName + " for node with did=" + did + ", value=" + value + ", wizard:" + wizardName); 1963 } 1964 Utils.storeText(fieldNode, value); 1965 } 1966 1967 1974 public String retrieveFieldValue(String did, String fieldName) throws WizardException { 1975 if (log.isDebugEnabled()) { 1976 log.debug("Get value in " + did + " for field " + fieldName); 1977 } 1978 1979 String xpath = ".//*[@did='" + did + "']"; 1980 Node objectNode = Utils.selectSingleNode(data, xpath); 1981 1982 xpath = "./field[@name='" + fieldName + "']"; 1983 Node fieldNode = Utils. selectSingleNode(objectNode, xpath); 1984 1985 if (fieldNode == null) { 1986 throw new WizardException("Unable to store value for field with name " + fieldName + " for node with did=" + did + ", wizard:" + wizardName); 1987 } 1988 1989 return Utils.getText(fieldNode); 1990 } 1991 1992 1993 1998 private void processCommands(ServletRequest req) throws WizardException { 1999 log.debug("processing commands"); 2000 mayBeClosed = false; 2001 startWizard = false; 2002 startWizardCmd = null; 2003 2004 boolean found = false; 2005 String commandName = ""; 2006 2007 List errors = new ArrayList(); 2008 Enumeration list = req.getParameterNames(); 2009 2010 while (list.hasMoreElements()) { 2011 commandName = (String ) list.nextElement(); 2012 2013 if ((commandName.indexOf("cmd/") == 0) && !commandName.endsWith(".y")) { 2014 if (log.isDebugEnabled()) { 2015 log.debug("found a command " + commandName); 2016 } 2017 2018 String commandValue = req.getParameter(commandName); 2020 WizardCommand wc = new WizardCommand(commandName, commandValue); 2021 processCommand(wc); 2022 } else { 2023 if (log.isDebugEnabled()) { 2024 log.trace("ignoring non-command " + commandName); 2025 } 2026 } 2027 } 2028 2029 } 2030 2031 2048 public void processCommand(WizardCommand cmd) throws WizardException { 2049 log.debug("Processing command " + cmd); 2050 switch (cmd.getType()) { 2052 case WizardCommand.DELETE_ITEM: { 2053 String did = cmd.getDid(); 2057 Node dataNode = Utils.selectSingleNode(data, ".//*[@did='" + did + "']"); 2058 2059 if (dataNode != null) { 2060 String fid = cmd.getFid(); 2066 Node itemNode = Utils.selectSingleNode(schema, ".//*[@fid='" + fid + "']"); 2067 Node listNode = itemNode.getParentNode(); 2068 Node objectDef = Utils.selectSingleNode(listNode, "action[@type='delete']/object"); 2069 2070 Node dataObjectNode = dataNode; 2071 2072 if (objectDef != null) { 2073 dataObjectNode = Utils.selectSingleNode(dataNode, "object"); 2074 } 2075 2076 Node newRepos = data.createElement("repos"); 2083 NodeList insideObjects = Utils.selectNodeList(dataObjectNode, "object|relation"); 2084 Utils.appendNodeList(insideObjects, newRepos); 2085 2086 dataNode.getParentNode().appendChild(newRepos); 2088 2089 dataNode.getParentNode().removeChild(dataNode); 2091 } 2092 2093 break; 2094 } 2095 2096 case WizardCommand.UPDATE_ITEM: { 2097 String value = cmd.getValue(); 2101 NodeList nodesToUpdate = Utils.selectNodeList(data, ".//*[@number='" + value + "']"); 2102 NodeList originalNodesToUpdate = Utils.selectNodeList(originalData, ".//*[@number='" + value + "']"); 2103 2104 if ((nodesToUpdate != null) || (originalNodesToUpdate != null)) { 2105 Node updatedNode = null; 2106 2107 try { 2108 updatedNode = databaseConnector.getDataNode(null, value, null); 2109 } catch (Exception e) { 2110 break; 2112 } 2113 2114 NodeList updatedFields = Utils.selectNodeList(updatedNode, "./field"); 2115 2116 Map fieldValues = new HashMap(); 2117 2118 for (int j = 0; j < updatedFields.getLength(); j++) { 2119 Node fieldNode = updatedFields.item(j); 2120 String fieldName = Utils.getAttribute(fieldNode, "name"); 2121 String fieldValue = Utils.getText(fieldNode); 2122 fieldValues.put(fieldName, fieldValue); 2123 } 2124 2125 NodeList insideObjects = Utils.selectNodeList(updatedNode, "*"); 2126 2127 for (int i = 0; i < nodesToUpdate.getLength(); i++) { 2128 Node dataNode = nodesToUpdate.item(i); 2129 NodeList fieldsToUpdate = Utils.selectNodeList(dataNode, "./field"); 2130 2131 for (int j = 0; j < fieldsToUpdate.getLength(); j++) { 2132 Node fieldNode = fieldsToUpdate.item(j); 2133 String fieldName = Utils.getAttribute(fieldNode, "name"); 2134 String fieldValue = (String ) fieldValues.get(fieldName); 2135 Utils.storeText(fieldNode, fieldValue); 2136 } 2137 } 2138 2139 for (int i = 0; i < originalNodesToUpdate.getLength(); i++) { 2140 Node dataNode = originalNodesToUpdate.item(i); 2141 NodeList fieldsToUpdate = Utils.selectNodeList(dataNode, "./field"); 2142 2143 for (int j = 0; j < fieldsToUpdate.getLength(); j++) { 2144 Node fieldNode = fieldsToUpdate.item(j); 2145 String fieldName = Utils.getAttribute(fieldNode, "name"); 2146 String fieldValue = (String ) fieldValues.get(fieldName); 2147 Utils.storeText(fieldNode, fieldValue); 2148 } 2149 } 2150 } 2151 2152 break; 2153 } 2154 2155 case WizardCommand.MOVE_UP: 2156 case WizardCommand.MOVE_DOWN: { 2157 String fid = cmd.getFid(); 2161 String did = cmd.getDid(); 2162 String otherdid = cmd.getParameter(2); 2163 2164 Node parentnode = Utils.selectSingleNode(schema, 2169 ".//*[@fid='" + fid + "']"); 2170 String orderby = Utils.getAttribute(parentnode.getParentNode(), 2171 "orderby"); 2172 2173 if (orderby != null) { 2177 if (orderby.indexOf('@') == -1) { 2179 orderby = "object/field[@name='" + orderby + "']"; 2180 } 2181 2182 log.debug("swap " + did + " and " + otherdid + " on " + orderby); 2183 2184 Node datanode = Utils.selectSingleNode(data, 2185 ".//*[@did='" + did + "']/" + orderby); 2186 2187 if (datanode != null) { 2188 Node othernode = Utils.selectSingleNode(data, 2190 ".//*[@did='" + otherdid + "']/" + orderby); 2191 2192 if (othernode != null) { 2194 String datavalue = Utils.getText(datanode); 2195 String othervalue = Utils.getText(othernode); 2196 Utils.storeText(othernode, datavalue); 2197 Utils.storeText(datanode, othervalue); 2198 } 2199 } 2200 } 2201 2202 break; 2203 } 2204 2205 case WizardCommand.START_WIZARD: { 2206 startWizard = true; 2208 startWizardCmd = cmd; 2209 2210 break; 2211 } 2212 2213 case WizardCommand.GOTO_FORM: { 2214 currentFormId = cmd.getDid(); 2217 2218 break; 2219 } 2220 2221 case WizardCommand.ADD_ITEM: { 2222 String fid = cmd.getFid(); 2230 String did = cmd.getDid(); 2231 String value = cmd.getValue(); 2232 2233 if (log.isDebugEnabled()) { 2234 log.debug("Adding item fid: " + fid + " did: " + did + " value: " + value); 2235 } 2236 2237 if ((value != null) && !value.equals("")) { 2238 log.debug("no value"); 2239 2240 int createOrder = 1; 2241 StringTokenizer ids = new StringTokenizer(value, "|"); 2242 2243 while (ids.hasMoreElements()) { 2244 Node newObject = addListItem(fid, did, ids.nextToken(), false, createOrder); 2245 createOrder++; 2246 } 2247 } else { 2248 String otherdid = cmd.getParameter(2); 2249 2250 if (otherdid.equals("")) { 2251 otherdid = null; 2252 } 2253 2254 Node newObject = addListItem(fid, did, otherdid, true, 1); 2255 } 2256 2257 break; 2258 } 2259 2260 case WizardCommand.CANCEL: { 2261 mayBeClosed = true; 2263 2264 break; 2265 } 2266 case WizardCommand.SAVE : { 2267 log.debug("Wizard " + objectNumber + " will be saved (but not closed)"); 2268 } 2269 2270 case WizardCommand.COMMIT: { 2271 log.debug("Committing wizard " + objectNumber); 2272 2273 if (log.isDebugEnabled()) { 2275 log.debug("orig: " + Utils.stringFormatted(originalData)); 2276 log.debug("new orig: " + Utils.stringFormatted(data)); 2277 } 2278 2279 Element results = databaseConnector.put(originalData, data, binaries); 2280 2281 String oldNumber = Utils.selectSingleNodeText(data, ".//object/@number", null); 2283 2284 if (log.isDebugEnabled()) { 2286 log.trace("results : " + results); 2287 log.debug("found old number " + oldNumber); 2288 } 2289 2290 String newNumber = Utils.selectSingleNodeText(results, ".//object[@oldnumber='" + oldNumber + "']/@number", null); 2293 2294 if (log.isDebugEnabled()) { 2295 log.debug("found new wizard number " + newNumber); 2296 } 2297 2298 if (newNumber != null) { 2299 objectNumber = newNumber; 2300 } 2301 2302 committed = true; 2303 mayBeClosed = (cmd.getType() == WizardCommand.COMMIT); 2304 2305 if (!mayBeClosed) { 2306 2307 if (log.isDebugEnabled()) { 2309 log.trace("Using data was " + Utils.getSerializedXML(originalData)); 2310 log.trace("is " + Utils.getSerializedXML(data)); 2311 } 2312 2313 2316 2317 if (newNumber != null) { 2318 dataId = newNumber; 2319 } 2320 2321 loadData(); 2323 2324 2325 } 2326 2327 break; 2328 } 2329 default: { 2330 log.warn("Received an unknown wizard command '" + cmd.getValue() + "'"); 2331 } 2332 } 2333 } 2334 2335 2348 private Node addListItem(String listId, String subDataId, String destinationId, 2349 boolean isCreate, int createOrder) throws WizardException { 2350 log.debug("Adding list item"); 2351 2352 Node listNode = Utils.selectSingleNode(schema, ".//list[@fid='" + listId + "']"); 2354 Node relationDefinition = null; 2355 2356 if (!isCreate) { 2358 relationDefinition = Utils.selectSingleNode(listNode, "action[@type='add']/relation"); 2359 } 2360 2361 if (relationDefinition == null) { 2364 relationDefinition = Utils.selectSingleNode(listNode, "action[@type='create']/relation"); 2365 } 2366 2367 2368 if (relationDefinition == null) { throw new WizardException("Could not find action (add or create) to add a item to list with id " + listId); 2370 } 2371 2372 relationDefinition = relationDefinition.cloneNode(true); 2374 if (log.isDebugEnabled()) { 2375 log.debug("Creating object " + relationDefinition.getNodeName() + " type " + Utils.getAttribute(relationDefinition, "type")); 2376 } 2377 2378 if (destinationId != null) { 2380 Utils.setAttribute(relationDefinition, "destination", destinationId); 2381 } 2382 2383 Node parent = Utils.selectSingleNode(data, ".//*[@did='" + subDataId + "']"); 2385 2386 2387 2388 Node newRelation = databaseConnector.createObject(data, parent, relationDefinition, variables, createOrder); 2390 2391 if (destinationId != null) { 2393 Node newRelatedNode = Utils.selectSingleNode(newRelation, "object"); 2394 if (newRelatedNode != null) { 2395 String relatedType = Utils.selectSingleNodeText(newRelatedNode, "@type", null); 2396 2397 Node loadAction = Utils.selectSingleNode(schema.getDocumentElement(), "action[@type='load']/relation[@destination='" + relatedType + "']/object"); 2398 2399 if (loadAction != null) { 2400 Collection newSubRelations = databaseConnector.loadRelations(newRelatedNode, destinationId, loadAction); 2401 2403 Iterator i = newSubRelations.iterator(); 2404 while (i.hasNext()) { 2405 Node newSubRelation = (Node) i.next(); 2406 Utils.setAttribute(newSubRelation, "already-exists", "true"); 2407 NodeList newSubObjects = Utils.selectNodeList(newSubRelation, ".//object"); 2408 2409 for (int j = 0; j < newSubObjects.getLength(); j++) { 2410 Node newSubObject = newSubObjects.item(j); 2411 Utils.setAttribute(newSubObject, "already-exists", "true"); 2412 } 2413 2414 NodeList newSubSubRelations = Utils.selectNodeList(newSubRelation, ".//relation"); 2415 for (int k = 0; k < newSubSubRelations.getLength(); k++) { 2416 Node newSubSubRelation = newSubSubRelations.item(k); 2417 Utils.setAttribute(newSubSubRelation, "already-exists", "true"); 2418 } 2419 } 2420 } else { 2421 log.debug("Nothing found to load"); 2422 } 2423 } else { 2424 2425 throw new WizardException("Could not find relatednode " + Utils.getXML(newRelation)); 2426 } 2427 } 2428 return newRelation; 2429 2430 } 2431 2432 2440 public void setBinary(String did, byte[] bytes, String name, String path) { 2441 setBinary(did, bytes, name, path, null); 2442 } 2443 2444 2450 public void setBinary(String did, byte[] bytes, String name, String path, String type) { 2451 binaries.put(did, bytes); 2452 binaryNames.put(did, name); 2453 binaryPaths.put(did, path); 2454 2455 if (type != null) { 2456 Node mimetypeField = Utils.selectSingleNode(data, "//object[field/@did = '" + did + "']/field[@name='mimetype']"); 2457 if (mimetypeField != null) { 2458 Utils.storeText(mimetypeField, type); 2459 } 2460 Node sizeField = Utils.selectSingleNode(data, "//object[field/@did = '" + did + "']/field[@name='size']"); 2461 if (sizeField != null && bytes != null) { 2462 Utils.storeText(sizeField, "" + bytes.length); 2463 } 2464 Node fileNameField = Utils.selectSingleNode(data, "//object[field/@did = '" + did + "']/field[@name='filename']"); 2465 if (fileNameField != null && name != null) { 2466 Utils.storeText(fileNameField, name); 2467 } 2468 } 2469 2470 } 2471 2472 2473 2474 2480 public byte[] getBinary(String did) { 2481 return (byte[]) binaries.get(did); 2482 } 2483 2484 2490 public String getBinaryName(String did) { 2491 return (String ) binaryNames.get(did); 2492 } 2493 2494 2500 public String getBinaryPath(String did) { 2501 return (String ) binaryPaths.get(did); 2502 } 2503 2504 2510 public void addBinaryData(Node fieldnode) { 2511 String did = Utils.getAttribute(fieldnode, "did", null); 2514 2515 if (did != null) { 2516 byte[] binary = getBinary(did); 2517 2518 if (binary != null) { 2519 Node binarynode = fieldnode.getOwnerDocument().createElement("upload"); 2521 Utils.setAttribute(binarynode, "uploaded", "true"); 2522 Utils.setAttribute(binarynode, "size", binary.length + ""); 2523 Utils.setAttribute(binarynode, "name", getBinaryName(did)); 2524 2525 String path = getBinaryPath(did); 2526 Utils.createAndAppendNode(binarynode, "path", path); 2527 fieldnode.appendChild(binarynode); 2528 } 2529 } 2530 } 2531 2532 2541 public void mergeConstraints(Node fieldDef, Node fieldNode) { 2542 if (fieldNode == null) { 2545 log.warn("Tried mergeContraints on fieldNode which is null. FielDef: " + 2546 Utils.getXML(fieldDef)); 2547 } 2548 2549 String objectType = Utils.getAttribute(fieldNode.getParentNode(), "type", 2550 null); 2551 String fieldName = Utils.getAttribute(fieldNode, "name", null); 2552 2553 if ((objectType == null) || (fieldName == null)) { 2554 if (log.isDebugEnabled()) { 2555 log.debug("wizard.mergeConstraints: objecttype or fieldname could not be retrieved for this field. Field:"); 2556 log.debug(Utils.getXML(fieldNode)); 2557 } 2558 2559 return; 2560 } 2561 2562 Node con = getConstraints(objectType, fieldName); 2563 2564 if (con == null) { 2565 return; } 2567 2568 String xmlSchemaType = null; 2569 String guiType = Utils.selectSingleNodeText(con, Dove.GUITYPE, "string/line"); 2570 int pos = guiType.indexOf("/"); 2571 2572 if (pos != -1) { 2573 xmlSchemaType = guiType.substring(0, pos); 2574 guiType = guiType.substring(pos + 1); 2575 } 2576 2577 String required = Utils.selectSingleNodeText(con, Dove.REQUIRED, "false"); 2578 String guiName = Utils.selectSingleNodeText(con, Dove.GUINAME, ""); 2579 String description = Utils.selectSingleNodeText(con, Dove.DESCRIPTION, ""); 2580 String maxLength = Utils.selectSingleNodeText(con, Dove.MAXLENGTH, "-1"); 2581 2582 String ftype = Utils.getAttribute(fieldDef, "ftype", null); 2584 String dttype = Utils.getAttribute(fieldDef, "dttype", null); 2585 Node prompt = Utils.selectSingleNode(fieldDef, "prompt"); 2586 Node descriptionTag = Utils.selectSingleNode(fieldDef, "description"); 2587 2588 if (dttype == null) { 2589 dttype = xmlSchemaType; 2620 2621 if (log.isDebugEnabled()) { 2622 log.debug("dttype was null, setting to " + xmlSchemaType); 2623 } 2624 } 2625 2626 if (ftype == null) { 2627 ftype = guiType; 2631 } 2632 2633 if ("upload".equals(ftype)) { 2647 if ("image".equals(dttype)) { 2648 ftype = "image"; 2649 dttype = "binary"; 2650 } else { 2651 ftype = "file"; 2652 dttype = "binary"; 2653 } 2654 } else if ("image".equals(ftype)) { 2655 if (!"binary".equals(dttype)) { 2657 dttype = "data"; 2658 } 2659 } 2660 2661 if (!"data".equals(ftype)) { 2668 if ("date".equals(dttype) || "time".equals(dttype)) { 2669 ftype = dttype; 2670 dttype = "datetime"; 2671 } else if ("datetime".equals(dttype) && 2672 (!"date".equals(ftype) && !"time".equals(ftype) && !"duration".equals(ftype))) { 2673 ftype = "datetime"; 2674 } 2675 } 2676 2677 if ("html".equals(dttype)) { 2680 ftype = "html"; 2681 dttype = "string"; 2682 } 2683 2684 if (prompt == null) { 2686 Utils.createAndAppendNode(fieldDef, "prompt", guiName); 2687 } 2688 2689 if (descriptionTag == null) { 2691 Utils.createAndAppendNode(fieldDef, "description", description); 2692 } 2693 2694 String dtrequired = Utils.getAttribute(fieldDef, "dtrequired", null); 2697 2698 if (dtrequired == null) { 2699 dtrequired = required; 2701 } 2702 2703 if ("wizard".equals(ftype)) { 2705 ftype = "startwizard"; 2706 } 2707 2708 Utils.setAttribute(fieldDef, "ftype", ftype); 2710 Utils.setAttribute(fieldDef, "dttype", dttype); 2711 2712 if (dtrequired != null) { 2713 Utils.setAttribute(fieldDef, "dtrequired", dtrequired); 2714 } 2715 2716 if ("string".equals(dttype) || "html".equals(dttype)) { 2718 String dtminlength = Utils.getAttribute(fieldDef, "dtminlength", null); 2719 2720 if (dtminlength == null) { 2721 if ("true".equals(dtrequired)) { 2723 Utils.setAttribute(fieldDef, "dtminlength", "1"); 2724 } 2725 } 2726 2727 String dtmaxlength = Utils.getAttribute(fieldDef, "dtmaxlength", null); 2728 2729 if (dtmaxlength == null) { 2730 int maxlen = -1; 2731 2732 try { 2733 maxlen = Integer.parseInt(maxLength); 2734 } catch (NumberFormatException e) { 2735 } 2736 2737 if (maxlen > 0) { 2740 Utils.setAttribute(fieldDef, "dtmaxlength", "" + maxlen); 2741 } 2742 } 2743 } 2744 } 2745 2746 2751 public Node getConstraints(String objecttype) { 2752 return getConstraints(objecttype, null); 2753 } 2754 2755 2761 public Node getConstraints(String objecttype, String fieldname) { 2762 Node con = Utils.selectSingleNode(constraints, 2765 "/*/getconstraints[@type='" + objecttype + "']"); 2766 2767 if (con == null) { 2768 try { 2770 con = databaseConnector.getConstraints(objecttype); 2771 } catch (Exception e) { 2772 log.error(Logging.stackTrace(e)); 2773 2774 return null; 2775 } 2776 2777 if (con == null) { 2778 log.debug("wizard.getConstraints: Could not retrieve MMBase constraints for objecttype:" + objecttype); 2780 2781 return null; 2782 } 2783 2784 con = constraints.importNode(con.cloneNode(true), true); 2786 constraints.getDocumentElement().appendChild(con); 2787 } 2788 2789 if (fieldname == null) { 2791 return con; 2792 } 2793 2794 Node fieldcon = Utils.selectSingleNode(con, "fields/field[@name='" + fieldname + "']"); 2796 2797 return fieldcon; 2798 } 2799 2800 class OrderByComparator implements Comparator { 2801 boolean compareByNumber = false; 2802 2803 OrderByComparator(String ordertype) { 2804 compareByNumber = ordertype.equals("number"); 2805 } 2806 2807 public int compare(Object o1, Object o2) { 2808 Element n1 = (Element) o1; 2809 Element n2 = (Element) o2; 2810 2811 String order1 = n1.getAttribute("orderby"); 2814 String order2 = n2.getAttribute("orderby"); 2815 2816 if (compareByNumber) { 2818 try { 2819 return Double.valueOf(order1).compareTo(Double.valueOf(order2)); 2820 } catch (Exception e) { 2821 log.error("Invalid field values (" + order1 + "/" + order2 + "):" + e); 2822 2823 return 0; 2824 } 2825 } else { 2826 return order1.compareToIgnoreCase(order2); 2827 } 2828 } 2829 } 2830 2831 2835 static class NodeCache extends Cache { 2836 NodeCache() { 2837 super(100); 2838 } 2839 2840 public String getName() { 2841 return "nodes"; 2842 } 2843 2844 public String getDescription() { 2845 return "objectNumber -> Node"; 2846 } 2847 } 2848 2849 2853 private static class WizardSchemaCache extends Cache { 2854 WizardSchemaCache() { 2855 super(100); 2856 } 2857 2858 public String getName() { 2859 return "Editwizard schemas"; 2860 } 2861 2862 public String getDescription() { 2863 return "File -> Editwizard schema Document (resolved includes/shortcuts)"; 2864 } 2865 2866 synchronized public Object put(URL f, Document doc, List dependencies) { 2867 Object retval = super.get(f); 2868 2869 if (retval != null) { 2870 return retval; 2871 } 2872 2873 return super.put(f, new Entry(f, doc, dependencies)); 2874 } 2875 2876 synchronized public Object remove(Object key) { 2877 URL file = (URL ) key; 2878 Entry entry = (Entry) get(file); 2879 2880 if ((entry != null) && (entry.fileWatcher != null)) { 2881 entry.fileWatcher.exit(); 2882 } else { 2883 log.warn("entry: " + entry); 2884 } 2885 2886 return super.remove(key); 2887 } 2888 2889 synchronized public Document getDocument(URL key) { 2890 Entry entry = (Entry) super.get(key); 2891 2892 if (entry == null) { 2893 return null; 2894 } 2895 2896 return entry.doc; 2897 } 2898 2899 private class Entry { 2900 Document doc; URL file; 2903 2906 ResourceWatcher fileWatcher = new ResourceWatcher(ResourceLoader.getWebRoot()) { 2907 public void onChange(String u) { 2908 WizardSchemaCache.this.remove(Entry.this.file); 2910 } 2912 }; 2913 2914 Entry(URL f, Document doc, List dependencies) { 2915 this.file = f; 2916 this.doc = doc; 2917 fileWatcher.add(f); 2918 2919 Iterator i = dependencies.iterator(); 2920 2921 while (i.hasNext()) { 2922 URL ff = (URL ) i.next(); 2923 fileWatcher.add(ff); 2924 } 2925 2926 fileWatcher.setDelay(10 * 1000); fileWatcher.start(); 2928 } 2929 } 2930 } 2931} 2932 | Popular Tags |