tim         2004/01/26 21:50:09

  Modified:    src/blocks/woody/java/org/apache/cocoon/woody/binding
                        InsertBeanJXPathBinding.java
                        InsertNodeJXPathBinding.java
                        RepeaterJXPathBinding.java
                        TempRepeaterJXPathBinding.java
                        TempRepeaterJXPathBindingBuilder.java
               src/blocks/woody/samples/forms form_model_gui_binding.xml
  Log:
  Make the InsertNodeJXPathBinding actually insert its node
  and the InsertBeanJXPathBinding actually insert its bean
  instead of registering a factory do the insert later.
  Together with associated changes to RepeaterJXPathBinding
  and TempRepeaterJXPathBinding, the insert node and bean
  implementation now matches the documentation.
  
  Also, the TempRepeaterJXPathBinding was modified to
  support virtual rows for DOM bindings.  This provides
  a virtual JXPath context for the selected row data,
  making it easier to bind to rows that do not have a
  common row element wrapped around them.
  
  The sample form model GUI binding was updated to use
  these new/modified features.  This binding now works
  correctly, except for adding extraneous whitespace to
  the output document.
  
  Revision  Changes    Path
  1.6       +52 -30    
cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/InsertBeanJXPathBinding.java
  
  Index: InsertBeanJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/InsertBeanJXPathBinding.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- InsertBeanJXPathBinding.java      11 Jan 2004 20:51:16 -0000      1.5
  +++ InsertBeanJXPathBinding.java      27 Jan 2004 05:50:08 -0000      1.6
  @@ -97,35 +97,57 @@
        * inside this object into the target objectmodel.
        */
       public void doSave(Widget frmModel, JXPathContext jxpc) throws 
BindingException {
  -        jxpc.setFactory(new AbstractFactory() {
  -            public boolean createObject(JXPathContext context, Pointer 
pointer,
  -                                        Object parent, String name, int 
index) {
  -                try {
  -                    Object[] args = new Object[1];
  -                    Class[] argTypes = new Class[1];
  +        try {
  +            Object parent = jxpc.getContextBean();
  +            Object[] args = new Object[1];
  +            Class[] argTypes = new Class[1];
   
  -                    // instantiate the new object
  -                    argTypes[0] = 
Class.forName(InsertBeanJXPathBinding.this.className);
  -                    args[0] = argTypes[0].newInstance();
  -                    // lookup the named method on the parent
  +            // instantiate the new object
  +            argTypes[0] = Class.forName(this.className);
  +            args[0] = argTypes[0].newInstance();
   
  -                    Method addMethod =
  -                        
parent.getClass().getMethod(InsertBeanJXPathBinding.this.addMethodName, 
argTypes);
  -                    // invoke this method with this new beast.
  +            // lookup the named method on the parent
  +            Method addMethod =
  +                parent.getClass().getMethod(this.addMethodName, argTypes);
   
  -                    addMethod.invoke(parent, args);
  +            // invoke this method with this new beast.
  +            addMethod.invoke(parent, args);
   
  -                    if (getLogger().isDebugEnabled())
  -                        getLogger().debug("InsertBean jxpath factory 
executed for index " + index);
  -                    return true;
  -                } catch (Exception e) {
  -                    throw new CascadingRuntimeException("InsertBean jxpath 
factory failed.", e);
  -                }
  -            }
  -        });
  +            if (getLogger().isDebugEnabled())
  +                getLogger().debug("InsertBean performed.");
  +        } catch (Exception e) {
  +            throw new CascadingRuntimeException("InsertBean failed.", e);
  +        }
   
  -        if (getLogger().isDebugEnabled())
  -            getLogger().debug("done registered factory for inserting node -- 
" + toString());
  +        // jxpc.setFactory(new AbstractFactory() {
  +        //     public boolean createObject(JXPathContext context, Pointer 
pointer,
  +        //                                 Object parent, String name, int 
index) {
  +        //         try {
  +        //             Object[] args = new Object[1];
  +        //             Class[] argTypes = new Class[1];
  +        //
  +        //             // instantiate the new object
  +        //             argTypes[0] = 
Class.forName(InsertBeanJXPathBinding.this.className);
  +        //             args[0] = argTypes[0].newInstance();
  +        //             // lookup the named method on the parent
  +        //
  +        //             Method addMethod =
  +        //                 
parent.getClass().getMethod(InsertBeanJXPathBinding.this.addMethodName, 
argTypes);
  +        //             // invoke this method with this new beast.
  +        //
  +        //             addMethod.invoke(parent, args);
  +        //
  +        //             if (getLogger().isDebugEnabled())
  +        //                 getLogger().debug("InsertBean jxpath factory 
executed for index " + index);
  +        //             return true;
  +        //         } catch (Exception e) {
  +        //             throw new CascadingRuntimeException("InsertBean 
jxpath factory failed.", e);
  +        //         }
  +        //     }
  +        // });
  +        //
  +        // if (getLogger().isDebugEnabled())
  +        //     getLogger().debug("done registered factory for inserting node 
-- " + toString());
       }
   
       public String toString() {
  
  
  
  1.6       +24 -16    
cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/InsertNodeJXPathBinding.java
  
  Index: InsertNodeJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/InsertNodeJXPathBinding.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- InsertNodeJXPathBinding.java      11 Jan 2004 20:51:16 -0000      1.5
  +++ InsertNodeJXPathBinding.java      27 Jan 2004 05:50:08 -0000      1.6
  @@ -97,23 +97,31 @@
        */
       public void doSave(Widget frmModel, JXPathContext jxpc) {
   
  -        jxpc.setFactory(new AbstractFactory() {
  -            public boolean createObject(JXPathContext context, Pointer 
pointer,
  -                Object parent, String name, int index) {
  -
  -                Node parentNode = (Node) parent;
  -                Document targetDoc = parentNode.getOwnerDocument();
  -                Node toInsert = 
targetDoc.importNode(InsertNodeJXPathBinding.this.template, true);
  -                parentNode.appendChild(toInsert);
  -
  -                if (getLogger().isDebugEnabled())
  -                    getLogger().debug("InsertNode jxpath factory executed 
for index." + index);
  -                return true;
  -            }
  -        });
  +        Node parentNode = (Node)jxpc.getContextBean();
  +        Document targetDoc = parentNode.getOwnerDocument();
  +        Node toInsert = targetDoc.importNode(this.template, true);
  +        parentNode.appendChild(toInsert);
   
           if (getLogger().isDebugEnabled())
  -            getLogger().debug("done registered factory for inserting node -- 
" + toString());
  +            getLogger().debug("InsertNode executed.");
  +
  +        // jxpc.setFactory(new AbstractFactory() {
  +        //     public boolean createObject(JXPathContext context, Pointer 
pointer,
  +        //         Object parent, String name, int index) {
  +        //
  +        //         Node parentNode = (Node) parent;
  +        //         Document targetDoc = parentNode.getOwnerDocument();
  +        //         Node toInsert = 
targetDoc.importNode(InsertNodeJXPathBinding.this.template, true);
  +        //         parentNode.appendChild(toInsert);
  +        //
  +        //         if (getLogger().isDebugEnabled())
  +        //             getLogger().debug("InsertNode jxpath factory executed 
for index." + index);
  +        //         return true;
  +        //     }
  +        // });
  +        //
  +        // if (getLogger().isDebugEnabled())
  +        //     getLogger().debug("done registered factory for inserting node 
-- " + toString());
       }
   
       public String toString() {
  
  
  
  1.16      +4 -2      
cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/RepeaterJXPathBinding.java
  
  Index: RepeaterJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/RepeaterJXPathBinding.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- RepeaterJXPathBinding.java        11 Jan 2004 20:51:16 -0000      1.15
  +++ RepeaterJXPathBinding.java        27 Jan 2004 05:50:08 -0000      1.16
  @@ -278,9 +278,11 @@
               if (this.insertRowBinding != null) {
                   Iterator rowIterator = rowsToInsert.iterator();
                   //register the factory!
  -                this.insertRowBinding.saveFormToModel(repeater, 
repeaterContext);
  +                //this.insertRowBinding.saveFormToModel(repeater, 
repeaterContext);
                   while (rowIterator.hasNext()) {
                       Repeater.RepeaterRow thisRow = (Repeater.RepeaterRow) 
rowIterator.next();
  +                    // Perform the insert row binding.
  +                    this.insertRowBinding.saveFormToModel(repeater, 
repeaterContext);
                       // -->  create the path to let the context be created
                       Pointer newRowContextPointer = 
repeaterContext.createPath(this.rowPathForInsert + "[" + indexCount + "]");
                       JXPathContext newRowContext = 
repeaterContext.getRelativeContext(newRowContextPointer);
  
  
  
  1.4       +99 -44    
cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/TempRepeaterJXPathBinding.java
  
  Index: TempRepeaterJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/TempRepeaterJXPathBinding.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TempRepeaterJXPathBinding.java    11 Jan 2004 20:51:16 -0000      1.3
  +++ TempRepeaterJXPathBinding.java    27 Jan 2004 05:50:08 -0000      1.4
  @@ -81,12 +81,13 @@
       private final JXPathBindingBase rowBinding;
       private final JXPathBindingBase insertRowBinding;
       private final boolean deleteIfEmpty;
  +    private final boolean virtualRows;
   
       public TempRepeaterJXPathBinding(
               JXpathBindingBuilderBase.CommonAttributes commonAtts,
               String repeaterId, String repeaterPath,
               String rowPath, String rowPathInsert,
  -            boolean clearOnLoad, boolean deleteIfEmpty,
  +            boolean virtualRows, boolean clearOnLoad, boolean deleteIfEmpty,
               JXPathBindingBase rowBinding, JXPathBindingBase insertBinding) {
           super(commonAtts);
           this.repeaterId = repeaterId;
  @@ -97,38 +98,53 @@
           this.rowBinding.setParent(this);
           this.insertRowBinding = insertBinding;
           this.insertRowBinding.setParent(this);
  +        this.virtualRows = virtualRows;
           this.clearOnLoad = clearOnLoad;
           this.deleteIfEmpty = deleteIfEmpty;
       }
   
       public void doLoad(Widget frmModel, JXPathContext jctx) {
  -        // Find the repeater and clear it
  +        // (There should be a general widget type checker for all the 
bindings to use,
  +        // coupled with a general informative exception class to throw if 
the widget is
  +        // of the wrong type or null.)
           Repeater repeater = (Repeater) frmModel.getWidget(this.repeaterId);
  -
  -        // TODO: RAD
           if (repeater == null) {
  +            String fullId = frmModel.getFullyQualifiedId();
  +            if (fullId == null || fullId.length() == 0) {
  +                fullId = "";
  +            } else {
  +                fullId = fullId + ".";
  +            }
               throw new RuntimeException(
  -                    "frmModel.getLocation() = " + frmModel.getLocation() +
  -                    "  repeaterId = " + this.repeaterId);
  +                "TempRepeaterJXPathBinding: Repeater \"" + fullId + 
this.repeaterId +
  +                "\" does not exist (" + frmModel.getLocation() + ")");
           }
  -
  + 
  +        // Start by clearing the repeater, if necessary.
           if (this.clearOnLoad) {
               repeater.removeRows();
           }
   
  -        // Move to repeater context
  -        Pointer ptr = jctx.getPointer(this.repeaterPath);
  -        if (ptr.getNode() != null) {
  -            // There are some nodes to load from
  +        // Find the location of the repeater data.
  +        Pointer repeaterPointer = jctx.getPointer(this.repeaterPath);
  +
  +        // Check if there is data present.
  +        //
  +        // (Otherwise, should we check the leniency config option
  +        // to decide whether to be silent or throw an exception?) 
  +        if (repeaterPointer != null) {
   
  -            JXPathContext repeaterContext = jctx.getRelativeContext(ptr);
  -            // build a jxpath iterator for pointers
  +            // Narrow to repeater context.
  +            JXPathContext repeaterContext = 
jctx.getRelativeContext(repeaterPointer);
  +
  +            // Build a jxpath iterator for the repeater row pointers.
               Iterator rowPointers = 
repeaterContext.iteratePointers(this.rowPath);
   
  -            //iterate through it
  +            // Iterate through the rows of data.
               int rowNum = 0;
               while (rowPointers.hasNext()) {
  -                // Get a row. It is created if needed (depends on 
clearOnLoad)
  +
  +                // Get or create a row widget.
                   Repeater.RepeaterRow thisRow;
                   if (repeater.getSize() > rowNum) {
                       thisRow = repeater.getRow(rowNum);
  @@ -137,10 +153,29 @@
                   }
                   rowNum++;
   
  -                // make a jxpath sub context on the iterated element
  -                Pointer jxp = (Pointer) rowPointers.next();
  -                JXPathContext rowContext = 
repeaterContext.getRelativeContext(jxp);
  +                // Narrow to the row context.
  +                Pointer rowPointer = (Pointer) rowPointers.next();
  +                JXPathContext rowContext = 
repeaterContext.getRelativeContext(rowPointer);
  +
  +                // If virtual rows are requested, place a deep clone of the 
row data
  +                // into a temporary node, and narrow the context to this 
virtual row.
  +                //
  +                // (A clone of the data is used to prevent modifying the 
source document.
  +                // Otherwise, the appendChild method would remove the data 
from the source
  +                // document.  Is this protection worth the penalty of a deep 
clone?)
  +                //
  +                // (This implementation of virtual rows currently only 
supports DOM
  +                // bindings, but could easily be extended to support other 
bindings.)
  +
  +                if (virtualRows == true) {
  +                    Node repeaterNode = (Node)repeaterPointer.getNode();
  +                    Node virtualNode = 
repeaterNode.getOwnerDocument().createElementNS(null, "virtual");
  +                    Node clone = 
((Node)rowPointer.getNode()).cloneNode(true);
  +                    virtualNode.appendChild(clone);
  +                    rowContext = JXPathContext.newContext(repeaterContext, 
virtualNode);
  +                }
   
  +                // Finally, perform the load row binding.
                   this.rowBinding.loadFormFromModel(thisRow, rowContext);
               }
           }
  @@ -150,47 +185,67 @@
       }
   
       public void doSave(Widget frmModel, JXPathContext jctx) throws 
BindingException {
  -        // Find the repeater
  +        // (See comment in doLoad about type checking and throwing a 
meaningful exception.)
           Repeater repeater = (Repeater) frmModel.getWidget(this.repeaterId);
   
  +        // Perform shortcut binding if the repeater is empty
  +        // and the deleteIfEmpty config option is selected.
           if (repeater.getSize() == 0 && this.deleteIfEmpty) {
  -            // Repeater is empty : erase all
  +            // Delete all of the old data for this repeater.
               jctx.removeAll(this.repeaterPath);
   
  +        // Otherwise perform the normal save binding.
           } else {
  -            // Repeater is not empty
   
  -            // Move to repeater context and create the path if needed
  +            // Narrow to the repeater context, creating the path if it did 
not exist.
               JXPathContext repeaterContext = 
jctx.getRelativeContext(jctx.createPath(this.repeaterPath));
   
  -            // Delete all that is already present
  +            // Start by deleting all of the old row data.
               repeaterContext.removeAll(this.rowPath);
   
  +            // Verify that repeater is not empty and has an insert row 
binding.
               if(repeater.getSize() > 0) {
                   if (this.insertRowBinding != null) {
  +
                       //register the factory!
  -                    this.insertRowBinding.saveFormToModel(repeater, 
repeaterContext);
  +                    //this.insertRowBinding.saveFormToModel(repeater, 
repeaterContext);
  +
  +                    // Iterate through the repeater rows.
                       for (int i = 0; i < repeater.getSize(); i++) {
  -                        java.lang.System.err.println("TempRepeater: Bind 
row.");
  -                        //String path = this.rowPathInsert + '[' + (i+1) + 
']';
  -                        // -->  create the path to let the context be created
  -                        //Pointer rowPtr = repeaterContext.createPath(path);
  -                        //JXPathContext rowContext = 
repeaterContext.getRelativeContext(rowPtr);
  -                        Node node = (Node)repeaterContext.getContextBean();
  -                        Node virtualNode = 
node.getOwnerDocument().createElementNS(null, "virtual");
  -                        //JXPathContext rowContext = 
JXPathContext.newContext(repeaterContext, virtualNode);
  -                        JXPathContext rowContext = 
JXPathContext.newContext(repeaterContext, virtualNode);
  -                        //    + bind to children for output
  +
  +                        // Narrow to the repeater row context.
  +                        Pointer rowPointer = 
repeaterContext.getPointer(this.rowPathInsert);
  +                        JXPathContext rowContext = 
repeaterContext.getRelativeContext(rowPointer);
  +
  +                        // Variables used for virtual rows.
  +                        // They are initialized here just to keep the 
compiler happy. 
  +                        Node rowNode = null;
  +                        Node virtualNode = null;
  +
  +                        // If virtual rows are requested, create a temporary 
node and
  +                        // narrow the context to this initially empty new 
virtual row.
  +                        if (virtualRows == true) {
  +                            rowNode = (Node)rowContext.getContextBean();
  +                            virtualNode = 
rowNode.getOwnerDocument().createElementNS(null, "virtual");
  +                            rowContext = 
JXPathContext.newContext(repeaterContext, virtualNode);
  +                        }
  +
  +                        // Perform the insert row binding
  +                        this.insertRowBinding.saveFormToModel(repeater, 
rowContext);
  +
  +                        // Perform the save row binding.
                           this.rowBinding.saveFormToModel(repeater.getRow(i), 
rowContext);
  -                        // Append children to current path.
  -                        NodeList list = virtualNode.getChildNodes();
  -                        java.lang.System.err.println("Node count: " + 
list.getLength());
  -                        //node.appendChild(virtualNode);
  -                        int count = list.getLength();
  -                        for (int j = 0; j < count; j++) {
  -                            java.lang.System.err.println("Hello, child not 
null. j: " + j);
  -                            node.appendChild(list.item(0));
  -                            java.lang.System.err.println("After. j: " + j);
  +
  +                        // If virtual rows are requested, finish by 
appending the
  +                        // children of the virtual row to the real context 
node.
  +                        if (virtualRows == true) {
  +                            NodeList list = virtualNode.getChildNodes();
  +                            int count = list.getLength();
  +                            for (int j = 0; j < count; j++) {
  +                                // The list shrinks when a child is appended 
to the context
  +                                // node, so we always reference the first 
child in the list.
  +                                rowNode.appendChild(list.item(0));
  +                            }
                           }
                           getLogger().debug("bound new row");
                       }
  
  
  
  1.3       +6 -3      
cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/TempRepeaterJXPathBindingBuilder.java
  
  Index: TempRepeaterJXPathBindingBuilder.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/java/org/apache/cocoon/woody/binding/TempRepeaterJXPathBindingBuilder.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TempRepeaterJXPathBindingBuilder.java     11 Jan 2004 20:51:16 -0000      
1.2
  +++ TempRepeaterJXPathBindingBuilder.java     27 Jan 2004 05:50:08 -0000      
1.3
  @@ -82,6 +82,7 @@
               String parentPath = DomHelper.getAttribute(bindingElem, 
"parent-path");
               String rowPath = DomHelper.getAttribute(bindingElem, "row-path");
               String rowPathInsert = DomHelper.getAttribute(bindingElem, 
"row-path-insert", rowPath);
  +            boolean virtualRows = 
DomHelper.getAttributeAsBoolean(bindingElem, "virtual-rows", false);
               boolean clearOnLoad = 
DomHelper.getAttributeAsBoolean(bindingElem, "clear-before-load", true);
               boolean deleteIfEmpty = 
DomHelper.getAttributeAsBoolean(bindingElem, "delete-parent-if-empty", false);
   
  @@ -98,13 +99,15 @@
               if (insertWrapElement != null)
                   insertBindings = 
assistant.makeChildBindings(insertWrapElement);
   
  -            return new TempRepeaterJXPathBinding( commonAtts, repeaterId, 
parentPath, rowPath, rowPathInsert, clearOnLoad, deleteIfEmpty,
  +            return new TempRepeaterJXPathBinding(
  +                commonAtts, repeaterId, parentPath, rowPath, rowPathInsert, 
virtualRows, clearOnLoad, deleteIfEmpty,
                   new 
ComposedJXPathBindingBase(JXpathBindingBuilderBase.CommonAttributes.DEFAULT, 
childBindings),
                   new 
ComposedJXPathBindingBase(JXpathBindingBuilderBase.CommonAttributes.DEFAULT, 
insertBindings));
           } catch (BindingException e) {
               throw e;
           } catch (Exception e) {
  -            throw new BindingException("Error building temp-repeater binding 
defined at " + DomHelper.getLocation(bindingElem), e);
  +            throw new BindingException("Error building temp-repeater binding 
defined at " +
  +                DomHelper.getLocation(bindingElem), e);
           }
       }
   }
  
  
  
  1.2       +85 -125   
cocoon-2.1/src/blocks/woody/samples/forms/form_model_gui_binding.xml
  
  Index: form_model_gui_binding.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/woody/samples/forms/form_model_gui_binding.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- form_model_gui_binding.xml        29 Dec 2003 06:14:50 -0000      1.1
  +++ form_model_gui_binding.xml        27 Jan 2004 05:50:09 -0000      1.2
  @@ -1,23 +1,25 @@
   <?xml version="1.0" encoding="ISO-8859-1"?>
  +
  +<!--
  +Binding for example CForms form model GUI.
  +
  [EMAIL PROTECTED]: Tim Larson
  [EMAIL PROTECTED] CVS $Id$
  +-->
  +
   <wb:context
     xmlns:wb="http://apache.org/cocoon/woody/binding/1.0";
     xmlns:wd="http://apache.org/cocoon/woody/definition/1.0";
     path="/wd:form"
     lenient="true">
   
  -  <!--
  -    This binding needs lots of work...
  -
  -    CVS $Id$
  -    Author: Timothy Larson
  -  -->
  -
     <wb:new id="widgets-class"/>
   
     <wb:class id="widgets-class">
       <wb:temp-repeater id="widgets"
         parent-path="wd:widgets"
  -      row-path="*">
  +      row-path="*" row-path-insert="."
  +      virtual-rows="true">
         <wb:on-bind>
           <wb:new id="widget-row-class"/>
         </wb:on-bind>
  @@ -27,17 +29,10 @@
     <wb:class id="widget-row-class">
       <wb:javascript id="type" path=".">
         <wb:load-form>
  -        widget.setValue(jxpathPointer.getNode().getLocalName());
  +        var node = jxpathPointer.getNode().getFirstChild();
  +        widget.setValue(node.getLocalName());
         </wb:load-form>
         <wb:save-form>
  -        /*
  -        var value = widget.getValue();
  -        var node = jxpathPointer.getNode();
  -        var doc = node.getOwnerDocument();
  -        var newNode = 
doc.createElementNS("http://apache.org/cocoon/woody/binding/1.0";, value);
  -        node.appendChild(newNode);
  -        jxpathContext = 
jxpathContext.getRelativeContext(jxpathContext.getPointer(value));
  -        */
         </wb:save-form>
       </wb:javascript>
       <wb:union id="union" path=".">
  @@ -58,32 +53,24 @@
   
     <wb:class id="action-class">
       <wb:case id="action" path=".">
  -      <wb:struct id="action" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:action/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <wb:value id="label" path="wd:action/wb:label" direction="save"/>
  -        <wb:value id="id" path="wd:action/@id" direction="save"/>
  +      <wb:insert-node>
  +        <wd:action/>
  +      </wb:insert-node>
  +      <wb:struct id="action" path="wd:action">
  +        <wb:value id="label" path="wd:label"/>
  +        <wb:value id="id" path="@id"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="aggregatefield-class">
       <wb:case id="aggregatefield" path=".">
  -      <wb:struct id="aggregatefield" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:aggregatefield/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <wb:value id="label" path="wd:aggregatefield/wb:label" 
direction="save"/>
  -        <wb:value id="id" path="wd:aggregatefield/@id" direction="save"/>
  +      <wb:insert-node>
  +        <wd:aggregatefield/>
  +      </wb:insert-node>
  +      <wb:struct id="aggregatefield" path="wd:aggregatefield">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
           <wb:insert-node><wd:widgets/></wb:insert-node>
           <wb:new id="widgets-class"/>
         </wb:struct>
  @@ -92,29 +79,23 @@
   
     <wb:class id="booleanfield-class">
       <wb:case id="booleanfield" path=".">
  -      <wb:struct id="booleanfield" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:booleanfield/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <wb:value id="label" path="wb:booleanfield/wb:label" 
direction="save"/>
  -        <wb:value id="id" path="wb:booleanfield/@id" direction="save"/>
  +      <wb:insert-node>
  +        <wd:booleanfield/>
  +      </wb:insert-node>
  +      <wb:struct id="booleanfield" path="wd:booleanfield">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="class-class">
       <wb:case id="class" path=".">
  -      <wb:struct id="class" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:class/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  +      <wb:insert-node>
  +        <wd:class/>
  +      </wb:insert-node>
  +      <wb:struct id="class" path="wd:class">
  +        <wb:value id="id" path="@id"/>
           <wb:insert-node><wd:widgets/></wb:insert-node>
           <wb:new id="widgets-class"/>
         </wb:struct>
  @@ -123,15 +104,13 @@
   
     <wb:class id="field-class">
       <wb:case id="field" path=".">
  -      <wb:struct id="field" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:field/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <wb:value id="required" path="@required" direction="load">
  +      <wb:insert-node>
  +        <wd:field/>
  +      </wb:insert-node>
  +      <wb:struct id="field" path="wd:field">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
  +        <wb:value id="required" path="@required">
             <wd:convertor datatype="boolean"/>
           </wb:value>
         </wb:struct>
  @@ -140,42 +119,36 @@
   
     <wb:class id="new-class">
       <wb:case id="new" path=".">
  -      <wb:struct id="new" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:new/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  +      <wb:insert-node>
  +        <wd:new/>
  +      </wb:insert-node>
  +      <wb:struct id="new" path="wd:new">
  +        <wb:value id="id" path="@id"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="output-class">
       <wb:case id="output" path=".">
  -      <wb:struct id="output" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:output/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  +      <wb:insert-node>
  +        <wd:output/>
  +      </wb:insert-node>
  +      <wb:struct id="output" path="wd:output">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="repeater-class">
       <wb:case id="repeater" path=".">
  -      <wb:struct id="repeater" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:repeater/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <wb:value id="initial-size" path="@initial-size" direction="load">
  +      <wb:insert-node>
  +        <wd:repeater/>
  +      </wb:insert-node>
  +      <wb:struct id="repeater" path="wd:repeater">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
  +        <wb:value id="initial-size" path="@initial-size">
             <wd:convertor datatype="long"/>
           </wb:value>
           <wb:insert-node><wd:widgets/></wb:insert-node>
  @@ -186,28 +159,24 @@
   
     <wb:class id="row-action-class">
       <wb:case id="row-action" path=".">
  -      <wb:struct id="row-action" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:row-action/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  +      <wb:insert-node>
  +        <wd:row-action/>
  +      </wb:insert-node>
  +      <wb:struct id="row-action" path="wd:row-action">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="struct-class">
       <wb:case id="struct" path=".">
  -      <wb:struct id="struct" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:struct/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  +      <wb:insert-node>
  +        <wd:struct/>
  +      </wb:insert-node>
  +      <wb:struct id="struct" path="wd:struct">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
           <wb:insert-node><wd:widgets/></wb:insert-node>
           <wb:new id="widgets-class"/>
         </wb:struct>
  @@ -215,34 +184,25 @@
     </wb:class>
   
     <wb:class id="submit-class">
  -    <wb:case id="submit" path="/">
  -      <wb:struct id="submit" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:submit/>
  -        </wb:insert-node>
  -        -->
  -        <wb:insert-node>
  -          <wd:submit><wd:label/></wd:submit>
  -        </wb:insert-node>
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <!-- wb:value id="id" path="wd:submit/@id" direction="save"/ -->
  -        <wb:value id="label" path="wd:label" direction="load"/>
  -        <!-- wb:value id="label" path="wd:submit/wd:label" direction="save"/ 
-->
  +    <wb:case id="submit" path=".">
  +      <wb:insert-node>
  +        <wd:submit/>
  +      </wb:insert-node>
  +      <wb:struct id="submit" path="wd:submit">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
         </wb:struct>
       </wb:case>
     </wb:class>
   
     <wb:class id="union-class">
       <wb:case id="union" path=".">
  -      <wb:struct id="union" path=".">
  -        <!--
  -        <wb:insert-node>
  -          <wd:union/>
  -        </wb:insert-node>
  -        -->
  -        <wb:value id="id" path="@id" direction="load"/>
  -        <wb:value id="label" path="wd:label" direction="load"/>
  +      <wb:insert-node>
  +        <wd:union/>
  +      </wb:insert-node>
  +      <wb:struct id="union" path="wd:union">
  +        <wb:value id="id" path="@id"/>
  +        <wb:value id="label" path="wd:label"/>
           <wb:insert-node><wd:widgets/></wb:insert-node>
           <wb:new id="widgets-class"/>
         </wb:struct>
  
  
  

Reply via email to