@@ -53,6 +53,12 @@ examples section.</p> | |||||
</tr> | </tr> | ||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>Name</h4> | |||||
<p>As an alternative to (or in conjunction with) the <code>name</code> attribute, the nested text of | |||||
each of one or more nested <code><name></code> elements specifies a property name to declare in | |||||
the local scope. | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<h4>Temporarily shadow a global property's value</h4> | <h4>Temporarily shadow a global property's value</h4> | ||||
@@ -171,5 +177,15 @@ come up with unique names in some cases.</p> | |||||
<p>Each invocation gets its own property named <code>parent</code> and there will be no global | <p>Each invocation gets its own property named <code>parent</code> and there will be no global | ||||
property of that name at all.</p> | property of that name at all.</p> | ||||
<h4>Use of nested name elements</h4> | |||||
This style declares and executes a single task, as compensation for requiring more lines of XML than | |||||
would individual invocations using <code>@name</code>: | |||||
<pre> | |||||
<local> | |||||
<name>foo</name> | |||||
<name>bar</name> | |||||
<name>baz</name> | |||||
</local> | |||||
</pre> | |||||
</body> | </body> | ||||
</html> | </html> |
@@ -17,15 +17,48 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
import java.util.LinkedHashSet; | |||||
import java.util.Set; | |||||
import java.util.function.Consumer; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
import org.apache.tools.ant.property.LocalProperties; | import org.apache.tools.ant.property.LocalProperties; | ||||
import org.apache.tools.ant.util.StringUtils; | |||||
/** | /** | ||||
* Task to create a local property in the current scope. | |||||
* Task to create local properties in the current scope. | |||||
*/ | */ | ||||
public class Local extends Task { | public class Local extends Task { | ||||
/** | |||||
* Nested {@code name} element. | |||||
*/ | |||||
public static class Name implements Consumer<LocalProperties> { | |||||
private String text; | |||||
/** | |||||
* Set the property name. | |||||
* @param text | |||||
*/ | |||||
public void addText(String text) { | |||||
this.text = text; | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
@Override | |||||
public void accept(LocalProperties localProperties) { | |||||
if (text == null) { | |||||
throw new BuildException("nested name element is missing text"); | |||||
} | |||||
localProperties.addLocal(text); | |||||
} | |||||
} | |||||
private String name; | private String name; | ||||
private final Set<Name> nameElements = new LinkedHashSet<>(); | |||||
/** | /** | ||||
* Set the name attribute. | * Set the name attribute. | ||||
@@ -35,13 +68,28 @@ public class Local extends Task { | |||||
this.name = name; | this.name = name; | ||||
} | } | ||||
/** | |||||
* Create a nested {@code name} element. | |||||
* @return {@link Name} | |||||
*/ | |||||
public Name createName() { | |||||
final Name result = new Name(); | |||||
nameElements.add(result); | |||||
return result; | |||||
} | |||||
/** | /** | ||||
* Run the task. | * Run the task. | ||||
*/ | */ | ||||
public void execute() { | public void execute() { | ||||
if (name == null) { | |||||
throw new BuildException("Missing attribute name"); | |||||
if (name == null && nameElements.isEmpty()) { | |||||
throw new BuildException("Found no configured local property names"); | |||||
} | |||||
final LocalProperties localProperties = LocalProperties.get(getProject()); | |||||
if (name != null) { | |||||
localProperties.addLocal(name); | |||||
} | } | ||||
LocalProperties.get(getProject()).addLocal(name); | |||||
nameElements.forEach(n -> n.accept(localProperties)); | |||||
} | } | ||||
} | } |
@@ -93,4 +93,24 @@ | |||||
<au:assertPropertyEquals name="foo" value="foo" /> | <au:assertPropertyEquals name="foo" value="foo" /> | ||||
</target> | </target> | ||||
<target name="testMulti"> | |||||
<property name="bar" value="bar" /> | |||||
<property name="baz" value="baz" /> | |||||
<sequential> | |||||
<local> | |||||
<name>foo</name> | |||||
<name>bar</name> | |||||
<name>baz</name> | |||||
</local> | |||||
<property name="foo" value="FOO" /> | |||||
<property name="bar" value="BAR" /> | |||||
<property name="baz" value="BAZ" /> | |||||
<au:assertPropertyEquals name="foo" value="FOO" /> | |||||
<au:assertPropertyEquals name="bar" value="BAR" /> | |||||
<au:assertPropertyEquals name="baz" value="BAZ" /> | |||||
</sequential> | |||||
<au:assertPropertyEquals name="foo" value="foo" /> | |||||
<au:assertPropertyEquals name="bar" value="bar" /> | |||||
<au:assertPropertyEquals name="baz" value="baz" /> | |||||
</target> | |||||
</project> | </project> |