Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpelder2009-03-09 11:29:35 -0400
committerpelder2009-03-09 11:29:35 -0400
commite205df27c429e06e051423649658d1d00aa9b744 (patch)
tree406ee8142d541f9847060212129d16f980afd97c
parenteaad1b4c4a50baa9119054a2d213172caa719b12 (diff)
downloadorg.eclipse.jet-e205df27c429e06e051423649658d1d00aa9b744.tar.gz
org.eclipse.jet-e205df27c429e06e051423649658d1d00aa9b744.tar.xz
org.eclipse.jet-e205df27c429e06e051423649658d1d00aa9b744.zip
[267644] Enable more extensive use of relative Xpath expressions
-rw-r--r--doc/org.eclipse.jet.doc/references/taglibs/controlTags/iterateTag.html12
-rw-r--r--doc/org.eclipse.jet.doc/references/taglibs/controlTags/overview.html7
-rw-r--r--doc/org.eclipse.jet.doc/references/taglibs/controlTags/withTag.html86
-rw-r--r--doc/org.eclipse.jet.doc/toccontrolTags.xml1
-rw-r--r--plugins/org.eclipse.jet/plugin.xml35
-rw-r--r--plugins/org.eclipse.jet/src/org/eclipse/jet/XPathContextExtender.java151
-rw-r--r--plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/IterateTag.java87
-rw-r--r--plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/TagFactory.java5
-rw-r--r--plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/WithTag.java77
-rw-r--r--plugins/org.eclipse.jet/transforms/plugins/org.eclipse.jet.transforms.newproject_1.0.0.jarbin37537 -> 37842 bytes
-rw-r--r--transforms/org.eclipse.jet.transforms.newproject/templates/project/control.jet.jet7
11 files changed, 439 insertions, 29 deletions
diff --git a/doc/org.eclipse.jet.doc/references/taglibs/controlTags/iterateTag.html b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/iterateTag.html
index b1e1f68..bf3cb8d 100644
--- a/doc/org.eclipse.jet.doc/references/taglibs/controlTags/iterateTag.html
+++ b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/iterateTag.html
@@ -18,7 +18,7 @@
</TABLE>
<HR>
<P><B>iterate</B></P>
-<P><P> Write the tag contents for each in the template input model identified by an XPath expression.<P><P>If the &apos;select&apos; XPath expression selects no objects, then the contents of the tag are not processed. If the XPath expression is not well-formed, then an error results.<P><P>If the 'select' XPath expression returns a number, then the body of the loop is processed that number of times, and the variable named by 'var' is set to 1 for the first iteration, and incremented by one for each successive iteration.<P><P>If there is a variable in scope with the same name as the value &apos;var&apos; attribute, then it is hidden during the execution of this tag.<P> </P>
+<P><P> Write the tag contents for each in the template input model identified by an XPath expression.<P><P>If the &apos;select&apos; XPath expression selects no objects, then the contents of the tag are not processed. If the XPath expression is not well-formed, then an error results.<P><P>If the 'select' XPath expression returns a number, then the body of the loop is processed that number of times, and the variable named by 'var' is set to 1 for the first iteration, and incremented by one for each successive iteration.<P><P>If there is a variable in scope with the same name as the value &apos;var&apos; attribute, then it is hidden during the execution of this tag.<P><P>If the JET variable org.eclipse.jet.taglib.control.iterateSetsContext is set and evaluates to a boolean value of true, the iterate tag will set the XPath default context object to the current object in the iteration. Using this feature allows nested XPath expressions to be relative to that object (making them shorter).<P> </P>
<HR>
<TABLE border="1" width="100%">
<TBODY>
@@ -27,7 +27,7 @@
<TR>
<TD width="10%">required</TD>
<TD><SPAN style="font-family: monospace">
- &lt;c:iterate select=&quot;<I>value</I>&quot; var=&quot;<I>value</I>&quot;&gt;<br>
+ &lt;c:iterate select=&quot;<I>value</I>&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;<I>content to be repeated for each iteration</I><BR>
&lt;/c:iterate&gt;
</SPAN></TD>
@@ -51,10 +51,6 @@
<TD width="10%">select</TD>
<TD><BR> An XPath expression that returns either a node set (a collection of elements or attributes) or a number.<BR> </TD>
</TR>
- <TR>
- <TD width="10%">var</TD>
- <TD><BR> A variable name. During each iteration, the value of the variable is an object from the set of objects selected by the 'select' XPath expression.<BR> </TD>
- </TR>
</TBODY>
</TABLE>
<HR>
@@ -64,6 +60,10 @@
<TH colspan="2" align="left">Optional Attributes</TH></TR>
<TR>
<TR>
+ <TD width="10%">var</TD>
+ <TD><BR> A variable name. During each iteration, the value of the variable is an object from the set of objects selected by the 'select' XPath expression.<BR> </TD>
+ </TR>
+ <TR>
<TD width="10%">delimiter</TD>
<TD><BR> A string that is written to the tag's output between iteration of the tag. The text is not written after the last iteration.<BR> </TD>
</TR>
diff --git a/doc/org.eclipse.jet.doc/references/taglibs/controlTags/overview.html b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/overview.html
index 2b15aa8..6ac57cf 100644
--- a/doc/org.eclipse.jet.doc/references/taglibs/controlTags/overview.html
+++ b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/overview.html
@@ -213,6 +213,13 @@
<!-- End when description -->
</TD>
</TR>
+ <TR>
+ <TD width="10%"><A href="withTag.html">&lt;c:with&gt;</A></TD>
+ <TD><!-- Begin with description -->
+ <P> Evaluate the tag body with the XPath context set to the result of the'select' XPath expression
+ <!-- End with description -->
+ </TD>
+ </TR>
</TBODY>
</TABLE>
<HR>
diff --git a/doc/org.eclipse.jet.doc/references/taglibs/controlTags/withTag.html b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/withTag.html
new file mode 100644
index 0000000..2adea59
--- /dev/null
+++ b/doc/org.eclipse.jet.doc/references/taglibs/controlTags/withTag.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML>
+<HEAD>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<META name="GENERATOR" content="IBM Software Development Platform">
+<link rel="STYLESHEET" href="../../../book.css" charset="ISO-8859-1" type="text/css"/>
+<TITLE>&lt;c:with&gt; - Standard JET2 Control Tags</TITLE>
+</HEAD>
+<BODY>
+<TABLE border="0" cellpadding="0" cellspacing="1" width="100%">
+ <TBODY>
+ <TR>
+ <TH align="left">
+ <P>&lt;c:with&gt;</P></TH>
+ <TH align="right"><A href="overview.html">Standard JET2 Control Tags</A></TH>
+ </TR>
+ </TBODY>
+</TABLE>
+<HR>
+<P><B>with</B></P>
+<P><P> Evaluate the tag body with the XPath context set to the result of the'select' XPath expression. The XPath context is restored to its previous value once the tag handler completes.<P><P>If the XPath expression selects multiple objects, the first object is used.<P><P>If the XPath expression selects no objects, then an error occurs and the block is executed with the current context object.<P><P>Optionally, an XPath variable may be set by providing a 'var' attribute. The variable is restored to its previous value or removed if not previously set once the tag handler completes.<P> </P>
+<HR>
+<TABLE border="1" width="100%">
+ <TBODY>
+ <TR>
+ <TH colspan="2" align="left">Tag Summary</TH></TR>
+ <TR>
+ <TD width="10%">required</TD>
+ <TD><SPAN style="font-family: monospace">
+ &lt;c:with select=&quot;<I>value</I>&quot;&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;<I>content to be written</I><BR>
+ &lt;/c:with&gt;
+ </SPAN></TD>
+ </TR>
+ <TR>
+ <TD width="10%">full tag</TD>
+ <TD><SPAN style="font-family: monospace">
+ &lt;c:with select=&quot;<I>value</I>&quot; var=&quot;<I>value</I>&quot;&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;<I>content to be written</I><BR>
+ &lt;/c:with&gt;
+ </SPAN></TD>
+ </TR>
+ </TBODY>
+</TABLE>
+<HR>
+<TABLE border="1" width="100%">
+ <TBODY>
+ <TR>
+ <TH colspan="2" align="left">Required Attributes</TH></TR>
+ <TR>
+ <TD width="10%">select</TD>
+ <TD><BR> An XPath expression that is evaluated to a single object.<BR> </TD>
+ </TR>
+ </TBODY>
+</TABLE>
+<HR>
+<TABLE border="1" width="100%">
+ <TBODY>
+ <TR>
+ <TH colspan="2" align="left">Optional Attributes</TH></TR>
+ <TR>
+ <TR>
+ <TD width="10%">var</TD>
+ <TD><BR> An optional XPath variable name that will contain the result of the XPath expression.<BR> </TD>
+ </TR>
+ </TBODY>
+</TABLE>
+<HR>
+<TABLE border="1" width="100%">
+ <TBODY>
+ <TR>
+ <TH colspan="2" align="left">Example</TH></TR>
+ <TR>
+ <TD width="10%"></TD>
+ <TD><SPAN style="font-family: monospace">
+<!-- Begin with example -->
+ &lt;c:with select=&quot;<I>value</I>&quot;&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;<I>content to be written</I><BR>
+ &lt;/c:with&gt;
+<!-- End with example -->
+</SPAN></TD>
+ </TR>
+ </TBODY>
+</TABLE>
+<P></P></BODY>
+</HTML>
diff --git a/doc/org.eclipse.jet.doc/toccontrolTags.xml b/doc/org.eclipse.jet.doc/toccontrolTags.xml
index 71a66e2..b10711f 100644
--- a/doc/org.eclipse.jet.doc/toccontrolTags.xml
+++ b/doc/org.eclipse.jet.doc/toccontrolTags.xml
@@ -30,5 +30,6 @@
<topic label="c:visit" href="references/taglibs/controlTags/visitTag.html"/>
<topic label="c:visitor" href="references/taglibs/controlTags/visitorTag.html"/>
<topic label="c:when" href="references/taglibs/controlTags/whenTag.html"/>
+ <topic label="c:with" href="references/taglibs/controlTags/withTag.html"/>
</topic>
</toc>
diff --git a/plugins/org.eclipse.jet/plugin.xml b/plugins/org.eclipse.jet/plugin.xml
index ba1673e..973ef2d 100644
--- a/plugins/org.eclipse.jet/plugin.xml
+++ b/plugins/org.eclipse.jet/plugin.xml
@@ -277,7 +277,7 @@ The &apos;restoreNames&apos; and &apos;passVariables&apos; options are mutually
<attribute
name="var"
type="string"
- use="required">
+ use="optional">
<description>
A variable name. During each iteration, the value of the variable is an object from the set of objects selected by the &apos;select&apos; XPath expression.
</description>
@@ -290,6 +290,8 @@ If the &amp;apos;select&amp;apos; XPath expression selects no objects, then the
If the &apos;select&apos; XPath expression returns a number, then the body of the loop is processed that number of times, and the variable named by &apos;var&apos; is set to 1 for the first iteration, and incremented by one for each successive iteration.
If there is a variable in scope with the same name as the value &amp;apos;var&amp;apos; attribute, then it is hidden during the execution of this tag.
+
+If the JET variable org.eclipse.jet.taglib.control.iterateSetsContext is set and evaluates to a boolean value of true, the iterate tag will set the XPath default context object to the current object in the iteration. Using this feature allows nested XPath expressions to be relative to that object (making them shorter).
</description>
<attribute
name="delimiter"
@@ -551,6 +553,37 @@ If this tag is not directly contained by a 'choose' tag, then an error results.
</description>
</attribute>
</conditionalTag>
+ <containerTag
+ class="org.eclipse.jet.internal.taglib.control.WithTag"
+ name="with"
+ processContents="standard"
+ whenContainingLineIsEmpty="remove">
+ <description>
+ Evaluate the tag body with the XPath context set to the result of the&apos;select&apos; XPath expression. The XPath context is restored to its previous value once the tag handler completes.
+
+If the XPath expression selects multiple objects, the first object is used.
+
+If the XPath expression selects no objects, then an error occurs and the block is executed with the current context object.
+
+Optionally, an XPath variable may be set by providing a &apos;var&apos; attribute. The variable is restored to its previous value or removed if not previously set once the tag handler completes.
+ </description>
+ <attribute
+ name="select"
+ type="xpath"
+ use="required">
+ <description>
+ An XPath expression that is evaluated to a single object.
+ </description>
+ </attribute>
+ <attribute
+ name="var"
+ type="string"
+ use="optional">
+ <description>
+ An optional XPath variable name that will contain the result of the XPath expression.
+ </description>
+ </attribute>
+ </containerTag>
diff --git a/plugins/org.eclipse.jet/src/org/eclipse/jet/XPathContextExtender.java b/plugins/org.eclipse.jet/src/org/eclipse/jet/XPathContextExtender.java
index 0ddee32..8c8f552 100644
--- a/plugins/org.eclipse.jet/src/org/eclipse/jet/XPathContextExtender.java
+++ b/plugins/org.eclipse.jet/src/org/eclipse/jet/XPathContextExtender.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,8 +18,10 @@ package org.eclipse.jet;
import java.text.MessageFormat;
+import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Map;
+import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -75,6 +77,8 @@ public final class XPathContextExtender implements XPathVariableResolver
public DefaultXPathFunctionResolver customFunctionResolver = null;
public final Map knownXPathExpressions = new HashMap();
+
+ public final Stack contextObjectStack = new Stack();
}
/**
@@ -128,6 +132,9 @@ public final class XPathContextExtender implements XPathVariableResolver
return contextData;
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jet.xpath.XPathVariableResolver#resolveVariable(java.lang.String)
+ */
public Object resolveVariable(String name)
{
try
@@ -167,7 +174,33 @@ public final class XPathContextExtender implements XPathVariableResolver
}
return result;
}
+
+ /**
+ * Resolve the given XPath expression as a string value. Note that if the XPath expression
+ * returns an empty Node set, this method returns <code>null</code>. This is a convenience implementation of:
+ * <pre>
+ * resolveAsString(currentXPathContextObject(), selectXPath)
+ * </pre>
+ * @param selectXPath the XPath expression
+ * @return the string value of the XPath expression, or <code>null</code> if the expression resulted in an empty node set.
+ * @throws JET2TagException if an error occurs during expression evaluation
+ * @see #resolveAsString(Object, String)
+ * @since 1.0
+ */
+ public String resolveAsString(String selectXPath) throws JET2TagException
+ {
+ return resolveAsString(currentXPathContextObject(), selectXPath);
+ }
+ /**
+ * Resolve an XPath expression to a single object. If the Xpath expression returns a collection, then
+ * return the first element in the collection, or <code>null</code> if that colleciton is empty. Otherwise, the result
+ * of the XPath expression is returned.
+ * @param xpathContextObject the context object used to resolve relative XPath expressions
+ * @param selectXPath the Xpath expression
+ * @return an Object or <code>null</code>
+ * @throws JET2TagException if an XPath error occurs.
+ */
public Object resolveSingle(Object xpathContextObject, String selectXPath) throws JET2TagException
{
try
@@ -183,6 +216,21 @@ public final class XPathContextExtender implements XPathVariableResolver
}
/**
+ * Resolve an XPath expression to a single object. This is a convenience implementation of:
+ * <pre>
+ * resolveSingle(currentXPathContextObject(), selectXPath)
+ * </pre>
+ * @param selectXPath the Xpath expression
+ * @return an Object or <code>null</code>
+ * @throws JET2TagException if an XPath error occurs.
+ * @see #resolveSingle(Object, String)
+ * @since 1.0
+ */
+ public Object resolveSingle(String selectXPath) throws JET2TagException
+ {
+ return resolveSingle(currentXPathContextObject(), selectXPath);
+ }
+ /**
* @param selectXPath
* @return
* @throws XPathException
@@ -221,11 +269,56 @@ public final class XPathContextExtender implements XPathVariableResolver
}
}
+ /**
+ * Return the current XPath context object. If no context object has been specified
+ * via {{@link #pushXPathContextObject(Object)}, then value of {@link JET2Context#getSource()}
+ * is returned
+ * @return the XPath context object
+ */
public Object currentXPathContextObject()
{
- return context.getSource();
+
+ return contextData.contextObjectStack.isEmpty() ? context.getSource() : contextData.contextObjectStack.peek();
}
+ /**
+ * Push a new XPath context object.
+ * The XPath context object is used to resolve relative XPath expressions.
+ * @param contextObject the object that will be the new XPath context object
+ * @see #currentXPathContextObject()
+ * @see #popXPathContextObject()
+ *
+ * @since 1.0
+ */
+ public void pushXPathContextObject(Object contextObject)
+ {
+ contextData.contextObjectStack.push(contextObject);
+ }
+
+ /**
+ * Restore the previous XPath context object.
+ *
+ * @return the XPath context object that was just removed
+ * @throws EmptyStackException if there is no prior XPath context to restore.
+ *
+ * @see #currentXPathContextObject()
+ * @see #pushXPathContextObject(Object)
+ *
+ * @since 1.0
+ */
+ public Object popXPathContextObject()
+ {
+ return contextData.contextObjectStack.pop();
+ }
+
+
+ /**
+ * Resolve an XPath expression into an array of Objects.
+ * @param xpathContextObject the context object for relative Xpath expressions
+ * @param selectXPath the XPath expression
+ * @return a possibly empty array of objects resolved by the expression
+ * @throws JET2TagException if an error in the XPath expression occurs
+ */
public Object[] resolve(Object xpathContextObject, String selectXPath) throws JET2TagException
{
try
@@ -238,12 +331,30 @@ public final class XPathContextExtender implements XPathVariableResolver
throw new JET2TagException(e);
}
}
+
+ /**
+ * Resolve an XPath expression into an array of Objects. This method
+ * is a convenience implementation of:
+ * <pre>
+ * resolve(currentXPathContextObject(), selectXPath)
+ * </pre>
+ *
+ * @param selectXPath selectXPath the XPath expression
+ * @return a possibly empty array of objects resolved by the expression
+ * @throws JET2TagException if an error in the XPath expression occurs
+ * @since 1.0
+ */
+ public Object[] resolve(String selectXPath) throws JET2TagException
+ {
+ return resolve(currentXPathContextObject(), selectXPath);
+ }
/**
* Resolve an xpath expression as a boolean result according to the
* XPath rules.
* <p>
- * TODO Add link to XPath 1.0 spec for clarification
+ * See the documentation of the XPath<a href="http://www.w3.org/TR/xpath#function-boolean">boolean</a>
+ * function for complete details on how XPath results are converted to boolean values.
* </p>
* @param xpathContext the XPath context object
* @param testXPath the XPath expression
@@ -263,6 +374,23 @@ public final class XPathContextExtender implements XPathVariableResolver
}
}
+ /**
+ * Resolve an xpath expression as a boolean result according to the
+ * XPath rules. This method is a convenience implementation of:
+ * <pre>
+ * resolveTest(currentXPathContextObject(), textXPath)
+ * </pre>
+ * @param testXPath the XPath expression
+ * @return <code>true</code> or <code>false</code>
+ * @throws JET2TagException if an error occurs in evaluating the expression.
+ * @see #resolveTest(Object, String)
+ * @since 1.0
+ */
+ public boolean resolveTest(String textXPath) throws JET2TagException
+ {
+ return resolveTest(currentXPathContextObject(), textXPath);
+ }
+
public boolean setAttribute(Object element, String name, String bodyContent) throws JET2TagException
{
IElementInspector elementInspector = getElementInspector(element);
@@ -479,6 +607,23 @@ public final class XPathContextExtender implements XPathVariableResolver
}
/**
+ * Resolve the XPath expression, returning an object. Unlike the other resolve methods, this
+ * method performs no type conversions on the XPath results. This is a convenience implementation of:
+ * <pre>
+ * resolveAsObject(currentXPathContextObject(), selectXPath);
+ * </pre>
+ * @param selectXPath the XPath expression
+ * @return the result of the expression evaluation.
+ * @throws JET2TagException if an error occurs.
+ * @see #resolveAsObject(Object, String)
+ * @since 1.0
+ */
+ public Object resolveAsObject(String selectXPath) throws JET2TagException
+ {
+ return resolveAsObject(currentXPathContextObject(), selectXPath);
+ }
+
+ /**
* Return the value of the named attribute on the passed element.
* @param element the element containing the attribute
* @param attributeName the attribute name
diff --git a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/IterateTag.java b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/IterateTag.java
index e3b2c77..9ac9e47 100644
--- a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/IterateTag.java
+++ b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/IterateTag.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * Copyright (c) 2005, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,12 +20,14 @@ package org.eclipse.jet.internal.taglib.control;
import java.text.MessageFormat;
import org.eclipse.jet.JET2Context;
+import org.eclipse.jet.JET2Writer;
import org.eclipse.jet.XPathContextExtender;
import org.eclipse.jet.internal.l10n.JET2Messages;
import org.eclipse.jet.taglib.AbstractIteratingTag;
import org.eclipse.jet.taglib.JET2TagException;
import org.eclipse.jet.taglib.TagInfo;
import org.eclipse.jet.xpath.NodeSet;
+import org.eclipse.jet.xpath.XPathUtil;
/**
@@ -35,6 +37,10 @@ import org.eclipse.jet.xpath.NodeSet;
public class IterateTag extends AbstractIteratingTag
{
+ private static final String UPDATE_CONTEXT_VAR = "org.eclipse.jet.taglib.control.iterateSetsContext"; //$NON-NLS-1$
+
+ private Boolean updateContext;
+
private Object[] selectedObjects;
private int currentIndex;
@@ -42,7 +48,7 @@ public class IterateTag extends AbstractIteratingTag
private String varName;
private Object savedVarValue = null;
-
+
private boolean nodeSetIteration;
private long maxIterations = 0;
@@ -60,34 +66,64 @@ public class IterateTag extends AbstractIteratingTag
*/
public boolean doEvalLoopCondition(TagInfo tc, JET2Context context) throws JET2TagException
{
- boolean doAnotherIteration = currentIndex < maxIterations;
+ boolean doAnotherIteration = ++currentIndex < maxIterations;
- if (doAnotherIteration)
+ if (!doAnotherIteration && varName != null)
{
- if (nodeSetIteration)
+ // clean up variables...
+ if (savedVarValue != null)
{
- context.setVariable(varName, selectedObjects[currentIndex]);
+ context.setVariable(varName, savedVarValue);
}
else
{
- context.setVariable(varName, new Long(currentIndex + 1));
+ context.removeVariable(varName);
+ }
+ }
+
+ return doAnotherIteration;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jet.taglib.AbstractIteratingTag#doBeforeBody(org.eclipse.jet.taglib.TagInfo, org.eclipse.jet.JET2Context, org.eclipse.jet.JET2Writer)
+ */
+ public void doBeforeBody(TagInfo td, JET2Context context, JET2Writer out) throws JET2TagException
+ {
+ super.doBeforeBody(td, context, out);
+
+ // set variables and context objects for this interation
+ if (nodeSetIteration)
+ {
+ final Object currentObject = selectedObjects[currentIndex];
+ if(varName != null) {
+ context.setVariable(varName, currentObject);
+ }
+ if(updateContext(context)) {
+ XPathContextExtender.getInstance(context).pushXPathContextObject(currentObject);
}
- // writeDelimiterIfAppropriate();
}
else
{
- context.removeVariable(varName);
- if (savedVarValue != null)
- {
- context.setVariable(varName, savedVarValue);
+ // numeric based looping is 1-based, add 1 to the current index.
+ if(varName != null) {
+ context.setVariable(varName, new Long(currentIndex + 1));
}
}
- currentIndex++;
-
- return doAnotherIteration;
}
-
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jet.taglib.AbstractIteratingTag#doAfterBody(org.eclipse.jet.taglib.TagInfo, org.eclipse.jet.JET2Context, org.eclipse.jet.JET2Writer)
+ */
+ public void doAfterBody(TagInfo td, JET2Context context, JET2Writer out) throws JET2TagException
+ {
+ // restore variables, context objects from previous interation up variables
+ if (updateContext(context))
+ {
+ XPathContextExtender.getInstance(context).popXPathContextObject();
+ }
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jet.taglib.IteratingTag#doInitializeLoop(org.eclipse.jet.taglib.TagInfo, org.eclipse.jet.JET2Context)
*/
@@ -100,7 +136,11 @@ public class IterateTag extends AbstractIteratingTag
XPathContextExtender xpathContext = XPathContextExtender.getInstance(context);
- if (context.hasVariable(varName))
+ if(updateContext(context)) {
+ context.getSource();
+ }
+
+ if (varName != null && context.hasVariable(varName))
{
savedVarValue = context.getVariable(varName);
}
@@ -121,7 +161,18 @@ public class IterateTag extends AbstractIteratingTag
{
throw new JET2TagException(MessageFormat.format(JET2Messages.IterateTag_CannotIterateOnResult, new Object []{ selectXPath }));
}
- currentIndex = 0;
+ currentIndex = -1;
}
+ private boolean updateContext(JET2Context context)
+ {
+ if(updateContext == null) {
+ if(!context.hasVariable(UPDATE_CONTEXT_VAR)) {
+ updateContext = Boolean.FALSE;
+ } else {
+ updateContext = Boolean.valueOf(XPathUtil.xpathBoolean(context.getVariable(UPDATE_CONTEXT_VAR)));
+ }
+ }
+ return updateContext.booleanValue();
+ }
}
diff --git a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/TagFactory.java b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/TagFactory.java
index c09d6b9..b18f52b 100644
--- a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/TagFactory.java
+++ b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/TagFactory.java
@@ -32,7 +32,7 @@ public class TagFactory implements TagInstanceFactory
*/
public TagFactory()
{
- tagOrdinalByName = new HashMap(27);
+ tagOrdinalByName = new HashMap(28);
tagOrdinalByName.put("addElement",new Integer(1)); //$NON-NLS-1$
tagOrdinalByName.put("addTextElement",new Integer(2)); //$NON-NLS-1$
@@ -61,6 +61,7 @@ public class TagFactory implements TagInstanceFactory
tagOrdinalByName.put("visit",new Integer(25)); //$NON-NLS-1$
tagOrdinalByName.put("visitor",new Integer(26)); //$NON-NLS-1$
tagOrdinalByName.put("when",new Integer(27)); //$NON-NLS-1$
+ tagOrdinalByName.put("with",new Integer(28)); //$NON-NLS-1$
}
public CustomTag createCustomTag(String name)
@@ -122,6 +123,8 @@ public class TagFactory implements TagInstanceFactory
return new org.eclipse.jet.internal.taglib.control.VisitorTag();
case 27: // when
return new org.eclipse.jet.internal.taglib.control.WhenTag();
+ case 28: // with
+ return new org.eclipse.jet.internal.taglib.control.WithTag();
default:
throw new JET2TagException("Unknown Tag: " + name); //$NON-NLS-1$
}
diff --git a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/WithTag.java b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/WithTag.java
new file mode 100644
index 0000000..4123ddc
--- /dev/null
+++ b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/taglib/control/WithTag.java
@@ -0,0 +1,77 @@
+/**
+ * <copyright>
+ *
+ * Copyright (c) 2009 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *
+ * </copyright>
+ *
+ * $Id: WithTag.java,v 1.1 2009/03/09 15:29:32 pelder Exp $
+ */
+package org.eclipse.jet.internal.taglib.control;
+
+import org.eclipse.jet.JET2Context;
+import org.eclipse.jet.JET2Writer;
+import org.eclipse.jet.XPathContextExtender;
+import org.eclipse.jet.internal.l10n.JET2Messages;
+import org.eclipse.jet.taglib.AbstractContainerTag;
+import org.eclipse.jet.taglib.JET2TagException;
+import org.eclipse.jet.taglib.TagInfo;
+
+/**
+ * Implement the &lt;c:with&gt; tag.
+ */
+public class WithTag extends AbstractContainerTag
+{
+
+ private boolean contextPushed = false;
+ private String varName = null;
+ private Object savedVarValue = null;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jet.taglib.ContainerTag#doBeforeBody(org.eclipse.jet.taglib.TagInfo, org.eclipse.jet.JET2Context, org.eclipse.jet.JET2Writer)
+ */
+ public void doBeforeBody(TagInfo td, JET2Context context, JET2Writer out) throws JET2TagException
+ {
+ final String selectXPath = getAttribute("select"); //$NON-NLS-1$
+ varName = getAttribute("var"); //$NON-NLS-1$
+ final XPathContextExtender xpc = XPathContextExtender.getInstance(context);
+
+ final Object contextObject = xpc.resolveSingle(selectXPath);
+ if(contextObject == null) {
+ throw new JET2TagException(JET2Messages.GetTag_NoResult);
+ }
+ xpc.pushXPathContextObject(contextObject);
+ contextPushed = true;
+ if(varName != null) {
+ savedVarValue = context.hasVariable(varName) ? context.getVariable(varName) : null;
+
+ context.setVariable(varName, contextObject);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jet.taglib.ContainerTag#doAfterBody(org.eclipse.jet.taglib.TagInfo, org.eclipse.jet.JET2Context, org.eclipse.jet.JET2Writer)
+ */
+ public void doAfterBody(TagInfo td, JET2Context context, JET2Writer out) throws JET2TagException
+ {
+ final XPathContextExtender xpc = XPathContextExtender.getInstance(context);
+ if(contextPushed) {
+ xpc.popXPathContextObject();
+ }
+ if(varName != null) {
+ if(savedVarValue != null) {
+ context.setVariable(varName, savedVarValue);
+ } else {
+ context.removeVariable(varName);
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.jet/transforms/plugins/org.eclipse.jet.transforms.newproject_1.0.0.jar b/plugins/org.eclipse.jet/transforms/plugins/org.eclipse.jet.transforms.newproject_1.0.0.jar
index f5214c0..988b2cb 100644
--- a/plugins/org.eclipse.jet/transforms/plugins/org.eclipse.jet.transforms.newproject_1.0.0.jar
+++ b/plugins/org.eclipse.jet/transforms/plugins/org.eclipse.jet.transforms.newproject_1.0.0.jar
Binary files differ
diff --git a/transforms/org.eclipse.jet.transforms.newproject/templates/project/control.jet.jet b/transforms/org.eclipse.jet.transforms.newproject/templates/project/control.jet.jet
index 35f7c1b..24249f1 100644
--- a/transforms/org.eclipse.jet.transforms.newproject/templates/project/control.jet.jet
+++ b/transforms/org.eclipse.jet.transforms.newproject/templates/project/control.jet.jet
@@ -1,6 +1,13 @@
<%@taglib prefix="cc" id="org.eclipse.jet.controlTags" %>
<\%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %>
<\%-- Main entry point for <cc:get select="$project/@bundleSymbolicName"/> --%>
+
+<\%--
+ Let c:iterate tags set the XPath context object.
+ For 100% compatibility with JET 0.9.x or earlier, remove this statement
+ --%>
+<c:setVariable var="org.eclipse.jet.taglib.control.iterateSetsContext" select="true()"/>
+
<cc:choose>
<cc:when test="$project/@baseID">
<\%--

Back to the top