git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275962 13f79535-47bb-0310-9956-ffa450edef68master
@@ -43,16 +43,6 @@ | |||
</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">textname</td> | |||
<td valign="top"> | |||
The textname attribute value becomes a macrodef | |||
attribute that | |||
gets set to the value of the text contents of the macro. | |||
<em>since ant 1.6.1</em> | |||
</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h3>Parameters specified as nested elements</h3> | |||
<h4>attribute</h4> | |||
@@ -143,6 +133,54 @@ | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h4>text</h4> | |||
<p> | |||
This is used to specify the treatment of text contents of the macrodef. | |||
If this element is not present, then any nested text in the macro | |||
will be an error. If the text element is present, then the name | |||
becomes an attribute that gets set to the nested text of the macro. | |||
<em>Since ant 1.6.1.</em> | |||
</p> | |||
<p> | |||
The case of the text name is ignored. | |||
</p> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
<tr> | |||
<td valign="top"><b>Attribute</b></td> | |||
<td valign="top"><b>Description</b></td> | |||
<td align="center" valign="top"><b>Required</b></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">name</td> | |||
<td valign="top">The name of the text attribute</td> | |||
<td valign="top" align="center">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">optional</td> | |||
<td valign="top"> | |||
If true nested text in the macro is optional, default is "false". | |||
</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">trim</td> | |||
<td valign="top"> | |||
If true, the nested text is trimmed of white space, | |||
default is "false". | |||
</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">description</td> | |||
<td valign="top"> | |||
This contains a description | |||
informing the user what the nested text of the macro is expected | |||
to be. | |||
</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h3>Examples</h3> | |||
<p> | |||
@@ -211,11 +249,12 @@ | |||
</pre> | |||
</blockquote> | |||
<p> | |||
The following shows the use of the <code>textname</code> attribute. | |||
The following shows the use of the <code>text</code> element. | |||
</p> | |||
<blockquote> | |||
<pre class="code"> | |||
<macrodef name="echotest" textname="text"> | |||
<macrodef name="echotest"> | |||
<text name="text"/text> | |||
<sequential> | |||
<echo>@{text}</echo> | |||
</sequential> | |||
@@ -102,8 +102,9 @@ | |||
</ignore> | |||
</target> | |||
<target name="textname"> | |||
<macrodef name="echotest" textname="text"> | |||
<target name="textelement"> | |||
<macrodef name="echotest"> | |||
<text name="text" optional="yes"/> | |||
<sequential> | |||
<echo>@{text}</echo> | |||
</sequential> | |||
@@ -113,8 +114,31 @@ | |||
</echotest> | |||
</target> | |||
<target name="text.trim"> | |||
<macrodef name="echotest"> | |||
<text name="text" trim="yes"/> | |||
<sequential> | |||
<echo>[@{text}]</echo> | |||
</sequential> | |||
</macrodef> | |||
<echotest> | |||
Hello world | |||
</echotest> | |||
</target> | |||
<target name="duplicatetextname"> | |||
<macrodef name="echotest" textname="text"> | |||
<macrodef name="echotest"> | |||
<attribute name="text"/> | |||
<text name="text"/> | |||
<sequential> | |||
<echo>@{text}</echo> | |||
</sequential> | |||
</macrodef> | |||
</target> | |||
<target name="duplicatetextname2"> | |||
<macrodef name="echotest"> | |||
<text name="text"/> | |||
<attribute name="text"/> | |||
<sequential> | |||
<echo>@{text}</echo> | |||
@@ -59,6 +59,7 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.Locale; | |||
import java.util.HashMap; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.AntTypeDefinition; | |||
import org.apache.tools.ant.BuildException; | |||
@@ -82,6 +83,7 @@ public class MacroDef extends AntlibDefinition { | |||
private List attributes = new ArrayList(); | |||
private Map elements = new HashMap(); | |||
private String textName = null; | |||
private Text text = null; | |||
/** | |||
* Name of the definition | |||
@@ -92,22 +94,39 @@ public class MacroDef extends AntlibDefinition { | |||
} | |||
/** | |||
* Name of the text attribute. | |||
* @param textName the name of the attribute to use for the | |||
* text content of the macro. | |||
* Add the text element. | |||
* @param text the nested text element to add | |||
* @since ant 1.6.1 | |||
*/ | |||
public void setTextName(String textName) { | |||
this.textName = textName; | |||
public void addConfiguredText(Text text) { | |||
if (this.text != null) { | |||
throw new BuildException( | |||
"Only one nested text element allowed"); | |||
} | |||
if (text.getName() == null) { | |||
throw new BuildException( | |||
"the text nested element needed a \"name\" attribute"); | |||
} | |||
// Check if used by attributes | |||
for (Iterator i = attributes.iterator(); i.hasNext();) { | |||
Attribute attribute = (Attribute) i.next(); | |||
if (text.getName().equals(attribute.getName())) { | |||
throw new BuildException( | |||
"the name \"" + text.getName() | |||
+ "\" is already used as an attribute"); | |||
} | |||
} | |||
this.text = text; | |||
this.textName = text.getName(); | |||
} | |||
/** | |||
* @return the name of the text content attribute | |||
* @return the nested text element | |||
* @since ant 1.6.1 | |||
*/ | |||
public String getTextName() { | |||
return textName; | |||
public Text getText() { | |||
return text; | |||
} | |||
/** | |||
@@ -245,7 +264,7 @@ public class MacroDef extends AntlibDefinition { | |||
if (attribute.getName().equals(textName)) { | |||
throw new BuildException( | |||
"the attribute name \"" + attribute.getName() | |||
+ "\" has already been used by the textname attribute"); | |||
+ "\" has already been used by the text element"); | |||
} | |||
for (int i = 0; i < attributes.size(); ++i) { | |||
if (((Attribute) attributes.get(i)).getName().equals( | |||
@@ -403,6 +422,122 @@ public class MacroDef extends AntlibDefinition { | |||
} | |||
} | |||
/** | |||
* A nested text element for the MacroDef task. | |||
* @since ant 1.6.1 | |||
*/ | |||
public static class Text { | |||
private String name; | |||
private boolean optional; | |||
private boolean trim; | |||
private String description; | |||
/** | |||
* The name of the attribute. | |||
* | |||
* @param name the name of the attribute | |||
*/ | |||
public void setName(String name) { | |||
if (!isValidName(name)) { | |||
throw new BuildException( | |||
"Illegal name [" + name + "] for attribute"); | |||
} | |||
this.name = name.toLowerCase(Locale.US); | |||
} | |||
/** | |||
* @return the name of the attribute | |||
*/ | |||
public String getName() { | |||
return name; | |||
} | |||
/** | |||
* The optional attribute of the text element. | |||
* | |||
* @param optional if true this is optional | |||
*/ | |||
public void setOptional(boolean optional) { | |||
this.optional = optional; | |||
} | |||
/** | |||
* @return true if the text is optional | |||
*/ | |||
public boolean getOptional() { | |||
return optional; | |||
} | |||
/** | |||
* The trim attribute of the text element. | |||
* | |||
* @param trim if true this String.trim() is called on | |||
* the contents of the text element. | |||
*/ | |||
public void setTrim(boolean trim) { | |||
this.trim = trim; | |||
} | |||
/** | |||
* @return true if the text is trim | |||
*/ | |||
public boolean getTrim() { | |||
return trim; | |||
} | |||
/** | |||
* @param desc Description of the text. | |||
*/ | |||
public void setDescription(String desc) { | |||
description = desc; | |||
} | |||
/** | |||
* @return the description of the text, or <code>null</code> if | |||
* no description is available. | |||
*/ | |||
public String getDescription() { | |||
return description; | |||
} | |||
/** | |||
* equality method | |||
* | |||
* @param obj an <code>Object</code> value | |||
* @return a <code>boolean</code> value | |||
*/ | |||
public boolean equals(Object obj) { | |||
if (obj == null) { | |||
return false; | |||
} | |||
if (obj.getClass() != getClass()) { | |||
return false; | |||
} | |||
Text other = (Text) obj; | |||
if (name == null) { | |||
if (other.name != null) { | |||
return false; | |||
} | |||
} else if (!name.equals(other.name)) { | |||
return false; | |||
} | |||
if (optional != other.optional) { | |||
return false; | |||
} | |||
if (trim != other.trim) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* @return a hash code value for this object. | |||
*/ | |||
public int hashCode() { | |||
return objectHashCode(name); | |||
} | |||
} | |||
/** | |||
* A nested element for the MacroDef task. | |||
* | |||
@@ -519,12 +654,12 @@ public class MacroDef extends AntlibDefinition { | |||
if (!name.equals(other.name)) { | |||
return false; | |||
} | |||
if (textName == null) { | |||
if (other.textName != null) { | |||
if (text == null) { | |||
if (other.text != null) { | |||
return false; | |||
} | |||
} else { | |||
if (!textName.equals(other.textName)) { | |||
if (!text.equals(other.text)) { | |||
return false; | |||
} | |||
} | |||
@@ -88,7 +88,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
private Map nsElements = null; | |||
private Map presentElements = new HashMap(); | |||
private Hashtable localProperties = new Hashtable(); | |||
private String text = ""; | |||
private String text = null; | |||
/** | |||
* Called from MacroDef.MyAntTypeDefinition#create() | |||
@@ -251,6 +251,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
* Set the text contents for the macro. | |||
* @param text the text to be added to the macro. | |||
*/ | |||
public void addText(String text) { | |||
this.text = text; | |||
} | |||
@@ -340,10 +341,25 @@ public class MacroInstance extends Task implements DynamicConfigurator { | |||
if (copyKeys.contains("id")) { | |||
copyKeys.remove("id"); | |||
} | |||
if (macroDef.getTextName() != null) { | |||
localProperties.put(macroDef.getTextName(), text); | |||
if (macroDef.getText() != null) { | |||
if (text == null) { | |||
if (!macroDef.getText().getOptional()) { | |||
throw new BuildException( | |||
"required text missing"); | |||
} | |||
text = ""; | |||
} | |||
if (macroDef.getText().getTrim()) { | |||
text = text.trim(); | |||
} | |||
localProperties.put(macroDef.getText().getName(), text); | |||
} else { | |||
if (text != null && !text.trim().equals("")) { | |||
throw new BuildException( | |||
"The \"" + getTaskName() + "\" macro does not support" | |||
+ " nested text data."); | |||
} | |||
} | |||
if (copyKeys.size() != 0) { | |||
throw new BuildException( | |||
"Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ") | |||
@@ -116,15 +116,25 @@ public class MacroDefTest extends BuildFileTest { | |||
"nested elementnested element"); | |||
} | |||
public void testTextName() { | |||
public void testTextElement() { | |||
expectLogContaining( | |||
"textname", "Hello world"); | |||
"textelement", "Hello world"); | |||
} | |||
public void testTextTrim() { | |||
expectLogContaining( | |||
"text.trim", "[Hello world]"); | |||
} | |||
public void testDuplicateTextName() { | |||
expectBuildException( | |||
"duplicatetextname", | |||
"the attribute text has already been specified"); | |||
"the name \"text\" is already used as an attribute"); | |||
} | |||
public void testDuplicateTextName2() { | |||
expectBuildException( | |||
"duplicatetextname2", | |||
"the attribute name \"text\" has already been used by the text element"); | |||
} | |||
} | |||