joerg       2004/03/11 19:31:40

  Modified:    src/blocks/forms/samples/forms form2_bind_bean.xml
                        form2_bind_xml.xml
               src/blocks/forms/java/org/apache/cocoon/forms/binding
                        RepeaterJXPathBindingBuilder.java
                        ValueJXPathBinding.java RepeaterJXPathBinding.java
               .        status.xml
  Removed:     src/blocks/forms/java/org/apache/cocoon/forms/binding
                        UniqueFieldJXPathBinding.java
                        UniqueFieldJXPathBindingBuilder.java
  Log:
  issue 17600: syntax update for repeater row identity handling
  
  Revision  Changes    Path
  1.2       +6 -3      
cocoon-2.1/src/blocks/forms/samples/forms/form2_bind_bean.xml
  
  Index: form2_bind_bean.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/forms/samples/forms/form2_bind_bean.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- form2_bind_bean.xml       9 Mar 2004 10:33:48 -0000       1.1
  +++ form2_bind_bean.xml       12 Mar 2004 03:31:39 -0000      1.2
  @@ -48,16 +48,19 @@
   
     <!-- repeater requires unique identification mechanism of the row-nodes -->
     <!-- (it is of course possible to implement other binding strategies) -->
  +  <!-- important note: the row-path is used inside jxpath-createPath context,
  +       as a consequence it cannot have dependent children or predicates -->
     <fb:repeater id="contacts"
       parent-path="."
       row-path="contacts"
       unique-row-id="id"
       unique-path="@id">
   
  -     <!-- compare to xml-binding: the convertor is not needed here -->
  +    <fb:identity>
  +      <!-- compare to xml-binding: the convertor is not needed here -->
  +      <fb:value id="id" path="@id"/>
  +    </fb:identity>
   
  -    <!-- important note: the row-path is used inside jxpath-createPath 
context,
  -    as a consequence it cannot have dependent children or predicates -->
   
       <fb:on-bind>
         <!-- executed on updates AND right after the insert -->
  
  
  
  1.2       +11 -10    
cocoon-2.1/src/blocks/forms/samples/forms/form2_bind_xml.xml
  
  Index: form2_bind_xml.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/forms/samples/forms/form2_bind_xml.xml,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- form2_bind_xml.xml        9 Mar 2004 10:33:48 -0000       1.1
  +++ form2_bind_xml.xml        12 Mar 2004 03:31:39 -0000      1.2
  @@ -69,18 +69,19 @@
     <fb:multi-value id="drinks" parent-path="drinks" row-path="drink"/>
   
     <!-- repeater requires unique identification mechanism of the row-nodes -->
  +  <!-- important note: the row-path is used inside jxpath-createPath context,
  +       as a consequence it cannot have dependent children or predicates -->
     <fb:repeater id="contacts"
       parent-path="contacts"
  -    row-path="contact"
  -    unique-row-id="id"
  -    unique-path="@id"
  -    >
  -    
  -    <!-- optional convertor to use for mapping the unique id -->
  -    <fd:convertor datatype="long" />
  -        
  -    <!-- important note: the row-path is used inside jxpath-createPath 
context,
  -         as a consequence it cannot have dependent children or predicates -->
  +    row-path="contact">
  +
  +    <fb:identity>
  +      <fb:value id="id" path="@id">
  +        <!-- optional convertor to use for mapping the unique id -->
  +        <fd:convertor datatype="long" />
  +      </fb:value>
  +    </fb:identity>
  +
   
       <fb:on-bind>
           <!-- executed on updates AND right after the insert -->
  
  
  
  1.3       +12 -48    
cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBindingBuilder.java
  
  Index: RepeaterJXPathBindingBuilder.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBindingBuilder.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RepeaterJXPathBindingBuilder.java 9 Mar 2004 13:08:46 -0000       1.2
  +++ RepeaterJXPathBindingBuilder.java 12 Mar 2004 03:31:39 -0000      1.3
  @@ -15,12 +15,7 @@
    */
   package org.apache.cocoon.forms.binding;
   
  -import java.util.Locale;
  -
  -import org.apache.cocoon.forms.Constants;
  -import org.apache.cocoon.forms.datatype.convertor.Convertor;
   import org.apache.cocoon.forms.util.DomHelper;
  -import org.apache.cocoon.i18n.I18nUtils;
   import org.w3c.dom.Element;
   
   /**
  @@ -76,30 +71,9 @@
               String rowPath = DomHelper.getAttribute(bindingElm, "row-path");
               String rowPathForInsert =
                   DomHelper.getAttribute(bindingElm, "row-path-insert", 
rowPath);
  -            String uniqueRowId =
  -                DomHelper.getAttribute(bindingElm, "unique-row-id", null);
  -            String uniqueRowIdPath =
  -                DomHelper.getAttribute(bindingElm, "unique-path", null);
  -
  -            Convertor convertor = null;
  -            Locale convertorLocale = Locale.US;
  -            Element convertorEl =
  -                DomHelper.getChildElement(bindingElm,
  -                        Constants.DEFINITION_NS, "convertor");
  -            if (convertorEl != null) {
  -                String datatype =
  -                    DomHelper.getAttribute(convertorEl, "datatype");
  -                String localeStr = convertorEl.getAttribute("datatype");
  -                if (!localeStr.equals("")) {
  -                    convertorLocale = I18nUtils.parseLocale(localeStr);
  -                }
  -                convertor =
  -                    assistant.getDatatypeManager().createConvertor(datatype,
  -                            convertorEl);
  -            }
   
  -            Element childWrapElement = DomHelper.getChildElement(bindingElm,
  -                    BindingManager.NAMESPACE, "on-bind");
  +            Element childWrapElement =
  +                DomHelper.getChildElement(bindingElm, 
BindingManager.NAMESPACE, "on-bind");
               if (childWrapElement == null) {
                   throw new BindingException(
                         "RepeaterBinding misses '<on-bind>' child definition. 
" +
  @@ -123,29 +97,19 @@
                   insertBinding =
                       assistant.makeChildBindings(insertWrapElement)[0];
               }
  -            /* New <wb:unique-row> child element builder */
  -            Element uniqueFieldWrapElement = 
DomHelper.getChildElement(bindingElm,
  -                    BindingManager.NAMESPACE, "unique-row");
  -            JXPathBindingBase[] uniqueFieldBinding = null;
  -            if (uniqueFieldWrapElement != null) {
  -                uniqueFieldBinding = 
assistant.makeChildBindings(uniqueFieldWrapElement);
  -            } else if (uniqueRowId == null || uniqueRowIdPath == null) {
  -                throw new BindingException(
  -                      "RepeaterBinding misses '<unique-row>' child 
definition. " +
  -                      DomHelper.getLocation(bindingElm));
  -            } else {
  -                if (this.getLogger().isInfoEnabled()) {
  -                this.getLogger().info("<wb:repeater>: The attributes 
'unique-row-id' and " +
  -                        "'unique-path' are deprecated. Use <unique-row> 
child element instead." +
  -                        " Located at " + DomHelper.getLocation(bindingElm));
  -                }
  +
  +            Element identityWrapElement = 
DomHelper.getChildElement(bindingElm,
  +                    BindingManager.NAMESPACE, "identity");
  +            JXPathBindingBase[] identityBinding = null;
  +            if (identityWrapElement != null) {
  +                identityBinding =
  +                    assistant.makeChildBindings(identityWrapElement);
               }
   
               RepeaterJXPathBinding repeaterBinding =
                   new RepeaterJXPathBinding(commonAtts, repeaterId, parentPath,
  -                        rowPath, rowPathForInsert, uniqueRowId,
  -                        uniqueRowIdPath, convertor, convertorLocale,
  -                        childBindings, insertBinding, deleteBindings, 
uniqueFieldBinding);
  +                        rowPath, rowPathForInsert, 
  +                        childBindings, insertBinding, deleteBindings, 
identityBinding);
               return repeaterBinding;
           } catch (BindingException e) {
               throw e;
  
  
  
  1.3       +17 -1     
cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/ValueJXPathBinding.java
  
  Index: ValueJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/ValueJXPathBinding.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ValueJXPathBinding.java   11 Mar 2004 02:56:32 -0000      1.2
  +++ ValueJXPathBinding.java   12 Mar 2004 03:31:39 -0000      1.3
  @@ -154,4 +154,20 @@
           super.enableLogging(logger);
           this.updateBinding.enableLogging(logger);
       }
  +
  +    public String getFieldId() {
  +        return this.fieldId;
  +    }
  +
  +    public String getXPath() {
  +        return this.xpath;
  +    }
  +
  +    public Convertor getConvertor() {
  +        return this.convertor;
  +    }
  +
  +    public Locale getConvertorLocale() {
  +        return this.convertorLocale;
  +    }
   }
  
  
  
  1.2       +85 -99    
cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java
  
  Index: RepeaterJXPathBinding.java
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- RepeaterJXPathBinding.java        9 Mar 2004 10:33:55 -0000       1.1
  +++ RepeaterJXPathBinding.java        12 Mar 2004 03:31:39 -0000      1.2
  @@ -19,11 +19,9 @@
   import java.util.HashSet;
   import java.util.Iterator;
   import java.util.List;
  -import java.util.Locale;
   import java.util.Set;
   
   import org.apache.avalon.framework.logger.Logger;
  -import org.apache.cocoon.forms.datatype.convertor.Convertor;
   import org.apache.cocoon.forms.formmodel.Repeater;
   import org.apache.cocoon.forms.formmodel.Widget;
   import org.apache.commons.collections.ListUtils;
  @@ -46,7 +44,7 @@
       private final JXPathBindingBase rowBinding;
       private final JXPathBindingBase insertRowBinding;
       private final JXPathBindingBase deleteRowBinding;
  -    private final List uniqueRowBinding;
  +    private final ComposedJXPathBindingBase identityBinding;
   
       /**
        * Constructs RepeaterJXPathBinding
  @@ -54,56 +52,37 @@
       public RepeaterJXPathBinding(
               JXPathBindingBuilderBase.CommonAttributes commonAtts,
               String repeaterId, String repeaterPath, String rowPath,
  -            String rowPathForInsert, String uniqueRowId,
  -            String uniqueRowPath, JXPathBindingBase[] childBindings,
  -            JXPathBindingBase insertBinding,
  -            JXPathBindingBase[] deleteBindings, JXPathBindingBase[] 
uniqueBindings) {
  -        this(commonAtts, repeaterId, repeaterPath, rowPath, rowPathForInsert,
  -                uniqueRowId, uniqueRowPath, null, null, childBindings,
  -                insertBinding, deleteBindings, uniqueBindings);
  -    }
  -
  -    /**
  -     * Constructs RepeaterJXPathBinding
  -     */
  -    public RepeaterJXPathBinding(
  -            JXPathBindingBuilderBase.CommonAttributes commonAtts,
  -            String repeaterId, String repeaterPath, String rowPath,
  -            String rowPathForInsert, String uniqueRowId,
  -            String uniqueRowPath, Convertor convertor, Locale 
convertorLocale,
  +            String rowPathForInsert,
               JXPathBindingBase[] childBindings, JXPathBindingBase 
insertBinding,
  -            JXPathBindingBase[] deleteBindings, JXPathBindingBase[] 
uniqueBindings) {
  +            JXPathBindingBase[] deleteBindings, JXPathBindingBase[] 
identityBindings) {
           super(commonAtts);
           this.repeaterId = repeaterId;
           this.repeaterPath = repeaterPath;
           this.rowPath = rowPath;
           this.rowPathForInsert = rowPathForInsert;
  +
           this.rowBinding = new ComposedJXPathBindingBase(
  -                JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  -                childBindings);
  +                                  
JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  +                                  childBindings);
           this.rowBinding.setParent(this);
  +
           this.insertRowBinding = insertBinding;
           if (this.insertRowBinding != null) {
               this.insertRowBinding.setParent(this);
           }
  +
           this.deleteRowBinding = new ComposedJXPathBindingBase(
  -                JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  -                deleteBindings);
  +                                        
JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  +                                        deleteBindings);
           if (this.deleteRowBinding != null) {
               this.deleteRowBinding.setParent(this);
           }
  -        // New unique key management
  -        uniqueRowBinding = new ArrayList();
  -        // Create a UniqueFieldJXPathBining for the unique define in 
old-style
  -        if (uniqueRowId != null && uniqueRowPath != null) {
  -            uniqueRowBinding.add(new UniqueFieldJXPathBinding(
  -                JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  -                uniqueRowId, uniqueRowPath, convertor, convertorLocale));
  -        }
  -        if (uniqueBindings != null) {
  -            for (int i=0; i < uniqueBindings.length; i++) {
  -                uniqueRowBinding.add(uniqueBindings[i]);
  -            }
  +
  +        this.identityBinding = new ComposedJXPathBindingBase(
  +                                       
JXPathBindingBuilderBase.CommonAttributes.DEFAULT,
  +                                       identityBindings);
  +        if (this.identityBinding != null) {
  +            this.identityBinding.setParent(this);
           }
       }
   
  @@ -136,10 +115,7 @@
               Pointer jxp = (Pointer)rowPointers.next();
               JXPathContext rowContext = 
repeaterContext.getRelativeContext(jxp);
               // hand it over to children
  -            Iterator iter = this.uniqueRowBinding.iterator();
  -            while (iter.hasNext()) {
  -                
((UniqueFieldJXPathBinding)iter.next()).loadFormFromModel(thisRow, rowContext);
  -            }
  +            this.identityBinding.loadFormFromModel(thisRow, rowContext);
               this.rowBinding.loadFormFromModel(thisRow, rowContext);
           }
           if (getLogger().isDebugEnabled())
  @@ -147,9 +123,9 @@
       }
   
       /**
  -     * Uses the mapped unique-id of each row to detect if rows have been
  +     * Uses the mapped identity of each row to detect if rows have been
        * updated, inserted or removed.  Depending on what happened the 
appropriate
  -     * child-bindings are alowed to visit the narrowed contexts.
  +     * child-bindings are allowed to visit the narrowed contexts.
        */
       public void doSave(Widget frmModel, JXPathContext jxpc)
               throws BindingException {
  @@ -160,7 +136,7 @@
               jxpc.getRelativeContext(jxpc.getPointer(this.repeaterPath));
   
           // create set of updatedRowIds
  -        Set updatedRowIds = new HashSet();
  +        Set updatedRows = new HashSet();
           //create list of rows to insert at end
           List rowsToInsert = new ArrayList();
   
  @@ -169,22 +145,22 @@
           for (int i = 0; i < formRowCount; i++) {
               Repeater.RepeaterRow thisRow = repeater.getRow(i);
   
  -            // Get the key values
  -            List rowIdValues = getUniqueRowValues(thisRow);
  +            // Get the identity
  +            List identity = getIdentity(thisRow);
   
  -            if (isAnyListElementNotNull(rowIdValues)) {
  +            if (hasNonNullElements(identity)) {
                   // iterate nodes to find match
                   Iterator rowPointers = 
repeaterContext.iteratePointers(this.rowPath);
                   boolean found = false;
                   while (rowPointers.hasNext()) {
                       Pointer jxp = (Pointer) rowPointers.next();
                       JXPathContext rowContext = 
repeaterContext.getRelativeContext(jxp);
  -                    List matchIds = getMatchIds(rowContext);
  -                    if (ListUtils.isEqualList(rowIdValues, matchIds)) {
  +                    List contextIdentity = getIdentity(rowContext);
  +                    if (ListUtils.isEqualList(identity, contextIdentity)) {
                           // match! --> bind to children
                           this.rowBinding.saveFormToModel(thisRow, rowContext);
                           //        --> store rowIdValue in list of 
updatedRowIds
  -                        updatedRowIds.add(rowIdValues);
  +                        updatedRows.add(identity);
                           found = true;
                           break;
                       }
  @@ -193,10 +169,10 @@
                       // this is a new row
                       rowsToInsert.add(thisRow);
                       // also add it to the updated row id's so that this row 
doesn't get deleted
  -                    updatedRowIds.add(rowIdValues);
  +                    updatedRows.add(identity);
                   }
               } else {
  -                // if all rowIdValues == null --> this is a new row
  +                // if there is no value to determine the identity --> this 
is a new row
                   rowsToInsert.add(thisRow);
               }
           }
  @@ -206,9 +182,10 @@
           while (rowPointers.hasNext()) {
               Pointer jxp = (Pointer)rowPointers.next();
               JXPathContext rowContext = 
repeaterContext.getRelativeContext((Pointer)jxp.clone());
  -            List matchIds = getMatchIds(rowContext);
  -            // check if matchPath was in list of updates, if not --> bind 
for delete
  -            if (!isListInSet(updatedRowIds, matchIds)) {
  +            List contextIdentity = getIdentity(rowContext);
  +            // check if the identity of the rowContext is in the updated rows
  +            //     if not --> bind for delete
  +            if (!isIdentityInUpdatedRows(updatedRows, contextIdentity)) {
                   rowsToDelete.add(rowContext);
               }
           }
  @@ -260,8 +237,8 @@
                   }
               } else {
                   if (getLogger().isWarnEnabled()) {
  -                    getLogger().warn("RepeaterBinding has detected rows to 
insert, but misses " +
  -                            "the <on-insert-row> binding to do it.");
  +                    getLogger().warn("RepeaterBinding has detected rows to 
insert, but misses "
  +                                     + "the <on-insert-row> binding to do 
it.");
                   }
               }
           }
  @@ -271,16 +248,16 @@
       }
   
       /**
  -     * Tests if a List is already contained in a Set of Lists.
  -     * @param set the Set of Lists.
  -     * @param list the list that is tested if it is already in the Set.
  -     * @return true if the Set contains the List, false otherwise.
  +     * Tests if an identity is already contained in a Set of identities.
  +     * @param identitySet the Set of identities.
  +     * @param identity the identity that is tested if it is already in the 
Set.
  +     * @return true if the Set contains the identity, false otherwise.
        */
  -    private boolean isListInSet(Set set, List list) {
  -        Iterator iter = set.iterator();
  +    private boolean isIdentityInUpdatedRows(Set identitySet, List identity) {
  +        Iterator iter = identitySet.iterator();
           while (iter.hasNext()) {
  -            List listFromSet = (List)iter.next();
  -            if (ListUtils.isEqualList(listFromSet, list)) {
  +            List identityFromSet = (List)iter.next();
  +            if (ListUtils.isEqualList(identityFromSet, identity)) {
                   return true;
               }
           }
  @@ -292,7 +269,7 @@
        * @param list
        * @return
        */
  -    private boolean isAnyListElementNotNull(List list) {
  +    private boolean hasNonNullElements(List list) {
           Iterator iter = list.iterator();
           while (iter.hasNext()) {
               if (iter.next() != null) {
  @@ -303,47 +280,57 @@
       }
   
       /**
  -     * 
  +     * Get the identity of the given row context. That's infact a list of all
  +     * the values of the fields in the bean or XML that constitute the 
identity. 
        * @param rowContext
  -     * @return
  +     * @return List the identity of the row context
        */
  -    private List getMatchIds(JXPathContext rowContext) {
  -        List matchIds = new ArrayList();
  -        Iterator iter = this.uniqueRowBinding.iterator();
  -        while (iter.hasNext()) {
  -            UniqueFieldJXPathBinding key = 
(UniqueFieldJXPathBinding)iter.next();
  -            Object matchId = rowContext.getValue(key.getXpath());
  -            if (matchId != null && key.getConvertor() != null) {
  -                if (matchId instanceof String) {
  -                    matchId = key.getConvertor().convertFromString(
  -                            (String)matchId, key.getConvertorLocale(), null);
  -                } else {
  -                    if (getLogger().isWarnEnabled()) {
  -                        getLogger().warn("Convertor ignored on backend-value 
" +
  -                                "which isn't of type String.");
  +    private List getIdentity(JXPathContext rowContext) {
  +        List identity = new ArrayList();
  +
  +        JXPathBindingBase[] childBindings = 
this.identityBinding.getChildBindings();
  +        if (childBindings != null) {
  +            int size = childBindings.length;
  +            for (int i = 0; i < size; i++) {
  +                ValueJXPathBinding vBinding = 
(ValueJXPathBinding)childBindings[i];
  +                Object value = rowContext.getValue(vBinding.getXPath());
  +                if (value != null && vBinding.getConvertor() != null) {
  +                    if (value instanceof String) {
  +                        value = vBinding.getConvertor().convertFromString(
  +                                (String)value, 
vBinding.getConvertorLocale(), null);
  +                    } else {
  +                        if (getLogger().isWarnEnabled()) {
  +                            getLogger().warn("Convertor ignored on 
backend-value " +
  +                                    "which isn't of type String.");
  +                        }
                       }
                   }
  +                identity.add(value);
               }   
  -            matchIds.add(matchId);
           }
  -        return matchIds;
  +        return identity;
       }
   
       /**
  -     * Get the values of the unique-fields of the given row in the formModel 
  +     * Get the identity of the given row. That's infact a list of all the 
values
  +     * of the fields in the form model that constitute the identity. 
        * @param thisRow
  -     * @return List
  +     * @return List the identity of the row
        */
  -    private List getUniqueRowValues(Repeater.RepeaterRow thisRow) {
  -        List values = new ArrayList();
  -        Iterator iter = this.uniqueRowBinding.iterator();
  -        while (iter.hasNext()) {
  -            UniqueFieldJXPathBinding key = 
(UniqueFieldJXPathBinding)iter.next();
  -            Widget rowIdWidget = thisRow.getWidget(key.getFieldId());
  -            Object rowIdValue = rowIdWidget.getValue();
  -            values.add(rowIdValue);
  +    private List getIdentity(Repeater.RepeaterRow row) {
  +        List identity = new ArrayList();
  +
  +        JXPathBindingBase[] childBindings = 
this.identityBinding.getChildBindings();
  +        if (childBindings != null) {
  +            int size = childBindings.length;
  +            for (int i = 0; i < size; i++) {
  +                String fieldId = 
((ValueJXPathBinding)childBindings[i]).getFieldId();
  +                Widget widget = row.getWidget(fieldId);
  +                Object value = widget.getValue();
  +                identity.add(value);
  +            }
           }
  -        return values;
  +        return identity;
       }
   
       public String toString() {
  @@ -360,9 +347,8 @@
               this.insertRowBinding.enableLogging(logger);
           }
           this.rowBinding.enableLogging(logger);
  -        Iterator iter = this.uniqueRowBinding.iterator();
  -        while (iter.hasNext()) {
  -            ((UniqueFieldJXPathBinding)iter.next()).enableLogging(logger);
  +        if (this.identityBinding != null) {
  +            this.identityBinding.enableLogging(logger);
           }
       }
   }
  
  
  
  1.275     +15 -9     cocoon-2.1/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/status.xml,v
  retrieving revision 1.274
  retrieving revision 1.275
  diff -u -r1.274 -r1.275
  --- status.xml        11 Mar 2004 14:21:56 -0000      1.274
  +++ status.xml        12 Mar 2004 03:31:40 -0000      1.275
  @@ -28,7 +28,13 @@
   <!ATTLIST actions
        priority (high | medium | low) #REQUIRED
   >
  -<!ELEMENT action (#PCDATA | link | br | code)*>
  +<!ELEMENT changes (release+)>
  +<!ELEMENT release (action+)>
  +<!ATTLIST release
  +     version CDATA #REQUIRED
  +     date CDATA #REQUIRED
  +>
  +<!ELEMENT action (#PCDATA | link | br | code | ul)*>
   <!ATTLIST action
        context (build | code | docs) #IMPLIED
        assigned-to CDATA #IMPLIED
  @@ -38,18 +44,14 @@
        due-to CDATA #IMPLIED
        due-to-email CDATA #IMPLIED
   >
  -<!ELEMENT changes (release+)>
   <!ELEMENT code (#PCDATA)>
   <!ELEMENT br EMPTY>
   <!ELEMENT link (#PCDATA)>
   <!ATTLIST link
        href CDATA #REQUIRED
   >
  -<!ELEMENT release (action+)>
  -<!ATTLIST release
  -     version CDATA #REQUIRED
  -     date CDATA #REQUIRED
  ->
  +<!ELEMENT ul (li)+>
  +<!ELEMENT li (#PCDATA | link | br | code | ul)*>
   <!ENTITY eacute           "&#x000E9;">
   <!ENTITY ouml             "&#x000F6;">
   <!ENTITY uuml             "&#x000FC;">
  @@ -210,6 +212,9 @@
     <changes>
   
    <release version="@version@" date="@date@">
  +   <action dev="JH" type="update" fixes-bug="27600">
  +     CForms: Change the syntax for repeater row identity handling.
  +   </action>
      <action dev="CZ" type="update">
        An internal redirect is now handled the same way as an external 
redirect would be handled.
        This includes that the error handler of the called pipeline is invoked 
in case of an error.
  @@ -253,7 +258,8 @@
                      to   
xmlns:fi="http://apache.org/cocoon/forms/1.0#instance";</li>
                  <li>from 
xmlns:wt="http://apache.org/cocoon/woody/template/1.0";
                      to   
xmlns:ft="http://apache.org/cocoon/forms/1.0#template";</li>
  -           </ul></li>
  +           </ul>
  +       </li>
          <li>Java packages moved from org.apache.cocoon.woody to 
org.apache.cocoon.forms</li>
        </ul>
      </action> 
  
  
  

Reply via email to