You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@apache.org on 2005/09/28 20:34:11 UTC
svn commit: r292244 - in /ant/core/trunk:
docs/manual/CoreTasks/antstructure.html
src/etc/testcases/taskdefs/antstructure.xml
src/main/org/apache/tools/ant/taskdefs/AntStructure.java
src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java
Author: bodewig
Date: Wed Sep 28 11:34:04 2005
New Revision: 292244
URL: http://svn.apache.org/viewcvs?rev=292244&view=rev
Log:
lay grounds for Schema or Relax NG description generators as plugins in antstructure
Modified:
ant/core/trunk/docs/manual/CoreTasks/antstructure.html
ant/core/trunk/src/etc/testcases/taskdefs/antstructure.xml
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java
Modified: ant/core/trunk/docs/manual/CoreTasks/antstructure.html
URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/CoreTasks/antstructure.html?rev=292244&r1=292243&r2=292244&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/antstructure.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/antstructure.html Wed Sep 28 11:34:04 2005
@@ -30,6 +30,14 @@
target="_top">here</a> for a way to get around this problem.</p>
<p>This task doesn't know about required attributes, all will be
listed as <code>#IMPLIED</code>.</p>
+
+<p><em>Since Ant 1.7</em> custom structure printers can be used
+instead of the one that emits a DTD. In order to plug in your own
+structure, you have to implement the interface
+<code>org.apache.tools.ant.taskdefs.AntStructure.StructurePrinter</code>
+and <code><typedef> your class and use the new type as a nested
+element of this task - see the example below.</code>
+
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -47,6 +55,31 @@
<blockquote><pre>
<antstructure output="project.dtd"/>
</pre></blockquote>
+
+<p><b>Emitting your own structure instead of a DTD</b></p>
+
+<p>First you need to implement the interface</p>
+
+<pre>
+package org.example;
+import org.apache.tools.ant.taskdefs.AntStructure;
+public class MyPrinter implements AntStructure.StructurePrinter {
+ ...
+}
+</pre>
+
+<p>and then use it via typedef</p>
+
+<pre>
+ <typedef name="myprinter" classname="org.example.MyPrinter"/>
+ <antstructure output="project.my">
+ <myprinter/>
+ <antstructure>
+</pre>
+
+<p>Your own StructurePrinter can accept attributes and nested elements
+just like any other Ant type or task.</p>
+
<hr><p align="center">Copyright © 2000-2002,2004-2005 The Apache Software Foundation. All rights
Reserved.</p>
Modified: ant/core/trunk/src/etc/testcases/taskdefs/antstructure.xml
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/etc/testcases/taskdefs/antstructure.xml?rev=292244&r1=292243&r2=292244&view=diff
==============================================================================
--- ant/core/trunk/src/etc/testcases/taskdefs/antstructure.xml (original)
+++ ant/core/trunk/src/etc/testcases/taskdefs/antstructure.xml Wed Sep 28 11:34:04 2005
@@ -6,4 +6,20 @@
<antstructure/>
</target>
+ <target name="testCustomPrinter">
+ <typedef name="myprinter"
+ classname="org.apache.tools.ant.taskdefs.AntStructureTest$MyPrinter">
+ <classpath>
+ <pathelement path="${tests-classpath.value}"/>
+ </classpath>
+ </typedef>
+ <antstructure output="foo.dtd">
+ <myprinter/>
+ </antstructure>
+ </target>
+
+ <target name="tearDown">
+ <delete file="foo.dtd" quiet="true"/>
+ </target>
+
</project>
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java?rev=292244&r1=292243&r2=292244&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java Wed Sep 28 11:34:04 2005
@@ -29,6 +29,7 @@
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.IntrospectionHelper;
+import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
import org.apache.tools.ant.types.EnumeratedAttribute;
@@ -44,15 +45,10 @@
*/
public class AntStructure extends Task {
- private final String lSep = System.getProperty("line.separator");
-
- private static final String BOOLEAN = "%boolean;";
- private static final String TASKS = "%tasks;";
- private static final String TYPES = "%types;";
-
- private Hashtable visited = new Hashtable();
+ private static final String lSep = System.getProperty("line.separator");
private File output;
+ private StructurePrinter printer = new DTDPrinter();
/**
* The output file.
@@ -63,6 +59,14 @@
}
/**
+ * The StructurePrinter to use.
+ * @since Ant 1.7
+ */
+ public void add(StructurePrinter p) {
+ printer = p;
+ }
+
+ /**
* Build the antstructure DTD.
*
* @exception BuildException if the DTD cannot be written.
@@ -87,25 +91,28 @@
out = new PrintWriter(new FileWriter(output));
}
- printHead(out, getProject().getTaskDefinitions().keys(),
- getProject().getDataTypeDefinitions().keys());
+ printer.printHead(out, getProject(),
+ getProject().getTaskDefinitions(),
+ getProject().getDataTypeDefinitions());
- printTargetDecl(out);
+ printer.printTargetDecl(out);
Enumeration dataTypes = getProject().getDataTypeDefinitions().keys();
while (dataTypes.hasMoreElements()) {
String typeName = (String) dataTypes.nextElement();
- printElementDecl(out, typeName,
+ printer.printElementDecl(out, getProject(), typeName,
(Class) getProject().getDataTypeDefinitions().get(typeName));
}
Enumeration tasks = getProject().getTaskDefinitions().keys();
while (tasks.hasMoreElements()) {
String tName = (String) tasks.nextElement();
- printElementDecl(out, tName,
+ printer.printElementDecl(out, getProject(), tName,
(Class) getProject().getTaskDefinitions().get(tName));
}
+ printer.printTail(out);
+
} catch (IOException ioe) {
throw new BuildException("Error writing "
+ output.getAbsolutePath(), ioe, getLocation());
@@ -113,11 +120,73 @@
if (out != null) {
out.close();
}
- visited.clear();
}
}
/**
+ * Writes the actual structure information.
+ *
+ * <p>{@link StructurePrinter#printHead printHead}, {@link
+ * StructurePrinter#printTargetDecl printTargetDecl} and {@link
+ * StructurePrinter#printTail printTail} are called exactly once,
+ * {@link StructurePrinter#printElement printElement} once for
+ * each declared task and type.</p>
+ */
+ public static interface StructurePrinter {
+ /**
+ * Prints the header of the generated output.
+ *
+ * @param out PrintWriter to write to.
+ * @param p Project instance for the current task
+ * @param tasks map (name to implementing class)
+ * @param types map (name to implementing class)
+ * data types.
+ */
+ void printHead(PrintWriter out, Project p, Hashtable tasks,
+ Hashtable types);
+
+ /**
+ * Prints the definition for the target element.
+ * @param out PrintWriter to write to.
+ */
+ void printTargetDecl(PrintWriter out);
+
+ /**
+ * Print the definition for a given element.
+ *
+ * @param out PrintWriter to write to.
+ * @param p Project instance for the current task
+ * @param name element name.
+ * @param name class of the defined element.
+ */
+ void printElementDecl(PrintWriter out, Project p, String name,
+ Class element);
+
+ /**
+ * Prints the trailer.
+ * @param out PrintWriter to write to.
+ */
+ void printTail(PrintWriter out);
+ }
+
+ private static class DTDPrinter implements StructurePrinter {
+
+ private static final String BOOLEAN = "%boolean;";
+ private static final String TASKS = "%tasks;";
+ private static final String TYPES = "%types;";
+
+ private Hashtable visited = new Hashtable();
+
+ public void printTail(PrintWriter out) {
+ visited.clear();
+ }
+
+ public void printHead(PrintWriter out, Project p, Hashtable tasks, Hashtable types) {
+ printHead(out, tasks.keys(), types.keys());
+ }
+
+
+ /**
* Prints the header of the generated output.
*
* <p>Basically this prints the XML declaration, defines some
@@ -169,7 +238,7 @@
/**
* Prints the definition for the target element.
*/
- private void printTargetDecl(PrintWriter out) {
+ public void printTargetDecl(PrintWriter out) {
out.print("<!ELEMENT target (");
out.print(TASKS);
out.print(" | ");
@@ -190,8 +259,8 @@
/**
* Print the definition for a given element.
*/
- private void printElementDecl(PrintWriter out, String name, Class element)
- throws BuildException {
+ public void printElementDecl(PrintWriter out, Project p,
+ String name, Class element) {
if (visited.containsKey(name)) {
return;
@@ -200,7 +269,7 @@
IntrospectionHelper ih = null;
try {
- ih = IntrospectionHelper.getHelper(getProject(), element);
+ ih = IntrospectionHelper.getHelper(p, element);
} catch (Throwable t) {
/*
* XXX - failed to load the class properly.
@@ -312,7 +381,7 @@
if (!"#PCDATA".equals(nestedName)
&& !TASKS.equals(nestedName)
&& !TYPES.equals(nestedName)) {
- printElementDecl(out, nestedName, ih.getElementType(nestedName));
+ printElementDecl(out, p, nestedName, ih.getElementType(nestedName));
}
}
}
@@ -322,7 +391,7 @@
* @param s the string to test
* @return true if the string matches the XML-NMTOKEN
*/
- protected boolean isNmtoken(String s) {
+ public static final boolean isNmtoken(String s) {
final int length = s.length();
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
@@ -343,7 +412,7 @@
* @param s the array of string to test
* @return true if all the strings in the array math XML-NMTOKEN
*/
- protected boolean areNmtokens(String[] s) {
+ public static final boolean areNmtokens(String[] s) {
for (int i = 0; i < s.length; i++) {
if (!isNmtoken(s[i])) {
return false;
@@ -351,5 +420,26 @@
}
return true;
}
+ }
+
+ /**
+ * Does this String match the XML-NMTOKEN production?
+ * @param s the string to test
+ * @return true if the string matches the XML-NMTOKEN
+ */
+ protected boolean isNmtoken(String s) {
+ return DTDPrinter.isNmtoken(s);
+ }
+ /**
+ * Do the Strings all match the XML-NMTOKEN production?
+ *
+ * <p>Otherwise they are not suitable as an enumerated attribute,
+ * for example.</p>
+ * @param s the array of string to test
+ * @return true if all the strings in the array math XML-NMTOKEN
+ */
+ protected boolean areNmtokens(String[] s) {
+ return DTDPrinter.areNmtokens(s);
+ }
}
Modified: ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java?rev=292244&r1=292243&r2=292244&view=diff
==============================================================================
--- ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java (original)
+++ ant/core/trunk/src/testcases/org/apache/tools/ant/taskdefs/AntStructureTest.java Wed Sep 28 11:34:04 2005
@@ -17,7 +17,12 @@
package org.apache.tools.ant.taskdefs;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import junit.framework.Assert;
import org.apache.tools.ant.BuildFileTest;
+import org.apache.tools.ant.Project;
+
/**
*/
public class AntStructureTest extends BuildFileTest {
@@ -30,7 +35,62 @@
configureProject("src/etc/testcases/taskdefs/antstructure.xml");
}
+ public void tearDown() {
+ executeTarget("tearDown");
+ }
+
public void test1() {
expectBuildException("test1", "required argument not specified");
+ }
+
+ public void testCustomPrinter() {
+ executeTarget("testCustomPrinter");
+ // can't access the booleans in MyPrinter here (even if they
+ // were static) since the MyPrinter instance that was used in
+ // the test has likely been loaded via a different classloader
+ // than this class. Therefore we make the printer assert its
+ // state and only check for the tail invocation.
+ assertLogContaining(MyPrinter.TAIL_CALLED);
+ }
+
+ public static class MyPrinter implements AntStructure.StructurePrinter {
+ private static final String TAIL_CALLED = "tail has been called";
+ private boolean headCalled = false;
+ private boolean targetCalled = false;
+ private boolean tailCalled = false;
+ private int elementCalled = 0;
+ private Project p;
+
+ public void printHead(PrintWriter out, Project p, Hashtable tasks,
+ Hashtable types) {
+ Assert.assertTrue(!headCalled);
+ Assert.assertTrue(!targetCalled);
+ Assert.assertTrue(!tailCalled);
+ Assert.assertEquals(0, elementCalled);
+ headCalled = true;
+ }
+ public void printTargetDecl(PrintWriter out) {
+ Assert.assertTrue(headCalled);
+ Assert.assertTrue(!targetCalled);
+ Assert.assertTrue(!tailCalled);
+ Assert.assertEquals(0, elementCalled);
+ targetCalled = true;
+ }
+ public void printElementDecl(PrintWriter out, Project p, String name,
+ Class element) {
+ Assert.assertTrue(headCalled);
+ Assert.assertTrue(targetCalled);
+ Assert.assertTrue(!tailCalled);
+ elementCalled++;
+ this.p = p;
+ }
+ public void printTail(PrintWriter out) {
+ Assert.assertTrue(headCalled);
+ Assert.assertTrue(targetCalled);
+ Assert.assertTrue(!tailCalled);
+ Assert.assertTrue(elementCalled > 0);
+ tailCalled = true;
+ p.log(TAIL_CALLED);
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org