mbenson 2004/04/22 13:27:21
Modified: src/main/org/apache/tools/ant/util ContainerMapper.java
docs/manual/CoreTypes mapper.html
src/main/org/apache/tools/ant/types Mapper.java
defaults.properties
src/testcases/org/apache/tools/ant/types MapperTest.java
Added: src/main/org/apache/tools/ant/util ChainedMapper.java
CompositeMapper.java
Log:
Make ContainerMapper abstract; move chained/composite behaviors to
subclasses ChainedMapper and CompositeMapper, respectively.
Revision Changes Path
1.3 +49 -77 ant/src/main/org/apache/tools/ant/util/ContainerMapper.java
Index: ContainerMapper.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/util/ContainerMapper.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ContainerMapper.java 15 Mar 2004 17:26:34 -0000 1.2
+++ ContainerMapper.java 22 Apr 2004 20:27:21 -0000 1.3
@@ -17,112 +17,84 @@
package org.apache.tools.ant.util;
-import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collections;
import org.apache.tools.ant.types.Mapper;
/**
- * A filenamemapper that contains other filename mappers.
- * The mappers proceeded in a chain or separately.
+ * A <code>FileNameMapper</code> that contains
+ * other <CODE>FileNameMapper</CODE>s.
* @see FileNameMapper
*/
+public abstract class ContainerMapper implements FileNameMapper {
-public class ContainerMapper implements FileNameMapper {
-
- private boolean chained = false;
private List mappers = new ArrayList();
/**
- * Add a file name mapper.
- *
- * @param fileNameMapper a file name mapper.
+ * Add a <code>Mapper</code>.
+ * @param mapper the <code>Mapper</code> to add.
*/
- public void add(FileNameMapper fileNameMapper) {
- mappers.add(fileNameMapper);
+ public void addConfiguredMapper(Mapper mapper) {
+ add(mapper.getImplementation());
}
/**
- * Add a Mapper
- * @param mapper the mapper to add
- */
- public void addConfiguredMapper(Mapper mapper) {
- mappers.add(mapper.getImplementation());
+ * Add a <code>FileNameMapper</code>.
+ * @param fileNameMapper a <CODE>FileNameMapper</CODE>.
+ * @throws <CODE>IllegalArgumentException</CODE> if attempting to add this
+ * <CODE>ContainerMapper</CODE> to itself, or if the specified
+ * <CODE>FileNameMapper</CODE> is itself a <CODE>ContainerMapper</CODE>
+ * that contains this <CODE>ContainerMapper</CODE>.
+ */
+ public synchronized void add(FileNameMapper fileNameMapper) {
+ if (this == fileNameMapper
+ || (fileNameMapper instanceof ContainerMapper
+ && ((ContainerMapper)fileNameMapper).contains(this))) {
+ throw new IllegalArgumentException(
+ "Circular mapper containment condition detected");
+ } else {
+ mappers.add(fileNameMapper);
+ }
+ }
+
+ /**
+ * Return <CODE>true</CODE> if this <CODE>ContainerMapper</CODE>
or any of
+ * its sub-elements contains the specified <CODE>FileNameMapper</CODE>.
+ * @param fileNameMapper the <CODE>FileNameMapper</CODE> to search for.
+ * @return <CODE>boolean</CODE>.
+ */
+ protected synchronized boolean contains(FileNameMapper fileNameMapper) {
+ boolean foundit = false;
+ for (Iterator iter = mappers.iterator(); iter.hasNext() && !foundit;) {
+ FileNameMapper next = (FileNameMapper)(iter.next());
+ foundit|= (next == fileNameMapper
+ || (next instanceof ContainerMapper
+ && ((ContainerMapper)next).contains(fileNameMapper)));
+ }
+ return foundit;
}
/**
- * Set the chained attribute.
- *
- * @param chained if true the mappers are processed in
- * a chained fashion. The outputs of
- * a mapper are the inputs for the next mapper.
- * if false the mappers are processed indepentanly, the
- * outputs are combined.
+ * Get the <CODE>List</CODE> of <CODE>FileNameMapper</CODE>s.
+ * @return <CODE>List</CODE>.
*/
- public void setChained(boolean chained) {
- this.chained = chained;
+ public synchronized List getMappers() {
+ return Collections.unmodifiableList(mappers);
}
/**
- * This method is ignored, present to fullfill the FileNameMapper
- * interface.
- * @param ignore this parameter is ignored.
+ * Empty implementation.
*/
public void setFrom(String ignore) {
}
/**
- * This method is ignored, present to fullfill the FileNameMapper
- * interface.
- * @param ignore this parameter is ignored.
+ * Empty implementation.
*/
public void setTo(String ignore) {
}
- /**
- * Map a filename using the list of mappers.
- *
- * @param sourceFileName The filename to map.
- * @return a <code>String[]</code> value or null if there
- * are no mappings.
- */
- public String[] mapFileName(String sourceFileName) {
- List ret = new ArrayList();
- if (chained) {
- List inputs = new ArrayList();
- ret.add(sourceFileName);
- for (int i = 0; i < mappers.size(); ++i) {
- inputs = ret;
- ret = new ArrayList();
- FileNameMapper mapper = (FileNameMapper) mappers.get(i);
- for (Iterator it = inputs.iterator(); it.hasNext();) {
- String[] mapped = mapper.mapFileName(
- (String) it.next());
- if (mapped != null) {
- for (int m = 0; m < mapped.length; ++m) {
- ret.add(mapped[m]);
- }
- }
- }
- if (ret.size() == 0) {
- return null;
- }
- }
- } else {
- for (int i = 0; i < mappers.size(); ++i) {
- FileNameMapper mapper = (FileNameMapper) mappers.get(i);
- String[] mapped = mapper.mapFileName(sourceFileName);
- if (mapped != null) {
- for (int m = 0; m < mapped.length; ++m) {
- ret.add(mapped[m]);
- }
- }
- }
- if (ret.size() == 0) {
- return null;
- }
- }
- return (String[]) ret.toArray(new String[ret.size()]);
- }
}
1.1 ant/src/main/org/apache/tools/ant/util/ChainedMapper.java
Index: ChainedMapper.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.util;
import java.util.List;
import java.util.Arrays;
import java.util.Iterator;
import java.util.ArrayList;
import org.apache.tools.ant.types.Mapper;
/**
* A <CODE>ContainerMapper</CODE> that chains the results of the first
* nested <CODE>FileNameMapper</CODE>s into sourcefiles for the second,
* the second to the third, and so on, returning the resulting mapped
* filenames from the last nested <CODE>FileNameMapper</CODE>.
*/
public class ChainedMapper extends ContainerMapper {
//inherit doc
public String[] mapFileName(String sourceFileName) {
List inputs = new ArrayList();
List results = new ArrayList();
results.add(sourceFileName);
FileNameMapper mapper = null;
for (Iterator mIter = getMappers().iterator(); mIter.hasNext();) {
mapper = (FileNameMapper)(mIter.next());
if (mapper != null) {
inputs.clear();
inputs.addAll(results);
results.clear();
for (Iterator it = inputs.iterator(); it.hasNext();) {
String[] mapped = mapper.mapFileName((String)(it.next()));
if (mapped != null) {
results.addAll(Arrays.asList(mapped));
}
}
}
}
return (results.size() == 0) ? null
: (String[]) results.toArray(new String[results.size()]);
}
}
1.1 ant/src/main/org/apache/tools/ant/util/CompositeMapper.java
Index: CompositeMapper.java
===================================================================
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.util;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
/**
* A <CODE>ContainerMapper</CODE> that unites the results of its constituent
* <CODE>FileNameMapper</CODE>s into a single set of result filenames.
*/
public class CompositeMapper extends ContainerMapper {
//inherit doc
public String[] mapFileName(String sourceFileName) {
HashSet results = new HashSet();
FileNameMapper mapper = null;
for (Iterator mIter = getMappers().iterator(); mIter.hasNext();) {
mapper = (FileNameMapper)(mIter.next());
if (mapper != null) {
String[] mapped = mapper.mapFileName(sourceFileName);
if (mapped != null) {
results.addAll(Arrays.asList(mapped));
}
}
}
return (results.size() == 0) ? null
: (String[]) results.toArray(new String[results.size()]);
}
}
1.17 +28 -34 ant/docs/manual/CoreTypes/mapper.html
Index: mapper.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/CoreTypes/mapper.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- mapper.html 11 Mar 2004 19:25:48 -0000 1.16
+++ mapper.html 22 Apr 2004 20:27:21 -0000 1.17
@@ -32,7 +32,7 @@
<tr>
<td valign="top">type</td>
<td valign="top">specifies one of the built-in implementations.</td>
- <td rowspan="2" align="center" valign="middle">Exactly one of both</td>
+ <td rowspan="2" align="center" valign="middle">Exactly one of these</td>
</tr>
<tr>
<td valign="top">classname</td>
@@ -62,12 +62,6 @@
implementation.</td>
<td align="center" valign="top">Depends on implementation.</td>
</tr>
- <tr>
- <td valign="top">chained</td>
- <td valign="top">Whether to chain nested <CODE><mapper></CODE>s.
- <i>Since Ant 1.7</i></td>
- <td align="center" valign="top">No, default is <CODE>false</CODE>.</td>
- </tr>
</table>
<p>Note that Ant will not automatically convert / or \ characters in
the <code>to</code> and <code>from</code> attributes to the correct
@@ -77,18 +71,17 @@
<p>The classpath can be specified via a nested
<code><classpath></code>, as well - that is,
a <a href="../using.html#path">path</a>-like structure.</p>
-<p><b>Since Ant 1.7,</b> nested File Mappers can
+<p><b>Since Ant 1.6.2,</b> nested File Mappers can
be supplied via either <CODE><mapper></CODE> elements or
<a href="../CoreTasks/typedef.html"><code><typedef></code></a>'d
implementations of <CODE>org.apache.tools.ant.util.FileNameMapper</CODE>.
-If one or more nested File Mappers are specified using either convention,
-only the <i>chained</i> attribute will be considered in the configuration
-of the implicitly used <a href="#container-mapper">container mapper</a>.
+If nested File Mappers are specified by either means, the mapper will be
+implicitly configured as a <a href="#composite-mapper">composite mapper</a>.
</p>
<hr/>
<h3>The built-in mapper types are:</h3>
<p>All built-in mappers are case-sensitive.</p>
-<p><b>As of Ant 1.7,</b> each of the built-in mapper implementation
+<p><b>As of Ant 1.6.2,</b> each of the built-in mapper implementation
types is directly accessible using a specific tagname. This makes it
possible for filename mappers to support attributes in addition to
the generally available <i>to</i> and <i>from</i>.<br/>
@@ -395,7 +388,7 @@
<td valign="top">ignored</td>
</tr>
</table>
-<h4><a name="unpackage-mapper">unpackage (since ant 1.6)</a></h4>
+<h4><a name="unpackage-mapper">unpackage (since ant 1.6.0)</a></h4>
<p>This mapper is the inverse of the <a href="#package-mapper">package</a>
mapper.
It replaces the dots in a package name with directory separators. This
is useful for matching XML formatter results against their JUnit test
@@ -417,22 +410,17 @@
<td valign="top"><code>${test.src.dir}/org/acme/AcmeTest.java</code></td>
</tr>
</table>
-<h4><a name="container-mapper">container (since ant 1.7)</a></h4>
- <p>This mapper implementation can contain multiple nested mappers,
- and can process in one of two modes, controlled by the <i>chained</i>
- attribute. In the default mode, file mapping is performed by passing
- the source filename to each nested <code><mapper></code>
in turn,
- returning all results. When <i>chained</i> is set to <CODE>true</CODE>,
- the source filename will be passed to the first nested mapper, its
- results will be passed to the second, and so on. The target filenames
- generated by the last nested mapper comprise the ultimate results of the
- mapping operation. The <i>to</i> and <i>from</i> attributes
are ignored.</p>
+<h4><a name="composite-mapper">composite (since ant 1.6.2)</a></h4>
+ <p>This mapper implementation can contain multiple nested mappers.
+ File mapping is performed by passing the source filename to each nested
+ <code><mapper></code> in turn, returning all results.
+ The <i>to</i> and <i>from</i> attributes are ignored.</p>
<b>Examples:</b>
<blockquote><pre>
-<containermapper>
+<compositemapper>
<identitymapper />
<packagemapper from="*.java" to="*"/>
-</containermapper>
+</compositemapper>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -447,15 +435,25 @@
<td valign="top"><code>foo.bar.A</code></td>
</tr>
</table>
+ <p>The composite mapper has no corresponding
+ <code><mapper <b>type</b>></code> attribute.
+ </p>
+<h4><a name="chained-mapper">chained (since ant 1.6.2)</a></h4>
+ <p>This mapper implementation can contain multiple nested mappers.
+ File mapping is performed by passing the source filename to the first
+ nested mapper, its results to the second, and so on. The target filenames
+ generated by the last nested mapper comprise the ultimate results of the
+ mapping operation. The <i>to</i> and <i>from</i> attributes
are ignored.</p>
+<b>Examples:</b>
<blockquote><pre>
-<mapper chained="true">
+<chainedmapper>
<flattenmapper />
<globmapper from="*" to="new/path/*"/>
<mapper>
<globmapper from="*" to="*1"/>
<globmapper from="*" to="*2"/>
</mapper>
-</mapper>
+</chainedmapper>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -477,13 +475,9 @@
<td valign="top"><code>new/path/B.java2</code></td>
</tr>
</table>
- <p>Finally, the container mapper is <b>not</b> built-in in the same
sense
- as the others. It is available via its own typedef,
- <code><containermapper></code>, and the use of a common
- <code><mapper></code> element with nested mappers will, as
mentioned
- previously, make implicit use of a container mapper. The container
- mapper is <b>not</b> available, however (nor does it need to be), using
- the common <code><mapper type="..."></code>
syntax.</p>
+ <p>The chained mapper has no corresponding
+ <code><mapper <b>type</b>></code> attribute.
+ </p>
<hr>
<p align="center">Copyright © 2000-2004 The Apache Software Foundation.
All rights
Reserved.</p>
1.28 +52 -51 ant/src/main/org/apache/tools/ant/types/Mapper.java
Index: Mapper.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/types/Mapper.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- Mapper.java 11 Mar 2004 19:25:48 -0000 1.27
+++ Mapper.java 22 Apr 2004 20:27:21 -0000 1.28
@@ -23,6 +23,7 @@
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.CompositeMapper;
import org.apache.tools.ant.util.ContainerMapper;
/**
@@ -31,16 +32,25 @@
*/
public class Mapper extends DataType implements Cloneable {
- protected MapperType type = null;
- private ContainerMapper container = null;
- private Boolean chained = null;
+ protected MapperType type = null;
+ protected String classname = null;
+ protected Path classpath = null;
+ protected String from = null;
+ protected String to = null;
+
+ private ContainerMapper container = null;
+ /**
+ * Construct a new <CODE>Mapper</CODE> element.
+ * @param p the owning Ant <CODE>Project</CODE>.
+ */
public Mapper(Project p) {
setProject(p);
}
/**
- * Set the type of FileNameMapper to use.
+ * Set the type of <code>FileNameMapper</code> to use.
+ * @param type the <CODE>MapperType</CODE> enumerated attribute.
*/
public void setType(MapperType type) {
if (isReference()) {
@@ -49,15 +59,26 @@
this.type = type;
}
- protected String classname = null;
-
/**
- * Add a nested filename mapper
- * @param fileNameMapper the mapper to add
+ * Add a nested <CODE>FileNameMapper</CODE>.
+ * @param fileNameMapper the <CODE>FileNameMapper</CODE> to add.
*/
public void add(FileNameMapper fileNameMapper) {
+ if (isReference()) {
+ throw noChildrenAllowed();
+ }
if (container == null) {
- container = new ContainerMapper();
+ if (type == null && classname == null) {
+ container = new CompositeMapper();
+ } else {
+ FileNameMapper m = getImplementation();
+ if (m instanceof ContainerMapper) {
+ container = (ContainerMapper)m;
+ } else {
+ throw new BuildException(String.valueOf(m)
+ + " mapper implementation does not support nested mappers!");
+ }
+ }
}
container.add(fileNameMapper);
}
@@ -69,16 +90,7 @@
public void addConfiguredMapper(Mapper mapper) {
add(mapper.getImplementation());
}
-
- /**
- * Set the chained attribute of the nested mapper container
- * @param chained the setting for the chained attribute of the
- * nested mapper container.
- */
- public void setChained(Boolean chained) {
- this.chained = chained;
- }
-
+
/**
* Set the class name of the FileNameMapper to use.
*/
@@ -89,8 +101,6 @@
this.classname = classname;
}
- protected Path classpath = null;
-
/**
* Set the classpath to load the FileNameMapper through (attribute).
*/
@@ -129,8 +139,6 @@
createClasspath().setRefid(r);
}
- protected String from = null;
-
/**
* Set the argument to FileNameMapper.setFrom
*/
@@ -141,8 +149,6 @@
this.from = from;
}
- protected String to = null;
-
/**
* Set the argument to FileNameMapper.setTo
*/
@@ -181,15 +187,6 @@
}
if (container != null) {
- if (type != null || classname != null ||
- to != null || from != null) {
- throw new BuildException(
- "for nested mappers, type, classname, to and from" +
- " attributes are not allowed");
- }
- if (chained != null) {
- container.setChained(chained.booleanValue());
- }
return container;
}
@@ -199,35 +196,39 @@
}
try {
- if (type != null) {
- classname = type.getImplementation();
- }
-
- Class c = null;
- if (classpath == null) {
- c = Class.forName(classname);
- } else {
- AntClassLoader al = getProject().createClassLoader(classpath);
- c = Class.forName(classname, true, al);
- }
-
- FileNameMapper m = (FileNameMapper) c.newInstance();
+ FileNameMapper m
+ = (FileNameMapper)(getImplementationClass().newInstance());
final Project project = getProject();
if (project != null) {
project.setProjectReference(m);
}
m.setFrom(from);
m.setTo(to);
+
return m;
} catch (BuildException be) {
throw be;
} catch (Throwable t) {
throw new BuildException(t);
- } finally {
- if (type != null) {
- classname = null;
- }
}
+ }
+
+ /**
+ * Gets the Class object associated with the mapper implementation.
+ * @return <CODE>Class</CODE>.
+ */
+ protected Class getImplementationClass() throws ClassNotFoundException {
+
+ String classname = this.classname;
+ if (type != null) {
+ classname = type.getImplementation();
+ }
+
+ ClassLoader loader = (classpath == null)
+ ? getClass().getClassLoader()
+ : getProject().createClassLoader(classpath);
+
+ return Class.forName(classname, true, loader);
}
/**
1.24 +2 -1 ant/src/main/org/apache/tools/ant/types/defaults.properties
Index: defaults.properties
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/types/defaults.properties,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- defaults.properties 27 Mar 2004 21:33:49 -0000 1.23
+++ defaults.properties 22 Apr 2004 20:27:21 -0000 1.24
@@ -16,7 +16,8 @@
regexpmapper=org.apache.tools.ant.util.RegexpPatternMapper
packagemapper=org.apache.tools.ant.util.PackageNameMapper
unpackagemapper=org.apache.tools.ant.util.UnPackageNameMapper
-containermapper=org.apache.tools.ant.util.ContainerMapper
+compositemapper=org.apache.tools.ant.util.CompositeMapper
+chainedmapper=org.apache.tools.ant.util.ChainedMapper
path=org.apache.tools.ant.types.Path
patternset=org.apache.tools.ant.types.PatternSet
1.15 +9 -9 ant/src/testcases/org/apache/tools/ant/types/MapperTest.java
Index: MapperTest.java
===================================================================
RCS file: /home/cvs/ant/src/testcases/org/apache/tools/ant/types/MapperTest.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- MapperTest.java 11 Mar 2004 19:25:48 -0000 1.14
+++ MapperTest.java 22 Apr 2004 20:27:21 -0000 1.15
@@ -140,7 +140,7 @@
assertEquals("a.class", result[0]);
}
- public void testContainer() {
+ public void testNested() {
Mapper mapper1 = new Mapper(project);
Mapper.MapperType mt = new Mapper.MapperType();
mt.setValue("glob");
@@ -171,7 +171,7 @@
list.contains("mergefile"));
}
- public void testChainedContainer() {
+ public void testChained() {
// a --> b --> c --- def
// \-- ghi
@@ -184,6 +184,7 @@
mapperBC.setFrom("b");
mapperBC.setTo("c");
+ //implicit composite
Mapper mapperCX = new Mapper(project);
FileNameMapper mapperDEF = new GlobPatternMapper();
@@ -197,20 +198,19 @@
mapperCX.add(mapperDEF);
mapperCX.add(mapperGHI);
- ContainerMapper chained = new ContainerMapper();
- chained.setChained(true);
+ Mapper chained = new Mapper(project);
+ chained.setClassname(ChainedMapper.class.getName());
chained.add(mapperAB);
chained.add(mapperBC);
chained.addConfiguredMapper(mapperCX);
- String[] targets = chained.mapFileName("a");
+ FileNameMapper fileNameMapper = chained.getImplementation();
+ String[] targets = fileNameMapper.mapFileName("a");
assertNotNull("no filenames mapped", targets);
assertEquals("wrong number of filenames mapped", 2, targets.length);
List list = Arrays.asList(targets);
- assertTrue("cannot find expected target \"def\"",
- list.contains("def"));
- assertTrue("cannot find expected target \"ghi\"",
- list.contains("ghi"));
+ assertTrue("cannot find expected target \"def\"", list.contains("def"));
+ assertTrue("cannot find expected target \"ghi\"", list.contains("ghi"));
}
public void testCopyTaskWithTwoFilesets() {
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org
|