Author: michiel
Date: 2010-05-18 18:20:37 +0200 (Tue, 18 May 2010)
New Revision: 42226
Modified:
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/core/util/Fields.java
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/BuilderReader.java
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/ParentBuilderReader.java
Log:
MMB-1959
Modified:
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/core/util/Fields.java
===================================================================
---
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/core/util/Fields.java
2010-05-18 15:15:08 UTC (rev 42225)
+++
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/core/util/Fields.java
2010-05-18 16:20:37 UTC (rev 42226)
@@ -217,6 +217,8 @@
*/
public static class DataTypeSetter {
+ private int type = -1;
+ private int listItemType = -1;
protected AbstractField field;
public DataTypeSetter(AbstractField field) {
this.field = field;
@@ -227,6 +229,18 @@
public AbstractField getField() {
return field;
}
+ public int getType() {
+ return type == -1 ? field.getType() : type;
+ }
+ public int getListItemType() {
+ return listItemType == -1 ? field.getListItemType() : listItemType;
+ }
+ public void setType(int t) {
+ type = t;
+ }
+ public void setListItemType(int t) {
+ listItemType = t;
+ }
}
Modified:
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
===================================================================
---
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
2010-05-18 15:15:08 UTC (rev 42225)
+++
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
2010-05-18 16:20:37 UTC (rev 42226)
@@ -10,7 +10,9 @@
package org.mmbase.util.xml;
import java.util.*;
+import java.util.concurrent.*;
import java.util.regex.Pattern;
+import org.mmbase.datatypes.DataTypes.FieldNotFoundException;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
@@ -18,6 +20,8 @@
import org.mmbase.bridge.NodeManager;
import org.mmbase.core.CoreField;
import org.mmbase.core.util.Fields;
+import org.mmbase.core.AbstractField;
+import org.mmbase.core.event.*;
import org.mmbase.datatypes.*;
import org.mmbase.datatypes.util.xml.DataTypeReader;
import org.mmbase.datatypes.util.xml.DependencyException;
@@ -95,6 +99,31 @@
return
ResourceLoader.getConfigurationRoot().getChildResourceLoader("builders");
}
+ private static List<Runnable> postponedDataTypeDecoders = new
CopyOnWriteArrayList<Runnable>();
+
+ static {
+ EventManager.getInstance().addEventListener(new SystemEventListener() {
+ public void notify(SystemEvent se) {
+ if (se instanceof BuildersRead) {
+ int iterationCount = 0;
+ int size;
+ do {
+ if (log.isDebugEnabled()) {
+ log.debug(iterationCount + ": Builders are
read now, dealing with " + postponedDataTypeDecoders);
+ }
+ size = postponedDataTypeDecoders.size();
+ for (int i = 0; i < size; i++) {
+ Runnable job =
postponedDataTypeDecoders.remove(0);
+ job.run();
+ }
+ iterationCount++;
+ } while (postponedDataTypeDecoders.size() < size);
+
+ }
+ }
+ });
+ }
+
/**
* If false, the parent builder could not be resolved.
* A builder with an unresolved parent is set to 'inactive', regardless of
actual status
@@ -109,8 +138,8 @@
* editor/positions), which is used to find defaults if not specified.
* @since MMBase-1.7
*/
- protected SortedSet<Integer> searchPositions = new TreeSet<Integer>();
- protected SortedSet<Integer> inputPositions = new TreeSet<Integer>();
+ protected final SortedSet<Integer> searchPositions = new
TreeSet<Integer>();
+ protected final SortedSet<Integer> inputPositions = new
TreeSet<Integer>();
protected AbstractBuilderReader(InputSource source) {
super(source, true, true, AbstractBuilderReader.class);
@@ -441,6 +470,26 @@
}
}
+
+
+ protected void decodeDataTypeLater(final Fields.DataTypeSetter setter,
+ final String builder,
+ final DataTypeCollector collector,
+ final String fieldName,
+ final Element fieldElement,
+ final boolean forceInstance) {
+ postponedDataTypeDecoders.add(new Runnable() {
+ public void run() {
+ decodeDataType(setter, builder, collector, fieldName,
fieldElement, forceInstance);
+ }
+ public String toString() {
+ return "Decoding datatype for " + builder + ":" +
fieldName;
+ }
+ });
+ log.debug("Scheduling for later " + postponedDataTypeDecoders);
+
+ }
+
/**
* Determine a data type instance based on the given gui element
* @todo 'guitype' may become deprecated in favour of the 'datatype'
element
@@ -453,10 +502,18 @@
* @param forceInstance If true, it will never return <code>null</code>,
but will return (a clone) of the DataType associated with the database type.
* @since MMBase-1.8
*/
- protected DataType decodeDataType(final String builder, final
DataTypeCollector collector, final String fieldName, final Element field, final
int type, final int listItemType, final boolean forceInstance) {
+ protected void decodeDataType(final Fields.DataTypeSetter setter,
+ final String builder,
+ final DataTypeCollector collector,
+ final String fieldName,
+ final Element fieldElement,
+ final boolean forceInstance) {
BasicDataType baseDataType = null;
+ final int type = setter.getType();
+ final int listItemType = setter.getListItemType();
if (type == Field.TYPE_LIST) {
baseDataType = DataTypes.getListDataType(listItemType);
+ log.debug("Type was list, found base datatype " + baseDataType);
} else if (type != Field.TYPE_UNKNOWN) {
baseDataType = DataTypes.getDataType(type);
if (baseDataType == null) {
@@ -464,11 +521,11 @@
}
}
BasicDataType dataType = null;
- Element guiTypeElement = getElementByPath(field, "field.gui.guitype");
+ Element guiTypeElement = getElementByPath(fieldElement,
"field.gui.guitype");
// XXX: deprecated tag 'type'
if (guiTypeElement == null) {
- guiTypeElement = getElementByPath(field, "field.gui.type");
+ guiTypeElement = getElementByPath(fieldElement, "field.gui.type");
}
// Backwards compatible 'guitype' support
@@ -540,27 +597,44 @@
}
}
- Element dataTypeElement = getElementByPath(field, "field.datatype");
+ Element dataTypeElement = getElementByPath(fieldElement,
"field.datatype");
if (dataTypeElement != null) {
if (dataType != null) {
log.warn("Using both deprecated 'gui/guitype' and 'datatype'
subelements in field tag for field '" + fieldName + "', ignoring the first
one.");
}
BasicDataType requestedBaseDataType; // pointer to the original
field's datatype which will be used as a base.
- String base = dataTypeElement.getAttribute("base");
- if (base.equals("")) {
- if (log.isDebugEnabled()) {
- log.debug("No base defined, using '" + baseDataType + "'");
+ String fieldAttribute = dataTypeElement.getAttribute("field");
+ if (! fieldAttribute.equals("")) {
+ try {
+ requestedBaseDataType =
DataTypes.getDataTypeForFieldAttribute(fieldAttribute);
+ } catch (FieldNotFoundException ex) {
+ decodeDataTypeLater(setter,
+ builder,
+ collector,
+ fieldName,
+ fieldElement,
+ forceInstance);
+ log.service(" " + ex.getMessage() + " Will try again
later.");
+ return;
}
- if (baseDataType == null) {
- throw new
IllegalArgumentException(getDocument().getDocumentURI() + ":'" + fieldName +
"'. No base datatype given, and no field type defined");
- }
- requestedBaseDataType = baseDataType;
} else {
- requestedBaseDataType = collector == null ? null :
collector.getDataType(base, true);
- if (requestedBaseDataType == null) {
- log.error("Could not find base datatype for '" + base + "'
falling back to " + baseDataType + " in builder '" + (builder == null ? "NULL"
: builder) + "'");
+ String base = dataTypeElement.getAttribute("base");
+ if (base.equals("")) {
+ if (log.isDebugEnabled()) {
+ log.debug("No base defined, using '" + baseDataType +
"'");
+ }
+ if (baseDataType == null) {
+ throw new
IllegalArgumentException(getDocument().getDocumentURI() + ":'" +
+ fieldName + "'. No
base datatype given, and no field type defined");
+ }
requestedBaseDataType = baseDataType;
+ } else {
+ requestedBaseDataType = collector == null ? null :
collector.getDataType(base, true);
+ if (requestedBaseDataType == null) {
+ log.error("Could not find base datatype for '" + base
+ "' falling back to " + baseDataType + " in builder '" + (builder == null ?
"NULL" : builder) + "'");
+ requestedBaseDataType = baseDataType;
+ }
}
}
try {
@@ -589,7 +663,7 @@
dataType = (BasicDataType) baseDataType.clone(""); // clone with
empty id
}
- return dataType;
+ setter.set(dataType);
}
@@ -616,8 +690,7 @@
boolean readOnly = false;
if ("".equals(fieldReadOnly)) {
readOnly = state == Field.STATE_SYSTEM || state ==
Field.STATE_SYSTEM_VIRTUAL;
- }
- else {
+ } else {
readOnly = "true".equalsIgnoreCase(fieldReadOnly);
}
Modified:
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/BuilderReader.java
===================================================================
---
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/BuilderReader.java
2010-05-18 15:15:08 UTC (rev 42225)
+++
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/BuilderReader.java
2010-05-18 16:20:37 UTC (rev 42226)
@@ -19,8 +19,6 @@
import org.mmbase.core.CoreField;
import org.mmbase.core.util.Fields;
import org.mmbase.datatypes.*;
-import org.mmbase.datatypes.util.xml.DataTypeReader;
-import org.mmbase.datatypes.util.xml.DependencyException;
import org.mmbase.module.core.MMBase;
import org.mmbase.module.core.MMObjectBuilder;
import org.mmbase.storage.util.Index;
@@ -186,7 +184,7 @@
* @return a List of all Fields as CoreField
* @since MMBase-1.8
*/
- public List<CoreField> getFields(MMObjectBuilder builder,
DataTypeCollector collector) {
+ public List<CoreField> getFields(final MMObjectBuilder builder, final
DataTypeCollector collector) {
List<CoreField> results = new ArrayList<CoreField>();
Map<String, CoreField> oldset = new HashMap<String, CoreField>();
int pos = 1;
@@ -207,30 +205,38 @@
}
for(Element fieldList : getChildElements("builder", "fieldlist")) {
- for (Element field : getChildElements(fieldList,"field")) {
- String fieldName = getElementAttributeValue(field, "name");
+ for (final Element fieldElement :
getChildElements(fieldList,"field")) {
+ String fieldName = getElementAttributeValue(fieldElement,
"name");
if ("".equals(fieldName)) {
- fieldName =
getElementValue(getElementByPath(field,"field.db.name"));
+ fieldName =
getElementValue(getElementByPath(fieldElement,"field.db.name"));
}
- CoreField def = oldset.get(fieldName);
+ final CoreField def = oldset.get(fieldName);
try {
if (def != null) {
def.rewrite();
- DataType dataType = decodeDataType((builder != null ?
builder.getTableName() : null), collector, def.getName(), field, def.getType(),
def.getListItemType(), false);
- if (dataType != null) {
- def.setDataType(dataType); // replace datatype
- }
- decodeFieldDef(field, def, collector);
- decodeFieldAttributes(field, def);
- def.finish();
+
+ Fields.DataTypeSetter setter = new
Fields.DataTypeSetter(def) {
+ @Override
+ public void set(DataType dt) {
+ if (dt != null) {
+ field.setDataType(dt); // replace
datatype
+ }
+ decodeFieldDef(fieldElement, def,
collector);
+ decodeFieldAttributes(fieldElement, def);
+ def.finish();
+ }
+
+ };
+ decodeDataType(setter,
+ (builder != null ?
builder.getTableName() : null), collector, def.getName(), fieldElement, false);
} else {
- def = decodeFieldDef(builder, collector, field);
+ decodeFieldDef(fieldElement, def, collector);
def.setStoragePosition(pos++);
def.finish();
results.add(def);
}
} catch (Exception e) {
- log.error("During parsing of " + XMLWriter.write(field,
true, true) + " " + e.getMessage(), e);
+ log.error("During parsing of " +
XMLWriter.write(fieldElement, true, true) + " " + e.getMessage(), e);
}
}
}
@@ -436,13 +442,14 @@
* obtained from the builder configuration.
* @since MMBase-1.8
*/
- private CoreField decodeFieldDef(MMObjectBuilder builder,
DataTypeCollector collector, Element field) {
+ private CoreField decodeFieldDef(final MMObjectBuilder builder, final
DataTypeCollector collector,
+ final Element fieldElement) {
// create a new CoreField we need to fill
// obtain field name.
// if both the field name attribute and the <db><name> tag are
specified, the attribute takes precedence.
- String fieldName = getElementAttributeValue(field, "name");
- String fieldDBName = getElementValue(getElementByPath(field,
"field.db.name"));
+ String fieldName = getElementAttributeValue(fieldElement, "name");
+ String fieldDBName = getElementValue(getElementByPath(fieldElement,
"field.db.name"));
if ("".equals(fieldName)) {
if ("".equals(fieldDBName)) {
throw new IllegalArgumentException("Field name was not
specified for builder " + builder.getTableName() + ".");
@@ -458,94 +465,113 @@
// implied by datatype
// use db/type to override for legacy database issues
// (mostly to prevent warnings in the log, as mmbase fixes this anyway)
- String fieldType = "";
- String fieldSize = "";
- String fieldNotNull = "";
+ final String fieldType;
+ final String fieldSize;
+ final String fieldNotNull;
// defined in datatype
- String fieldRequired = "";
- String fieldUnique = "";
+ final String fieldRequired;
+ final String fieldUnique;
+
+ // type - default unknown (derived from datatype)
// deprecated db type tag - only use if no other data is given!
- Element dbtype = getElementByPath(field, "field.db.type");
+ Element dbtype = getElementByPath(fieldElement, "field.db.type");
if (dbtype != null) {
- if (!"".equals(fieldType) || !"".equals(fieldNotNull) ||
!"".equals(fieldSize)) {
- log.warn("Specified field type info for '" + fieldName + "'
twice: once in the field tag attributes and once in the <db><type> tag.");
- } else {
- if (log.isDebugEnabled()) {
- log.debug("<db><type> tag for field '" + fieldName + "' is
deprecated.");
- }
- fieldType = getElementValue(dbtype);
- fieldNotNull = getElementAttributeValue(dbtype, "notnull");
- fieldRequired = getElementAttributeValue(dbtype, "required");
- fieldUnique = getElementAttributeValue(dbtype, "unique");
- fieldSize = getElementAttributeValue(dbtype, "size");
+ if (log.isDebugEnabled()) {
+ log.debug("<db><type> tag for field '" + fieldName + "' is
deprecated.");
}
+ fieldType = getElementValue(dbtype);
+ fieldNotNull = getElementAttributeValue(dbtype, "notnull");
+ fieldRequired = getElementAttributeValue(dbtype, "required");
+ fieldUnique = getElementAttributeValue(dbtype, "unique");
+ fieldSize = getElementAttributeValue(dbtype, "size");
+ } else {
+ fieldType = "";
+ fieldNotNull = "";
+ fieldRequired = "";
+ fieldUnique = "";
+ fieldSize = "";
}
- // type - default unknown (derived from datatype)
- int type = Field.TYPE_UNKNOWN;
- int listItemType = Field.TYPE_UNKNOWN;
- if (!"".equals(fieldType)) {
- type = Fields.getType(fieldType);
- if (type == Field.TYPE_LIST) {
- if (fieldType.length() > 5) {
- listItemType = Fields.getType(fieldType.substring(5,
fieldType.length() - 1));
+ final int type;
+ final int listItemType;
+ {
+ int _type = Field.TYPE_UNKNOWN;
+ int _listItemType = Field.TYPE_UNKNOWN;
+ if (!"".equals(fieldType)) {
+ _type = Fields.getType(fieldType);
+ if (_type == Field.TYPE_LIST) {
+ if (fieldType.length() > 5) {
+ _listItemType = Fields.getType(fieldType.substring(5,
fieldType.length()));
+ }
}
}
+ type = _type;
+ listItemType = _listItemType;
}
- // datatype
- DataType dataType = decodeDataType((builder != null ?
builder.getTableName() : null), collector, fieldName, field, type,
listItemType, true);
+ final CoreField def = Fields.createField(fieldName, type, listItemType,
+ Field.STATE_VIRTUAL,/*temp
default, will set by decodeFieldAttributes*/
+ Constants.DATATYPE_UNKNOWN);
- // determine type from datatype, if possible)
- if (type == Field.TYPE_UNKNOWN) {
- type = dataType.getBaseType();
- if (type == Field.TYPE_LIST) {
- listItemType =
((ListDataType)dataType).getItemDataType().getBaseType();
- }
- }
+ Fields.DataTypeSetter setter = new Fields.DataTypeSetter(def) {
+ @Override
+ public void set(DataType dataType) {
+ def.setDataType(dataType);
+ // determine type from datatype, if possible)
+ int _type = getType();
+ if (_type == Field.TYPE_UNKNOWN) {
+ setType(dataType.getBaseType());
+ if (_type == Field.TYPE_LIST) {
+
setListItemType(((ListDataType)dataType).getItemDataType().getBaseType());
+ }
+ }
- CoreField def = Fields.createField(fieldName, type, listItemType,
- Field.STATE_VIRTUAL,/*temp default,
will set by decodeFieldAttributes*/
- dataType);
- dataType = def.getDataType();
+ dataType = def.getDataType();
- decodeFieldAttributes(field, def);
+ decodeFieldAttributes(fieldElement, def);
- def.setParent(builder);
+ def.setParent(builder);
- if (!fieldSize.equals("")) {
- try {
- def.setMaxLength(Integer.parseInt(fieldSize));
- } catch (NumberFormatException e) {
- log.warn("invalid value for size : " + fieldSize);
- }
- }
+ if (!fieldSize.equals("")) {
+ try {
+ def.setMaxLength(Integer.parseInt(fieldSize));
+ } catch (NumberFormatException e) {
+ log.warn("invalid value for size : " + fieldSize);
+ }
+ }
- // set required property, but only if given
- if (!"".equals(fieldRequired)) {
- dataType.setRequired("true".equalsIgnoreCase(fieldRequired));
- }
+ // set required property, but only if given
+ if (!"".equals(fieldRequired)) {
+
dataType.setRequired("true".equalsIgnoreCase(fieldRequired));
+ }
- // default for notnull is value of required
- def.setNotNull("true".equals(fieldNotNull) || ("".equals(fieldNotNull)
&& dataType.isRequired()));
+ // default for notnull is value of required
+ def.setNotNull("true".equals(fieldNotNull) ||
("".equals(fieldNotNull) && dataType.isRequired()));
- if (def.isNotNull() && ! "false".equalsIgnoreCase(fieldRequired)) { //
If not null, it _must_ be required, unless explicitely not so (MMB-1504)
- dataType.setRequired(true);
- }
+ if (def.isNotNull() && !
"false".equalsIgnoreCase(fieldRequired)) { // If not null, it _must_ be
required, unless explicitely not so (MMB-1504)
+ dataType.setRequired(true);
+ }
- // set unique property, but only if given
- if ("implied".equalsIgnoreCase(fieldUnique)) {
- dataType.setUnique(true);
-
dataType.getUniqueRestriction().setEnforceStrength(DataType.ENFORCE_NEVER);
- } else if ("true".equalsIgnoreCase(fieldUnique)) {
- dataType.setUnique(true);
- }
+ // set unique property, but only if given
+ if ("implied".equalsIgnoreCase(fieldUnique)) {
+ dataType.setUnique(true);
+
dataType.getUniqueRestriction().setEnforceStrength(DataType.ENFORCE_NEVER);
+ } else if ("true".equalsIgnoreCase(fieldUnique)) {
+ dataType.setUnique(true);
+ }
- decodeFieldDef(field, def, collector);
+ decodeFieldDef(fieldElement, def, collector);
+ }
+ };
+ // datatype
+ decodeDataType(setter,
+ (builder != null ? builder.getTableName() : null),
collector, fieldName, fieldElement, true);
+
+
return def;
}
Modified:
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/ParentBuilderReader.java
===================================================================
---
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/ParentBuilderReader.java
2010-05-18 15:15:08 UTC (rev 42225)
+++
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/xml/ParentBuilderReader.java
2010-05-18 16:20:37 UTC (rev 42226)
@@ -11,6 +11,7 @@
package org.mmbase.util.xml;
import org.mmbase.datatypes.DataType;
+import org.mmbase.datatypes.Constants;
import org.mmbase.core.util.Fields;
import org.mmbase.util.xml.AbstractBuilderReader;
import org.mmbase.bridge.mock.MockField;
@@ -115,23 +116,38 @@
}
}
- int type = Field.TYPE_UNKNOWN;
+
+ final Element dbtype = getElementByPath(field,
"field.db.type");
+
+ final MockField newField = new MockField(fieldName, null,
Constants.DATATYPE_UNKNOWN);
+ Fields.DataTypeSetter setter = new
Fields.DataTypeSetter(newField) {
+ @Override
+ public void set(DataType dt) {
+ super.set(dt);
+ if (dbtype != null) {
+ if
("true".equals(dbtype.getAttribute("notnull"))) {// legacy
+ dt.setRequired(true);
+ }
+ }
+ }
+ };
// legacy support
- Element dbtype = getElementByPath(field, "field.db.type");
- if (dbtype != null) {
- type = Fields.getType(getNodeTextValue(dbtype));
- }
- DataType dt = decodeDataType(getName(),
org.mmbase.datatypes.DataTypes.getSystemCollector(),
- fieldName, field, type,
Field.TYPE_UNKNOWN, true);
if (dbtype != null) {
- if ("true".equals(dbtype.getAttribute("notnull"))) {//
legacy
- dt.setRequired(true);
+ String fieldType = getNodeTextValue(dbtype);
+ setter.setType(Fields.getType(fieldType));
+ if (setter.getType() == Field.TYPE_LIST) {
+ if (fieldType.length() > 5) {
+ String subType = fieldType.substring(5,
fieldType.length());
+ setter.setListItemType(Fields.getType(subType));
+ }
}
}
+ decodeDataType(setter,
+ getName(),
org.mmbase.datatypes.DataTypes.getSystemCollector(),
+ fieldName, field, true);
- MockField newField = new MockField(fieldName, null, dt);
String fieldState = getElementAttributeValue(field, "state");
if ("".equals(fieldState)) {
newField.setState(Field.STATE_PERSISTENT);
@@ -139,6 +155,7 @@
newField.setState(Fields.getState(fieldState));
}
assert newField.getName().length() > 0 :
XMLWriter.write(field);
+
results.add(newField);
}
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs