Author: polx Date: Fri Jan 28 04:36:23 2005 New Revision: 148883 URL: http://svn.apache.org/viewcvs?view=rev&rev=148883 Log: Applying Michael Schuerig's patch. jelly:xml is starting to get a really nifty fully-featured biest! paul
Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java Url: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java?view=diff&rev=148883&p1=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java&r1=148882&p2=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java&r2=148883 ============================================================================== --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java (original) +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/java/org/apache/commons/jelly/tags/xml/SetTag.java Fri Jan 28 04:36:23 2005 @@ -30,6 +30,7 @@ import org.jaxen.JaxenException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Collections; @@ -44,6 +45,12 @@ */ public class SetTag extends XPathTagSupport { + private static final int RETURN_NODE_LIST = 0; + private static final int RETURN_FIRST_NODE = 1; + private static final int RETURN_STRING_LIST = 2; + private static final int RETURN_DELIMITED_STRING_LIST = 3; + private static final int RETURN_FIRST_AS_STRING = 4; + /** The Log to which logging calls will be made. */ private Log log = LogFactory.getLog(SetTag.class); @@ -60,6 +67,8 @@ private Boolean asString = null; + private String delim = null; + public SetTag() { } @@ -86,36 +95,30 @@ catch (JaxenException e) { throw new JellyTagException(e); } - + if (value instanceof List) { // sort the list if xpCmp is set. if (xpCmp != null && (xpCmp.getXpath() != null)) { Collections.sort((List)value, xpCmp); } } - if (single!=null) { - if (single.booleanValue()==true) { - if(value instanceof List) { - List l = (List) value; - if (l.size()==0) - value=null; - else - value=l.get(0); - } - if(asString!=null && asString.booleanValue() && value instanceof Node) - value = ((Node) value).getStringValue(); - } else { // single == false - if(! (value instanceof List) ) { - List l = null; - if (value==null) { - l = new ArrayList(0); - } else { - l = new ArrayList(1); - l.add(value); - } - value = l; - } - } + + switch ( determineReturnType() ) { + case RETURN_NODE_LIST: + value = valueAsList(value); + break; + case RETURN_FIRST_NODE: + value = valueAsSingle(value); + break; + case RETURN_STRING_LIST: + value = nodeListToStringList(valueAsList(value)); + break; + case RETURN_DELIMITED_STRING_LIST: + value = joinDelimitedElements(nodeListToStringList(valueAsList(value))); + break; + case RETURN_FIRST_AS_STRING: + value = singleValueAsString(valueAsSingle(value)); + break; } //log.info( "Evaluated xpath: " + select + " as: " + value + " of type: " + value.getClass().getName() ); @@ -123,6 +126,84 @@ context.setVariable(var, value); } + private List valueAsList( final Object value ) { + if (value instanceof List) { + return (List)value; + } else { + if (value == null) { + return Collections.EMPTY_LIST; + } else { + return Collections.singletonList(value); + } + } + } + + private Object valueAsSingle( final Object value ) { + if (value instanceof List) { + List l = (List) value; + if (l.isEmpty()) + return null; + else + return l.get(0); + } else { + return value; + } + } + + private String singleValueAsString( final Object value ) { + if (value instanceof Node) { + return ((Node) value).getStringValue(); + } else { + return null; + } + } + + private List nodeListToStringList( final List values ) { + List l = new ArrayList(values.size()); + for (Iterator it = values.iterator(); it.hasNext(); ) { + Object v = it.next(); + String s = singleValueAsString(v); + if (s != null) { + l.add(s); + } + } + return l; + } + + private String joinDelimitedElements( final List values ) { + StringBuffer sb = new StringBuffer(); + int sz = values.size(); + for (int i = 0; i < sz; i++) { + String s = (String)values.get(i); + sb.append(s); + if (i < sz - 1) + sb.append(delim); + } + return sb.toString(); + } + + private int determineReturnType() { + int resultType; + if (single != null && single.booleanValue()) { // first node + if (asString != null && asString.booleanValue()) { + resultType = RETURN_FIRST_AS_STRING; + } else { + resultType = RETURN_FIRST_NODE; + } + } else { // all nodes + if (asString != null && asString.booleanValue()) { + if (delim != null) { + resultType = RETURN_DELIMITED_STRING_LIST; + } else { + resultType = RETURN_STRING_LIST; + } + } else { + resultType = RETURN_NODE_LIST; + } + } + return resultType; + } + // Properties //------------------------------------------------------------------------- @@ -138,11 +219,11 @@ } /** If set to true will only take the first element matching. - If set to false, guarantees that a list is returned. It then guarantees that the result is of type [EMAIL PROTECTED] org.dom4j.Node} thereby making sure that, for example, when an element is selected, one can directly call such methods as setAttribute. + If set to false, guarantees that a list is returned. */ public void setSingle(boolean single) { this.single = new Boolean(single); @@ -157,12 +238,15 @@ * attribute to true. */ public void setAsString(boolean asString) { - if(asString) - this.single = new Boolean(asString); this.asString = new Boolean(asString); } - + /** If set, returns a string delimited by this delimiter. + */ + public void setDelim(String delim) { + this.delim = delim; + } + /** Sets the xpath expression to use to sort selected nodes. * Ignored if single is true. */ Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly Url: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly?view=diff&rev=148883&p1=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly&r1=148882&p2=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly&r2=148883 ============================================================================== --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly (original) +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/src/test/org/apache/commons/jelly/tags/xml/suite.jelly Fri Jan 28 04:36:23 2005 @@ -300,11 +300,36 @@ <x:set var="blip" select="$blopElements/root/blip" single="false"/> <j:invokeStatic var="listClass" className="java.lang.Class" method="forName"><j:arg value="java.util.List"/></j:invokeStatic> <test:assert test="${listClass.isAssignableFrom(blip.getClass())}"/> - <!-- check if selecting blop/@id asString returns a string --> - <x:set var="blopId" select="$blopElements/root/blop/@id" asString="true"/> + <!-- check if selecting blop/@id asString and single returns a string --> + <x:set var="blopId" select="$blopElements/root/blop/@id" asString="true" single="true"/> <j:invokeStatic var="stringClass" className="java.lang.Class" method="forName"><j:arg value="java.lang.String"/></j:invokeStatic> <test:assert test="${stringClass.isAssignableFrom(blopId.getClass())}"/> </test:case> + + + <test:case name="testSetStringLists"> + <j:invokeStatic var="listClass" className="java.lang.Class" method="forName"><j:arg value="java.util.List"/></j:invokeStatic> + <j:invokeStatic var="stringClass" className="java.lang.Class" method="forName"><j:arg value="java.lang.String"/></j:invokeStatic> + + <x:parse var="blopElements"> + <root> + <blop>blop1</blop> + <blip/> + <blop id="bla">blop0</blop></root> + </x:parse> + + <!-- check if selecting root/blop asString returns a list of strings --> + <x:set var="blopList" select="$blopElements/root/blop" asString="true" /> + <test:assert test="${listClass.isAssignableFrom(blopList.getClass())}"/> + <test:assert test="${stringClass.isAssignableFrom(blopList.get(0).getClass())}"/> + <test:assertEquals expected="blop1" actual="${blopList.get(0)}"/> + + <!-- check if selecting root/blop asString + delim returns a delimited string --> + <x:set var="blopString" select="$blopElements/root/blop" asString="true" delim=","/> + <test:assert test="${stringClass.isAssignableFrom(blopString.getClass())}"/> + <test:assertEquals expected="blop1,blop0" actual="${blopString}"/> + </test:case> + <test:case name="testEntities"> <x:parse var="doc" xml="entity.xml"/> Modified: jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml Url: http://svn.apache.org/viewcvs/jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml?view=diff&rev=148883&p1=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml&r1=148882&p2=jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml&r2=148883 ============================================================================== --- jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml (original) +++ jakarta/commons/proper/jelly/trunk/jelly-tags/xml/xdocs/changes.xml Fri Jan 28 04:36:23 2005 @@ -24,6 +24,10 @@ <author email="[EMAIL PROTECTED]">dIon Gillard</author> </properties> <body> + <release version="1.1" date="in CVS"> + <action dev="polx" type="add" issue="JELLY-200" due-to="Michael Schuerig" + >xml:set can now return XPath strings and comma-separated strings</action> + </release> <release version="1.0" date="2004-09-11"> <action dev="dion" type="add">Initial release</action> </release> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]