1 10 package org.mmbase.util.xml; 11 12 import java.util.*; 13 import org.w3c.dom.*; 14 import org.xml.sax.InputSource ; 15 import org.mmbase.bridge.Field; 16 import org.mmbase.bridge.NodeManager; 17 import org.mmbase.core.CoreField; 18 import org.mmbase.core.util.Fields; 19 import org.mmbase.datatypes.*; 20 import org.mmbase.datatypes.util.xml.DataTypeReader; 21 import org.mmbase.module.core.MMBase; 22 import org.mmbase.module.core.MMObjectBuilder; 23 import org.mmbase.storage.util.Index; 24 25 import org.mmbase.util.LocalizedString; 26 import org.mmbase.util.XMLEntityResolver; 27 import org.mmbase.util.functions.*; 28 import org.mmbase.util.logging.*; 29 30 41 public class BuilderReader extends DocumentReader { 42 43 44 public static final String PUBLIC_ID_BUILDER_1_0 = "-//MMBase//DTD builder config 1.0//EN"; 45 46 public static final String PUBLIC_ID_BUILDER_1_1 = "-//MMBase//DTD builder config 1.1//EN"; 47 48 private static final String PUBLIC_ID_BUILDER_1_0_FAULT = "-//MMBase/DTD builder config 1.0//EN"; 50 private static final String PUBLIC_ID_BUILDER_OLD = "/MMBase - builder//"; 51 private static final String PUBLIC_ID_BUILDER_1_1_FAULT = "-//MMBase/DTD builder config 1.1//EN"; 52 53 54 public static final String DTD_BUILDER_1_0 = "builder_1_0.dtd"; 55 56 public static final String DTD_BUILDER_1_1 = "builder_1_1.dtd"; 57 58 59 public static final String PUBLIC_ID_BUILDER = PUBLIC_ID_BUILDER_1_1; 60 61 public static final String DTD_BUILDER = DTD_BUILDER_1_1; 62 63 public static final String XSD_BUILDER_2_0 = "builder.xsd"; 64 public static final String NAMESPACE_BUILDER_2_0 = "http://www.mmbase.org/xmlns/builder"; 65 public static final String NAMESPACE_BUILDER = NAMESPACE_BUILDER_2_0; 66 67 private static final Logger log = Logging.getLoggerInstance(BuilderReader.class); 68 69 73 public static void registerSystemIDs() { 74 XMLEntityResolver.registerSystemID(NAMESPACE_BUILDER_2_0 + ".xsd", XSD_BUILDER_2_0, BuilderReader.class); 75 } 76 77 78 82 public static void registerPublicIDs() { 83 XMLEntityResolver.registerPublicID(PUBLIC_ID_BUILDER_1_0, DTD_BUILDER_1_0, BuilderReader.class); 85 XMLEntityResolver.registerPublicID(PUBLIC_ID_BUILDER_1_1, DTD_BUILDER_1_1, BuilderReader.class); 86 88 XMLEntityResolver.registerPublicID(PUBLIC_ID_BUILDER_1_0_FAULT, DTD_BUILDER_1_0, BuilderReader.class); 90 XMLEntityResolver.registerPublicID(PUBLIC_ID_BUILDER_OLD, DTD_BUILDER_1_0, BuilderReader.class); 91 XMLEntityResolver.registerPublicID(PUBLIC_ID_BUILDER_1_1_FAULT, DTD_BUILDER_1_1, BuilderReader.class); 92 } 93 94 97 private MMBase mmbase; 98 99 105 private MMObjectBuilder parentBuilder; 106 107 113 private boolean inheritanceResolved = false; 114 115 116 121 private SortedSet searchPositions = new TreeSet(); 122 private SortedSet inputPositions = new TreeSet(); 123 124 127 public BuilderReader(InputSource source, MMBase mmb) { 128 super(source, BuilderReader.class); 129 mmbase = mmb; 130 resolveInheritance(); 131 } 132 133 136 public BuilderReader(Document doc, MMBase mmb) { 137 super(doc); 138 mmbase = mmb; 139 resolveInheritance(); 140 } 141 142 156 protected boolean resolveInheritance() { 157 String buildername = getExtends(); 158 if (buildername.equals("")) { 159 parentBuilder = null; 160 inheritanceResolved = true; 161 } else { 162 inheritanceResolved = false; 163 if (mmbase != null) { 164 parentBuilder = mmbase.getBuilder(buildername); 165 inheritanceResolved = (parentBuilder != null); 166 if (inheritanceResolved) { Iterator fields = parentBuilder.getFields(NodeManager.ORDER_EDIT).iterator(); 168 while (fields.hasNext()) { 169 CoreField def = (CoreField) fields.next(); 170 inputPositions.add(new Integer (def.getEditPosition())); 171 } 172 fields = parentBuilder.getFields(NodeManager.ORDER_SEARCH).iterator(); 173 while (fields.hasNext()) { 174 CoreField def = (CoreField) fields.next(); 175 searchPositions.add(new Integer (def.getSearchPosition())); 176 } 177 } 178 } 179 } 180 return inheritanceResolved; 181 } 182 183 192 public boolean isInheritanceResolved() { 193 return inheritanceResolved; 194 } 195 196 201 public String getStatus() { 202 if (!inheritanceResolved) { 203 return "inactive"; } else { 205 String val = getElementValue("builder.status").toLowerCase(); 206 if (!val.equals("inactive")) { 207 val = "active"; } 210 return val; 211 } 212 } 213 214 221 public int getSearchAge() { 222 int val = 30; 223 String sval = getElementValue("builder.searchage"); 224 if (sval.equals("") && (parentBuilder != null)) { 225 sval = parentBuilder.getSearchAge(); 226 } 227 try { 228 val = Integer.parseInt(sval); 229 } catch(Exception f) {} 230 return val; 231 } 232 233 241 public String getClassName() { 242 String val = getElementValue("builder.class"); 243 if (val.equals("")) { 244 val = getElementValue("builder.classfile"); } 246 247 if (val.equals("")) { 248 if (parentBuilder != null) { 249 return parentBuilder.getClass().getName(); 250 } else { 251 return ""; 252 } 253 } 254 int pos = val.indexOf('.'); 256 if (pos==-1) { 257 val = "org.mmbase.module.builders."+val; 258 } 259 if ("org.mmbase.module.corebuilders.ObjectTypes".equals(val)) { 260 log.warn("Specified the removed builder 'ObjectTypes', fall back to TypeDef. You can remove all core-builders from your configuration directory (the ones present in mmbase.jar are ok)"); 261 val = "org.mmbase.module.corebuilders.TypeDef"; 262 } 263 return val; 264 } 265 266 272 public Map getDataTypes(DataTypeCollector collector) { 273 Element element = getElementByPath("builder.datatypes"); 274 if (element != null) { 275 DataTypeReader.readDataTypes(element, collector); 276 } 277 return collector.getDataTypes(); 278 } 279 280 287 public List getFields() { 288 return getFields(null, DataTypes.getSystemCollector()); 289 } 290 291 300 public List getFields(MMObjectBuilder builder, DataTypeCollector collector) { 301 List results = new ArrayList(); 302 Map oldset = new HashMap(); 303 int pos = 1; 304 if (parentBuilder != null) { 305 List parentfields = parentBuilder.getFields(NodeManager.ORDER_CREATE); 306 if (parentfields != null) { 307 for (Iterator i = parentfields.iterator();i.hasNext();) { 310 CoreField f = (CoreField)i.next(); 311 CoreField newField = (CoreField)f.clone(f.getName()); 312 newField.setParent(builder); 313 while(newField.getStoragePosition() >= pos) pos++; 314 newField.finish(); 315 results.add(newField); 316 oldset.put(newField.getName(), newField); 317 } 318 } 319 } 320 321 for(Iterator ns = getChildElements("builder.fieldlist", "field"); ns.hasNext(); ) { 322 Element field = (Element) ns.next(); 323 String fieldName = getElementAttributeValue(field, "name"); 324 if ("".equals(fieldName)) { 325 fieldName = getElementValue(getElementByPath(field,"field.db.name")); 326 } 327 CoreField def = (CoreField) oldset.get(fieldName); 328 try { 329 if (def != null) { 330 def.rewrite(); 331 DataType dataType = decodeDataType(builder, collector, def.getName(), field, def.getType(), def.getListItemType(), false); 332 if (dataType != null) { 333 def.setDataType(dataType); } 335 decodeFieldDef(field, def, collector); 336 def.finish(); 337 } else { 338 def = decodeFieldDef(builder, collector, field); 339 def.setStoragePosition(pos++); 340 def.finish(); 341 results.add(def); 342 } 343 } catch (Exception e) { 344 log.error("During parsing of " + XMLWriter.write(field, true, true) + " " + e.getMessage(), e); 345 } 346 } 347 348 return results; 349 } 350 351 359 public List getIndices(MMObjectBuilder builder) { 360 List results = new ArrayList(); 361 Index mainIndex = null; 362 if (parentBuilder != null) { 363 Index parentIndex = parentBuilder.getStorageConnector().getIndex(Index.MAIN); 365 if (parentIndex != null) { 366 mainIndex = new Index(builder, Index.MAIN); 367 mainIndex.setUnique(true); 368 for (Iterator i = parentIndex.iterator(); i.hasNext(); ) { 369 Field field = (Field)i.next(); 370 mainIndex.add(builder.getField(field.getName())); 371 } 372 } 373 } 374 375 for (Iterator fields = getChildElements("builder.fieldlist","field"); fields.hasNext(); ) { 376 Element field = (Element)fields.next(); 377 Element dbtype = getElementByPath(field,"field.db.type"); 378 if (dbtype != null) { 379 String key = getElementAttributeValue(dbtype,"key"); 380 if (key != null && key.equalsIgnoreCase("true")) { 381 String fieldName = getElementAttributeValue(field, "name"); 382 if ("".equals(fieldName)) { 383 fieldName = getElementValue(getElementByPath(field,"field.db.name")); 384 } 385 if (mainIndex == null ) mainIndex = new Index(builder, Index.MAIN); 386 mainIndex.add(builder.getField(fieldName)); 387 } 388 } 389 } 390 if (mainIndex != null) { 391 results.add(mainIndex); 392 } 393 394 if (parentBuilder != null) { 395 Collection parentIndices = parentBuilder.getStorageConnector().getIndices().values(); 396 if (parentIndices != null) { 397 for (Iterator i = parentIndices.iterator();i.hasNext();) { 398 Index parentIndex = (Index)i.next(); 399 Index newIndex = new Index(builder, parentIndex.getName());; 400 newIndex.setUnique(parentIndex.isUnique()); 401 for (Iterator parentIndexIter = parentIndex.iterator(); parentIndexIter.hasNext(); ) { 402 Field field = (Field) parentIndexIter.next(); 403 newIndex.add(builder.getField(field.getName())); 404 } 405 results.add(newIndex); 406 } 407 } 408 } 409 410 411 for(Iterator indices = getChildElements("builder.indexlist","index"); indices.hasNext(); ) { 412 Element indexElement = (Element)indices.next(); 413 String indexName = indexElement.getAttribute("name"); 414 if (indexName != null && !indexName.equals("")) { 415 String unique = indexElement.getAttribute("unique"); 416 Index index = new Index(builder, indexName); 417 index.setUnique(unique != null && unique.equals("true")); 418 for(Iterator fields = getChildElements(indexElement,"indexfield"); fields.hasNext(); ) { 419 Element fieldElement = (Element)fields.next(); 420 String fieldName = fieldElement.getAttribute("name"); 421 Field field = builder.getField(fieldName); 422 if (field == null) { 423 log.error("field '" + fieldName +"' in index '" + indexName + "' in builder " + builder.getTableName() + " does not exist"); 424 } else { 425 index.add(field); 426 } 427 } 428 results.add(index); 429 } else { 430 log.error("index in builder " + builder.getTableName() + " has no name"); 431 } 432 } 433 return results; 434 } 435 436 439 public Set getFunctions() { 440 Set results = new HashSet(); 441 for(Iterator ns = getChildElements("builder.functionlist","function"); ns.hasNext(); ) { 442 try { 443 Element functionElement = (Element)ns.next(); 444 final String functionName = functionElement.getAttribute("name"); 445 String providerKey = functionElement.getAttribute("key"); 446 String functionClass = getNodeTextValue(getElementByPath(functionElement, "function.class")); 447 448 Function function; 449 log.service("Using " + functionClass); 450 Class claz = Class.forName(functionClass); 451 if (Function.class.isAssignableFrom(claz)) { 452 if (!providerKey.equals("")) { 453 log.warn("Specified a key attribute for a Function " + claz + " in " + getSystemId() + ", this makes only sense for FunctionProviders."); 454 } 455 function = (Function) claz.newInstance(); 456 } else if (FunctionProvider.class.isAssignableFrom(claz)) { 457 if ("".equals(providerKey)) providerKey = functionName; 458 if ("".equals(providerKey)) { 459 log.error("FunctionProvider " + claz + " specified in " + getSystemId() + " without key or name"); 460 continue; 461 } 462 FunctionProvider provider = (FunctionProvider) claz.newInstance(); 463 function = provider.getFunction(providerKey); 464 } else { 465 if ("".equals(providerKey)) providerKey = functionName; 466 if ("".equals(providerKey)) { 467 log.error("Speficied class " + claz + " in " + getSystemId() + "/functionslist/function is not a Function or FunctionProvider and can not be wrapped in a BeanFunction, because neither key nor name attribute were specified."); 468 continue; 469 } 470 function = BeanFunction.getFunction(claz, providerKey); 471 } 472 if (! functionName.equals("") && ! function.getName().equals(functionName)) { 473 log.service("Wrapping " + function.getName() + " to " + functionName); 474 function = new WrappedFunction(function) { 475 public String getName() { 476 return functionName; 477 } 478 }; 479 } 480 if (! (function instanceof NodeFunction)) { 481 Parameters test = function.createParameters(); 484 if (test.containsParameter(Parameter.NODE)) { 485 final Function f = function; 486 function = new NodeFunction(function.getName(), function.getParameterDefinition(), function.getReturnType()) { 487 protected Object getFunctionValue(org.mmbase.bridge.Node node, Parameters parameters) { 488 if (parameters == null) parameters = createParameters(); 489 parameters.set(Parameter.NODE, node); 490 return f.getFunctionValue(parameters); 491 } 492 public Object getFunctionValue(Parameters parameters) { 493 return f.getFunctionValue(parameters); 494 } 495 }; 496 } 497 } 498 499 results.add(function); 500 } catch (Throwable e) { 501 log.error(e.getMessage(), e); 502 } 503 504 } 505 506 507 return results; 508 509 } 510 511 517 private int getEditorPos(Element elm) { 518 try { 519 int val = Integer.parseInt(getElementValue(elm)); 520 return val; 521 } catch(Exception e) { 522 return -1; 523 } 524 } 525 532 private void decodeFieldDef(Element field, CoreField def, DataTypeCollector collector) { 533 Element descriptions = getElementByPath(field, "field.descriptions"); 535 if (descriptions != null) { 536 def.getLocalizedDescription().fillFromXml("description", descriptions); 537 } 538 539 Element gui = getElementByPath(field, "field.gui"); 541 if (gui != null) { 542 def.getLocalizedGUIName().fillFromXml("guiname", gui); 543 def.getLocalizedGUIName().fillFromXml("name", gui); 545 } 546 547 Element editorpos = getElementByPath(field, "field.editor.positions.input"); 549 if (editorpos != null) { 550 int inputPos = getEditorPos(editorpos); 551 if (inputPos > -1) inputPositions.add(new Integer (inputPos)); 552 def.setEditPosition(inputPos); 553 } else { 554 int i = 1; 556 while (inputPositions.contains(new Integer (i))) { 557 ++i; 558 } 559 inputPositions.add(new Integer (i)); 560 def.setEditPosition(i); 561 562 } 563 editorpos = getElementByPath(field, "field.editor.positions.list"); 564 if (editorpos != null) { 565 def.setListPosition(getEditorPos(editorpos)); 566 } 567 editorpos = getElementByPath(field, "field.editor.positions.search"); 568 if (editorpos != null) { 569 int searchPos = getEditorPos(editorpos); 570 if (searchPos > -1) searchPositions.add(new Integer (searchPos)); 571 def.setSearchPosition(searchPos); 572 } else { 573 if (def.getType() != Field.TYPE_BINARY && !def.isVirtual()) { 576 int i = 1; 577 while (searchPositions.contains(new Integer (i))) { 578 ++i; 579 } 580 searchPositions.add(new Integer (i)); 581 def.setSearchPosition(i); 582 } else { 583 def.setSearchPosition(-1); 584 } 585 } 586 } 587 588 600 protected DataType decodeDataType(final MMObjectBuilder builder, final DataTypeCollector collector, final String fieldName, final Element field, final int type, final int listItemType, final boolean forceInstance) { 601 BasicDataType baseDataType = null; 602 if (type == Field.TYPE_LIST) { 603 baseDataType = DataTypes.getListDataType(listItemType); 604 } else if (type != Field.TYPE_UNKNOWN) { 605 baseDataType = DataTypes.getDataType(type); 606 } 607 BasicDataType dataType = null; 608 Element guiTypeElement = getElementByPath(field, "field.gui.guitype"); 609 610 if (guiTypeElement == null) { 612 guiTypeElement = getElementByPath(field, "field.gui.type"); 613 } 614 615 if (guiTypeElement != null && collector != null) { 617 if (baseDataType == null) { 618 throw new IllegalArgumentException ("No type defined"); 619 } 620 String guiType = getElementValue(guiTypeElement); 621 if (!guiType.equals("")) { 622 if (guiType.indexOf('.') != -1) { 623 dataType = (BasicDataType) baseDataType.clone(); 626 dataType.getEnumerationFactory().addBundle(guiType, getClass().getClassLoader(), null, dataType.getTypeAsClass(), null); 627 dataType.getEnumerationRestriction().setEnforceStrength(DataType.ENFORCE_NEVER); 628 } else { 629 MMObjectBuilder enumerationBuilder = null; 631 if ("string".equals(guiType)) { 635 guiType = "line"; 636 if (log.isDebugEnabled()) { 637 log.debug("Converted deprecated guitype 'string' for field " + (builder != null ? builder.getTableName() + "." : "") + fieldName + " with datatype 'line'."); 638 } 639 } else 640 if ("eventtime".equals(guiType)) { 642 guiType = "datetime"; 643 if (log.isDebugEnabled()) { 644 log.debug("Converted deprecated guitype 'eventtime' for field " + (builder != null ? builder.getTableName() + "." : "") + fieldName + " with datatype 'datetime'."); 645 } 646 } else 647 if ("relativetime".equals(guiType)) { 649 guiType = "duration"; 650 if (log.isDebugEnabled()) { 651 log.debug("Converted deprecated guitype 'relativetime' for field " + (builder != null ? builder.getTableName() + "." : "") + fieldName + " with datatype 'duration'."); 652 } 653 } else 654 if (type == Field.TYPE_NODE) { 656 try { 657 enumerationBuilder = mmbase.getBuilder(guiType); 658 } catch (RuntimeException re) { 659 log.warn("Exception during parsing of field '" + fieldName + "' of " + (builder != null ? builder.getTableName() : "NULL") + ": " + re.getMessage()); 660 } 661 } 662 if (enumerationBuilder != null) { 663 Element queryElement = guiTypeElement.getOwnerDocument().createElementNS("http://www.mmbase.org/xmlns/searchquery", "query"); 667 queryElement.setAttribute("type", enumerationBuilder.getTableName()); 668 dataType = (BasicDataType) baseDataType.clone(); 669 Document queryDocument = DocumentReader.toDocument(queryElement); 670 dataType.getEnumerationFactory().addQuery(LocalizedString.getLocale(queryElement), queryDocument); 671 dataType.getEnumerationRestriction().setEnforceStrength(DataType.ENFORCE_NEVER); 672 } else { 673 dataType = collector.getDataTypeInstance(guiType, baseDataType); 674 if (dataType == null) { 675 log.warn("Could not find data type for " + baseDataType + " / " + guiType + " for builder: '" + (builder == null ? "NULL" : builder.getTableName()) + "'"); 676 } 677 } 678 } 679 } 680 } 681 682 Element dataTypeElement = getElementByPath(field, "field.datatype"); 683 684 if (dataTypeElement != null) { 685 if (dataType != null) { 686 log.warn("Using both deprecated 'gui/guitype' and 'datatype' subelements in field tag for field '" + fieldName + "', ignoring the first one."); 687 } 688 BasicDataType requestedBaseDataType; String base = dataTypeElement.getAttribute("base"); 690 if (base.equals("")) { 691 if (log.isDebugEnabled()) { 692 log.debug("No base defined, using '" + baseDataType + "'"); 693 } 694 if (baseDataType == null) { 695 throw new IllegalArgumentException ("No base datatype given, and no field type defined"); 696 } 697 requestedBaseDataType = baseDataType; 698 } else { 699 requestedBaseDataType = collector == null ? null : collector.getDataType(base, true); 700 if (requestedBaseDataType == null) { 701 log.error("Could not find base datatype for '" + base + "' falling back to " + baseDataType + " in builder '" + (builder == null ? "NULL" : builder.getTableName()) + "'"); 702 requestedBaseDataType = baseDataType; 703 } 704 } 705 dataType = (BasicDataType) DataTypeReader.readDataType(dataTypeElement, requestedBaseDataType, collector).dataType; 706 if (log.isDebugEnabled()) log.debug("Found datatype " + dataType + " for field " + fieldName); 707 } 708 709 if (dataType != null && baseDataType != null && !baseDataType.getClass().isAssignableFrom(dataType.getClass())) { 711 BasicDataType newDataType = (BasicDataType) dataType.clone(); 714 newDataType.inherit(baseDataType); 715 if (log.isDebugEnabled()) log.debug("" + dataType + " in '" + getSystemId() + "' field " + fieldName + " is not compatible with " + baseDataType + ". Cloning and inheriting to support gracefull fall backs -> " + newDataType); 716 dataType = newDataType; 717 } 718 719 if (dataType == null && forceInstance) { 720 if (baseDataType == null) { 722 throw new IllegalArgumentException ("No datatype given, and no type defined"); 723 } 724 dataType = (BasicDataType) baseDataType.clone(""); } 726 727 return dataType; 728 } 729 730 735 private CoreField decodeFieldDef(MMObjectBuilder builder, DataTypeCollector collector, Element field) { 736 738 String fieldName = getElementAttributeValue(field, "name"); 741 String fieldDBName = getElementValue(getElementByPath(field, "field.db.name")); 742 if ("".equals(fieldName)) { 743 if ("".equals(fieldDBName)) { 744 throw new IllegalArgumentException ("Field name was not specified for builder " + builder.getTableName() + "."); 745 } 746 if (log.isDebugEnabled()) { 747 log.debug("<db><name> tag for field '" + fieldDBName + "' is deprecated. Use the name attribute."); 748 } 749 fieldName = fieldDBName; 750 } else if (!"".equals(fieldDBName)) { 751 log.warn("Specified field name twice: once in the name attribute ('" + fieldName + "') and once in the <name> tag ('" + fieldDBName + "'). Ignoring name tag."); 752 } 753 754 String fieldState = getElementAttributeValue(field, "state"); 755 String fieldReadOnly = getElementAttributeValue(field, "readonly"); 756 757 String fieldType = ""; 761 String fieldSize = ""; 762 String fieldNotNull = ""; 763 764 String fieldRequired = ""; 766 String fieldUnique = ""; 767 768 Element dbtype = getElementByPath(field, "field.db.type"); 770 if (dbtype != null) { 771 if (!"".equals(fieldType) || !"".equals(fieldNotNull) || !"".equals(fieldSize)) { 772 log.warn("Specified field type info for '" + fieldName + "' twice: once in the field tag attributes and once in the <db><type> tag."); 773 } else { 774 if (log.isDebugEnabled()) { 775 log.debug("<db><type> tag for field '" + fieldName + "' is deprecated."); 776 } 777 fieldType = getElementValue(dbtype); 778 fieldState = getElementAttributeValue(dbtype, "state"); 779 fieldReadOnly = getElementAttributeValue(dbtype, "readonly"); 780 fieldNotNull = getElementAttributeValue(dbtype, "notnull"); 781 fieldRequired = getElementAttributeValue(dbtype, "required"); 782 fieldUnique = getElementAttributeValue(dbtype, "unique"); 783 fieldSize = getElementAttributeValue(dbtype, "size"); 784 } 785 } 786 787 int type = Field.TYPE_UNKNOWN; 789 int listItemType = Field.TYPE_UNKNOWN; 790 if (!"".equals(fieldType)) { 791 type = Fields.getType(fieldType); 792 if (type == Field.TYPE_LIST) { 793 if (fieldType.length() > 5) { 794 listItemType = Fields.getType(fieldType.substring(5, fieldType.length() - 1)); 795 } 796 } 797 } 798 799 DataType dataType = decodeDataType(builder, collector, fieldName, field, type, listItemType, true); 801 802 if (type == Field.TYPE_UNKNOWN) { 804 type = dataType.getBaseType(); 805 if (type == Field.TYPE_LIST) { 806 listItemType = ((ListDataType)dataType).getItemDataType().getBaseType(); 807 } 808 } 809 810 int state = Field.STATE_PERSISTENT; 812 if (!"".equals(fieldState)) { state = Fields.getState(fieldState); } 813 814 CoreField def = Fields.createField(fieldName, type, listItemType, state, dataType); 815 dataType = def.getDataType(); 816 817 def.setParent(builder); 818 819 if (!fieldSize.equals("")) { 820 try { 821 def.setMaxLength(Integer.parseInt(fieldSize)); 822 } catch (NumberFormatException e) { 823 log.warn("invalid value for size : " + fieldSize); 824 } 825 } 826 827 if (!"".equals(fieldReadOnly)) { 829 def.setReadOnly("true".equalsIgnoreCase(fieldReadOnly)); 830 } 831 832 if (!"".equals(fieldRequired)) { 834 dataType.setRequired("true".equalsIgnoreCase(fieldRequired)); 835 } 836 837 def.setNotNull("true".equals(fieldNotNull) || ("".equals(fieldNotNull) && dataType.isRequired())); 839 840 if ("implied".equalsIgnoreCase(fieldUnique)) { 842 dataType.setUnique(true); 843 dataType.getUniqueRestriction().setEnforceStrength(DataType.ENFORCE_NEVER); 844 } else if ("true".equalsIgnoreCase(fieldUnique)) { 845 dataType.setUnique(true); 846 } 847 848 decodeFieldDef(field, def, collector); 849 850 return def; 851 } 852 853 858 public Hashtable getProperties() { 859 Hashtable results=new Hashtable(); 860 if (parentBuilder != null) { 861 Map parentparams = parentBuilder.getInitParameters(); 862 if (parentparams != null) { 863 results.putAll(parentparams); 864 } 865 } 866 for(Iterator iter = getChildElements("builder.properties","property"); 867 iter.hasNext(); ) { 868 Element p = (Element)iter.next(); 869 String name = getElementAttributeValue(p,"name"); 870 String value = getElementValue(p); 871 results.put(name,value); 872 } 873 return results; 874 } 875 876 877 882 public Hashtable getDescriptions() { 883 Hashtable results=new Hashtable(); 884 Element tmp; 885 String lang; 886 for (Iterator iter = getChildElements("builder.descriptions","description"); 887 iter.hasNext(); ) { 888 tmp = (Element)iter.next(); 889 lang = getElementAttributeValue(tmp,"xml:lang"); 890 results.put(lang,getElementValue(tmp)); 891 } 892 return results; 893 } 894 895 900 public Hashtable getPluralNames() { 901 Hashtable results=new Hashtable(); 902 for (Iterator iter = getChildElements("builder.names","plural"); iter.hasNext(); ) { 903 Element tmp = (Element)iter.next(); 904 String lang = getElementAttributeValue(tmp,"xml:lang"); 905 results.put(lang,getElementValue(tmp)); 906 } 907 return results; 908 } 909 910 915 public Hashtable getSingularNames() { 916 Hashtable results=new Hashtable(); 917 for (Iterator iter = getChildElements("builder.names","singular"); iter.hasNext(); ) { 918 Element tmp = (Element)iter.next(); 919 String lang = getElementAttributeValue(tmp,"xml:lang"); 920 results.put(lang,getElementValue(tmp)); 921 } 922 return results; 923 } 924 925 926 932 public MMObjectBuilder getParentBuilder() { 933 return parentBuilder; 934 } 935 936 941 public String getExtends() { 942 return getElementAttributeValue("builder", "extends"); 943 } 944 945 950 public int getVersion() { 951 String version = getElementAttributeValue("builder","version"); 952 if (version.equals("") && parentBuilder != null) { 953 return parentBuilder.getVersion(); 954 } else { 955 int n = 0; 956 if (!version.equals("")) { 957 try { 958 n = Integer.parseInt(version); 959 } catch (Exception f) {} 960 } 961 return n; 962 } 963 } 964 965 970 public String getMaintainer() { 971 String maintainer = getElementAttributeValue("builder", "maintainer"); 972 if (maintainer.equals("")) { 973 if (parentBuilder != null) { 974 maintainer = parentBuilder.getMaintainer(); 975 } else { 976 maintainer = "mmbase.org"; 977 } 978 } 979 return maintainer; 980 } 981 982 986 public boolean equals(Object o) { 987 if (o instanceof BuilderReader) { 988 BuilderReader b = (BuilderReader) o; 989 List fields = getFields(); 990 List otherFields = b.getFields(); 991 return 992 fields.equals(otherFields) && 993 getMaintainer().equals(b.getMaintainer()) && 994 getVersion() == b.getVersion() && 995 getExtends().equals(b.getExtends()) && 996 getSingularNames().equals(b.getSingularNames()) && 997 getPluralNames().equals(b.getPluralNames()) && 998 getDescriptions().equals(b.getDescriptions()) && 999 getProperties().equals(b.getProperties()) && 1000 getClassName().equals(b.getClassName()) 1001 ; 1002 } else { 1003 return false; 1004 } 1005 } 1006 1007 1011 public boolean storageEquals(BuilderReader f) { 1012 List otherFields = f.getFields(); 1013 List thisFields = getFields(); 1014 if (otherFields.size() != thisFields.size()) return false; 1015 for (int i = 0; i < thisFields.size(); i++) { 1016 CoreField thisField = (CoreField) thisFields.get(i); 1017 CoreField otherField = (CoreField) otherFields.get(i); 1018 if (! thisField.storageEquals(otherField)) return false; 1019 } 1020 return true; 1021 } 1022 1023 1026 public static void main(String [] argv) throws Exception { 1027 org.mmbase.util.ResourceLoader rl = org.mmbase.util.ResourceLoader.getSystemRoot(); 1028 Document doc = rl.getDocument(argv[0], true, BuilderReader.class); 1029 new BuilderReader(doc, null); 1030 } 1031 1032} 1033 1034
| Popular Tags
|