Author: pierre
Date: 2010-01-12 16:40:27 +0100 (Tue, 12 Jan 2010)
New Revision: 40534

Modified:
   
mmbase/trunk/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
   mmbase/trunk/core/src/main/java/org/mmbase/util/xml/resources/builder.xsd
Log:
MMB-1907

Modified: 
mmbase/trunk/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java
===================================================================
--- 
mmbase/trunk/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java  
    2010-01-12 15:35:47 UTC (rev 40533)
+++ 
mmbase/trunk/core/src/main/java/org/mmbase/util/xml/AbstractBuilderReader.java  
    2010-01-12 15:40:27 UTC (rev 40534)
@@ -152,34 +152,88 @@
             }
         }
 
-        for (String list : new String[] {"names", "descriptions", 
"properties"}) {
-            // if these are found, simply all sub-elements must be added.
+        // add and replace names and descriptions, identified by xml:lang
+        mergeElementLists(doc, overrides, "names", "singular", "xml:lang", 
true);
+        mergeElementLists(doc, overrides, "names", "plural", "xml:lang", true);
+        mergeElementLists(doc, overrides, "descriptions", "description", 
"xml:lang", true);
 
-            List<Element> elementList = 
getChildElements(doc.getDocumentElement(), list);
-            Element element;
-            if (elementList.size() == 0) {
-                element = doc.createElement(list);
-                doc.getDocumentElement().appendChild(element);
-            } else {
-                element = elementList.get(elementList.size() - 1);
-            }
-            for (Element overridesList : 
getChildElements(overrides.getDocumentElement(), list)) {
-                for (Element e : getChildElements(overridesList, "*")) {
-                    Element newE = (Element) doc.importNode(e, true);
-                    element.appendChild(newE);
-                }
-            }
-        }
+        // add and replace properties, identified by name
+        mergeElementLists(doc, overrides, "properties", "property", "name", 
true);
 
-        for (String list : new String[] {"fieldlist", "functionlist", 
"indexlist"}) {
-            // if these are found, they simply must be added too.
+        // add and merge fields, functions, and indices, identified by name
+        // (or replace them if the override attribute is set to replace)
+        mergeElementLists(doc, overrides, "fieldlist", "field", "name", false);
+        mergeElementLists(doc, overrides, "functionlist", "function", "name", 
false);
+        mergeElementLists(doc, overrides, "indexlist", "index", "name", false);
 
-            for(Element el : getChildElements(overrides.getDocumentElement(), 
list)) {
+    }
+
+    /**
+     * Copy a list of elements, identified by an attribute, from overrides to 
doc.
+     * Replace or merge those elements if they already exist in doc under that 
attribute.
+     * Merging an element means either adding or replacing the sub tags of 
that element.
+     * @param doc The receiving builder xml document. This one will be changed.
+     * @param overrides The builder xml document that provided overriding 
information. This one will only
+     * be read.
+     * @param list The tagname of list element(s) containign the items
+     * @param item The tagname of the list item element
+     * @param attr The attribute identifying the item (i.e. "name" or 
"xml:lang")
+     * @param replace if <code>true</code>, the item is entirely replaced. If 
<code>false</code>, it is merged.
+     * @since MMBase-1.9
+     */
+    protected static void mergeElementLists(Document doc, Document overrides, 
String list, String item, String attr, boolean replace) {
+        Element docListEl = getElementByPath(doc.getDocumentElement(), 
"builder." + list);
+        for (Element listEl : getChildElements(overrides.getDocumentElement(), 
list)) {
+            for (Element el : getChildElements(listEl, item)) {
+                if (docListEl == null) {
+                    docListEl = doc.createElement(list);
+                    doc.getDocumentElement().appendChild(docListEl);
+                }
                 Element newEl = (Element) doc.importNode(el, true);
-                doc.getDocumentElement().appendChild(newEl);
+                String name = newEl.getAttribute(attr);
+                // determine if an item should be replaced or merged
+                boolean replaceItem = replace;
+                String replaceAttr = newEl.getAttribute("override");
+                if (replaceAttr != null) {
+                    replaceItem = replaceAttr.equals("replace");
+                }
+                Element docEl = null;
+                if (name != null && !(name.equals(""))) {
+                    for(Element orgListEl : 
getChildElements(doc.getDocumentElement(), list)) {
+                        for(Element orgEl : getChildElements(docListEl, item)) 
{
+                            if (name.equals(orgEl.getAttribute(attr))) {
+                                docListEl = orgListEl;
+                                docEl = orgEl;
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (docEl != null) {
+                    if (replaceItem) { // replace an item
+                        docListEl.replaceChild(newEl, docEl);
+                    } else { // merge an item (iow add and or replace subtags)
+                        // merge attributes
+                        NamedNodeMap attributes = newEl.getAttributes();
+                        for (int i = 0; i < attributes.getLength(); i++) {
+                            Attr attribute = (Attr) 
(attributes.item(i).cloneNode(true));
+                            docEl.setAttributeNode(attribute);
+                        }
+                        // merge element tags
+                        for (Element newFel : getChildElements(newEl)) {
+                            Element docFel = getElementByPath(docEl, "field." 
+ newFel.getLocalName());
+                            if (docFel != null) {
+                                docEl.replaceChild(newFel,docFel);
+                            } else {
+                                docEl.appendChild(newFel);
+                            }
+                        }
+                    }
+                } else {
+                    docListEl.appendChild(newEl);
+                }
             }
         }
-
     }
 
     /**

Modified: 
mmbase/trunk/core/src/main/java/org/mmbase/util/xml/resources/builder.xsd
===================================================================
--- mmbase/trunk/core/src/main/java/org/mmbase/util/xml/resources/builder.xsd   
2010-01-12 15:35:47 UTC (rev 40533)
+++ mmbase/trunk/core/src/main/java/org/mmbase/util/xml/resources/builder.xsd   
2010-01-12 15:40:27 UTC (rev 40534)
@@ -137,6 +137,14 @@
           </xsd:restriction>
         </xsd:simpleType>
       </xsd:attribute>
+      <xsd:attribute name="override">
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="replace" />
+            <xsd:enumeration value="merge" />
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
       <xsd:attribute name="readonly">
         <xsd:simpleType>
           <xsd:restriction base="xsd:string">
@@ -267,12 +275,21 @@
       <xsd:attribute ref="xml:base" />
     </xsd:complexType>
   </xsd:element>
+
   <xsd:element name="index">
     <xsd:complexType>
       <xsd:sequence>
         <xsd:element ref="indexfield" maxOccurs="unbounded" />
       </xsd:sequence>
       <xsd:attribute name="name" type="xsd:string" use="required" />
+      <xsd:attribute name="override">
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="replace" />
+            <xsd:enumeration value="merge" />
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
       <xsd:attribute name="unique">
         <xsd:simpleType>
           <xsd:restriction base="xsd:string">
@@ -283,6 +300,7 @@
       </xsd:attribute>
     </xsd:complexType>
   </xsd:element>
+
   <xsd:element name="indexfield">
     <xsd:complexType>
       <xsd:attribute name="name" type="xsd:string" use="required" />
@@ -297,6 +315,7 @@
       <xsd:attribute ref="xml:base" />
     </xsd:complexType>
   </xsd:element>
+
   <xsd:element name="function">
     <xsd:complexType>
       <xsd:sequence>
@@ -305,6 +324,14 @@
       <xsd:attribute ref="xml:base" />
       <xsd:attribute name="name" type="xsd:string" />
       <xsd:attribute name="key" type="xsd:string" />
+      <xsd:attribute name="override">
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="replace" />
+            <xsd:enumeration value="merge" />
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
     </xsd:complexType>
   </xsd:element>
 

_______________________________________________
Cvs mailing list
Cvs@lists.mmbase.org
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to