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"); | |||
| } | |||
| } | |||