jstrachan    2002/11/27 11:22:42

  Modified:    jelly/src/java/org/apache/commons/jelly/tags/xml SetTag.java
                        XPathComparator.java SortTag.java ForEachTag.java
               jelly/src/test/org/apache/commons/jelly/xml suite.jelly
  Log:
  Patch to Jason's XPath sorting implementation that uses XPaths numerical functions 
instead of taking a Java Class to perform conversions.
  
  So to sort by the foo attribute you could use
  
  @foo
  
  for textual sorting or for numeric sorting...
  
  number(@foo)
  
  Revision  Changes    Path
  1.11      +5 -15     
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/SetTag.java
  
  Index: SetTag.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/SetTag.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- SetTag.java       27 Nov 2002 17:21:16 -0000      1.10
  +++ SetTag.java       27 Nov 2002 19:22:41 -0000      1.11
  @@ -150,14 +150,4 @@
           if (xpCmp == null) xpCmp = new XPathComparator();
           xpCmp.setDescending(descending);
       }
  -
  -    /**
  -     * Set the data type to convert nodes being sorted on into before sorting.
  -     * This should be the name of a class that commons.beanutils knows how to 
convert strings
  -     * into.
  -     */
  -    public void setSortDataType(String sortType) throws ClassNotFoundException {
  -        if (xpCmp == null) xpCmp = new XPathComparator();
  -        xpCmp.setType(Class.forName(sortType));
  -    }
   }
  
  
  
  1.2       +23 -67    
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/XPathComparator.java
  
  Index: XPathComparator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/XPathComparator.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XPathComparator.java      27 Nov 2002 17:21:16 -0000      1.1
  +++ XPathComparator.java      27 Nov 2002 19:22:41 -0000      1.2
  @@ -62,6 +62,7 @@
   package org.apache.commons.jelly.tags.xml;
   
   import java.util.Comparator;
  +import java.util.List;
   
   import org.dom4j.Node;
   
  @@ -85,9 +86,6 @@
       /** The xpath to use to extract value from nodes to compare */
       private XPath xpath = null;
   
  -    /** If set then the value extracted will be cast into this type and compared. */
  -    private Class type = null;
  -
       /** Sort descending or ascending */
       private boolean descending = false;
   
  @@ -100,12 +98,6 @@
           this.descending = descending;
       }
   
  -    public XPathComparator(XPath xpath, Class type, boolean descending) {
  -        this.xpath = xpath;
  -        this.type = type;
  -        this.descending = descending;
  -    }
  -
       public void setXpath(XPath xpath) {
           this.xpath = xpath;
       }
  @@ -114,10 +106,6 @@
           return xpath;
       }
   
  -    public void setType(Class type) {
  -        this.type = type;
  -    }
  -
       public void setDescending(boolean descending) {
           this.descending = descending;
       }
  @@ -131,43 +119,16 @@
   
               // apply the xpaths. not using stringValueOf since I don't
               // want all of the child nodes appended to the strings
  -            Node val1 = (Node)xpath.selectSingleNode(n1);
  -            Node val2 = (Node)xpath.selectSingleNode(n2);
  +            Object val1 = xpath.evaluate(n1);
  +            Object val2 = xpath.evaluate(n2);
   
               // return if null
               if (val1 == null || val2 == null) {
                   return val1 == null ? (val2 == null ? 1 : -1) : 1;
               }
   
  -            // these are what will be compared
  -            Comparable c1, c2;
  -
  -            // extract the string values
  -            String s1 = val1.getText();
  -            String s2 = val2.getText();
  -
  -            // if type is set convert to it and compare
  -            // if it is not set try to infer types
  -            if (type != null) {
  -                c1 = (Comparable)ConvertUtils.convert(s1, type);
  -                c2 = (Comparable)ConvertUtils.convert(s2, type);
  -            } else {
  -                // check if numeric type
  -                if (isNumeric(s1) && isNumeric(s2)) {
  -                    // if either is a double, cast to doubles
  -                    if (isDouble(s1) || isDouble(s2)) {
  -                        c1 = (Double)ConvertUtils.convert(s1, Double.class);
  -                        c2 = (Double)ConvertUtils.convert(s2, Double.class);
  -                    } else {
  -                        c1 = (Integer)ConvertUtils.convert(s1, Integer.class);
  -                        c2 = (Integer)ConvertUtils.convert(s2, Integer.class);
  -                    }
  -                } else {
  -                    // nope, leave as strings
  -                    c1 = s1;
  -                    c2 = s2;
  -                }
  -            }
  +            Comparable c1 = getComparableValue(val1);
  +            Comparable c2 = getComparableValue(val2);
   
               // compare descending or ascending
               if (!descending) {
  @@ -184,32 +145,27 @@
       }
   
       /**
  -     * Check to see if a string is a number. Negative and decimals supported.
  -     * @param str String to check
  -     * @return True if the string is numeric. Empty strings are not numeric.
  +     * Turns the XPath result value into a Comparable object.
        */
  -    private static final boolean isNumeric(String str) {
  -        final int strLen = str.length();
  -        // empty strings are not numbers
  -        if (strLen == 0) return false;
  -        // start at pos 1 if the 1st char is '-' to support negatives
  -        final int startPos = (str.charAt(0) == '-') ? 1 : 0;
  -        if (startPos == strLen) return false;
  -        for (int i=startPos;i<strLen;i++) {
  -            char ch = str.charAt(i);
  -            if ((ch < '0' || ch > '9') && (ch != '.')) {
  -                return false;
  +    protected Comparable getComparableValue(Object value) {
  +        if (value instanceof List) {
  +            List list = (List) value;
  +            if (list.isEmpty()) {
  +                value = "";
  +            }
  +            value = list.get(0);
  +            if (value == null) {
  +                value = "";
               }
           }
  -
  -        return true;
  -    }
  -
  -    /**
  -     * Check to see if the number has a period.
  -     */
  -    private static final boolean isDouble(String str) {
  -        return str.indexOf(".") != -1;
  +        if (value instanceof Comparable) {
  +            return (Comparable) value;
  +        }
  +        else if (value instanceof Node) {
  +            Node node = (Node) value;
  +            return node.getStringValue();
  +        }
  +        return value.toString();
       }
   
       /**
  
  
  
  1.2       +0 -10     
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/SortTag.java
  
  Index: SortTag.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/SortTag.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SortTag.java      27 Nov 2002 17:21:16 -0000      1.1
  +++ SortTag.java      27 Nov 2002 19:22:41 -0000      1.2
  @@ -114,14 +114,4 @@
           if (xpCmp == null) xpCmp = new XPathComparator();
           xpCmp.setDescending(descending);
       }
  -
  -    /**
  -     * Set the data type to convert nodes being sorted on into before sorting. This
  -     * should be the name of a class that commons.beanutils knows how to convert 
strings
  -     * into.
  -     */
  -    public void setSortDataType(String sortType) throws ClassNotFoundException {
  -        if (xpCmp == null) xpCmp = new XPathComparator();
  -        xpCmp.setType(Class.forName(sortType));
  -    }
   }
  
  
  
  1.12      +5 -15     
jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/ForEachTag.java
  
  Index: ForEachTag.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/xml/ForEachTag.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- ForEachTag.java   27 Nov 2002 17:21:16 -0000      1.11
  +++ ForEachTag.java   27 Nov 2002 19:22:41 -0000      1.12
  @@ -155,14 +155,4 @@
           if (xpCmp == null) xpCmp = new XPathComparator();
           xpCmp.setDescending(descending);
       }
  -
  -    /**
  -     * Set the data type to convert nodes being sorted on into before sorting. This
  -     * should be the name of a class that commons.beanutils knows how to convert 
strings
  -     * into.
  -     */
  -    public void setSortDataType(String sortType) throws ClassNotFoundException {
  -        if (xpCmp == null) xpCmp = new XPathComparator();
  -        xpCmp.setType(Class.forName(sortType));
  -    }
   }
  
  
  
  1.5       +16 -14    
jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/suite.jelly
  
  Index: suite.jelly
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons-sandbox/jelly/src/test/org/apache/commons/jelly/xml/suite.jelly,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- suite.jelly       27 Nov 2002 17:21:16 -0000      1.4
  +++ suite.jelly       27 Nov 2002 19:22:42 -0000      1.5
  @@ -28,13 +28,15 @@
     </test:case>
     
     <test:case name="testBadElementAndAttribute">
  -     
  -    <j:catch var="ex">
  -             <x:element name="foo">
  -                     some text
  -                     <x:attribute name="x">1234</x:attribute>
  -             </x:element>
  -             </j:catch>      
  +
  +             <log:info>
  +                     <j:catch var="ex">
  +                             <x:element name="foo">
  +                                     some text
  +                                     <x:attribute name="x">1234</x:attribute>
  +                             </x:element>
  +                     </j:catch>      
  +             </log:info>     
                
                <test:assert test="${ex != null}">
                        We should have created an exception as some text is output 
before the attributes
  @@ -59,7 +61,7 @@
                
                <test:assert test="${ex != null}">We should have created an 
exception</test:assert>
                
  -             The exception was: ${ex.message}
  +             <log:info>The exception was: ${ex.message}</log:info>
     </test:case>
   
        <!-- test the use of namespaces with XPath -->
  @@ -118,7 +120,7 @@
   
           <!-- test ascending -->
           <j:set var="result" value=""/>
  -        <x:forEach select="$nums/a/b" var="x" sort="@v">
  +        <x:forEach select="$nums/a/b" var="x" sort="number(@v)">
               <x:set var="num" select="$x/@v"/>
               <j:set var="result" value="${result} ${num.get(0).getText()}"/>
           </x:forEach>
  @@ -127,7 +129,7 @@
   
           <!-- test descending -->
           <j:set var="result" value=""/>
  -        <x:forEach select="$nums/a/b" var="x" sort="@v" descending="true">
  +        <x:forEach select="$nums/a/b" var="x" sort="number(@v)" descending="true">
               <x:set var="num" select="$x/@v"/>
               <j:set var="result" value="${result} ${num.get(0).getText()}"/>
           </x:forEach>
  @@ -136,7 +138,7 @@
   
           <!-- test deeper nesting -->
           <j:set var="result" value=""/>
  -        <x:forEach select="$deeper/a/b" var="x" sort="c/d">
  +        <x:forEach select="$deeper/a/b" var="x" sort="number(c/d/text())">
               <j:set var="result" value="${result} ${x.getStringValue()}"/>
           </x:forEach>
   
  @@ -144,7 +146,7 @@
   
           <!-- test sort as strings -->
           <j:set var="result" value=""/>
  -        <x:forEach select="$nums/a/b" var="x" sort="@v" 
sortDataType="java.lang.String">
  +        <x:forEach select="$nums/a/b" var="x" sort="@v">
               <x:set var="num" select="$x/@v"/>
               <j:set var="result" value="${result} ${num.get(0).getText()}"/>
           </x:forEach>
  @@ -153,7 +155,7 @@
   
           <!-- test x:set with sort -->
           <j:set var="result" value=""/>
  -        <x:set var="rset" select="$nums/a/b" sort="@v"/>
  +        <x:set var="rset" select="$nums/a/b" sort="number(@v)"/>
           <j:forEach var="num" items="${rset.iterator()}">
               <j:set var="result" value="${result} ${num.attributeValue('v')}"/>
           </j:forEach>
  @@ -163,7 +165,7 @@
           <!-- test x:set with sort -->
           <j:set var="result" value=""/>
           <x:set var="rset" select="$nums/a/b"/>
  -        <x:sort list="${rset}" sort="@v"/>
  +        <x:sort list="${rset}" sort="number(@v)"/>
           <j:forEach var="num" items="${rset.iterator()}">
               <j:set var="result" value="${result} ${num.attributeValue('v')}"/>
           </j:forEach>
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to