mbenson 2004/03/11 11:25:48
Modified: . WHATSNEW
src/main/org/apache/tools/ant/types Mapper.java
defaults.properties
src/testcases/org/apache/tools/ant/types MapperTest.java
docs/manual/CoreTypes mapper.html
Added: src/main/org/apache/tools/ant/util ContainerMapper.java
Log:
Nested file mappers; container mapper.
PR: 26364
Revision Changes Path
1.1
ant/src/main/org/apache/tools/ant/util/ContainerMapper.java
Index: ContainerMapper.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.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.util.FileNameMapper;
/**
* A filenamemapper that contains other filename mappers.
* The mappers proceeded in a chain or separately.
* @see 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.
*/
public void add(FileNameMapper fileNameMapper) {
mappers.add(fileNameMapper);
}
/**
* Add a Mapper
* @param mapper the mapper to add
*/
public void addConfiguredMapper(Mapper mapper) {
mappers.add(mapper.getImplementation());
}
/**
* 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.
*/
public void setChained(boolean chained) {
this.chained = chained;
}
/**
* This method is ignored, present to fullfill the FileNameMapper
* interface.
* @param ignore this parameter is ignored.
*/
public void setFrom(String ignore) {
}
/**
* This method is ignored, present to fullfill the FileNameMapper
* interface.
* @param ignore this parameter is ignored.
*/
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.569 +5 -0 ant/WHATSNEW
Index: WHATSNEW
===================================================================
RCS file: /home/cvs/ant/WHATSNEW,v
retrieving revision 1.568
retrieving revision 1.569
diff -u -r1.568 -r1.569
--- WHATSNEW 11 Mar 2004 11:22:10 -0000 1.568
+++ WHATSNEW 11 Mar 2004 19:25:48 -0000 1.569
@@ -41,6 +41,11 @@
a granularity of two seconds). The default remains to round up.
Bugzilla Report 17934.
+* Nested file mappers and a container mapper implementation have been
+ introduced. Additionally, the <mapper> element now accepts "defined"
+ nested FileNameMapper implementations directly, allowing a usage
+ comparable to those of <condition>, <filter>, and <selector>.
+
Changes from Ant 1.6.1 to current Ant 1.6 CVS version
=============================================
1.27 +51 -4 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.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- Mapper.java 9 Mar 2004 16:48:41 -0000 1.26
+++ Mapper.java 11 Mar 2004 19:25:48 -0000 1.27
@@ -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.ContainerMapper;
/**
* Element to define a FileNameMapper.
@@ -30,7 +31,9 @@
*/
public class Mapper extends DataType implements Cloneable {
- protected MapperType type = null;
+ protected MapperType type = null;
+ private ContainerMapper container = null;
+ private Boolean chained = null;
public Mapper(Project p) {
setProject(p);
@@ -49,6 +52,34 @@
protected String classname = null;
/**
+ * Add a nested filename mapper
+ * @param fileNameMapper the mapper to add
+ */
+ public void add(FileNameMapper fileNameMapper) {
+ if (container == null) {
+ container = new ContainerMapper();
+ }
+ container.add(fileNameMapper);
+ }
+
+ /**
+ * Add a Mapper
+ * @param mapper the mapper to add
+ */
+ 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.
*/
public void setClassname(String classname) {
@@ -143,12 +174,28 @@
return getRef().getImplementation();
}
- if (type == null && classname == null) {
- throw new BuildException("one of the attributes type or
classname is required");
+ if (type == null && classname == null && container == null) {
+ throw new BuildException(
+ "nested mapper or "
+ + "one of the attributes type or classname is required");
+ }
+
+ 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;
}
if (type != null && classname != null) {
- throw new BuildException("must not specify both type and
classname attribute");
+ throw new BuildException(
+ "must not specify both type and classname attribute");
}
try {
1.22 +10 -0
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.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- defaults.properties 23 Dec 2003 11:07:00 -0000 1.21
+++ defaults.properties 11 Mar 2004 19:25:48 -0000 1.22
@@ -7,6 +7,16 @@
filterreader=org.apache.tools.ant.types.AntFilterReader
filterset=org.apache.tools.ant.types.FilterSet
mapper=org.apache.tools.ant.types.Mapper
+# different filename mappers
+identitymapper=org.apache.tools.ant.util.IdentityMapper
+flattenmapper=org.apache.tools.ant.util.FlatFileNameMapper
+globmapper=org.apache.tools.ant.util.GlobPatternMapper
+mergemapper=org.apache.tools.ant.util.MergingMapper
+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
+
path=org.apache.tools.ant.types.Path
patternset=org.apache.tools.ant.types.PatternSet
regexp=org.apache.tools.ant.types.RegularExpression
1.14 +75 -0
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.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- MapperTest.java 9 Mar 2004 16:49:05 -0000 1.13
+++ MapperTest.java 11 Mar 2004 19:25:48 -0000 1.14
@@ -26,6 +26,8 @@
import junit.framework.AssertionFailedError;
import java.io.File;
+import java.util.List;
+import java.util.Arrays;
/**
* JUnit 3 testcases for org.apache.tools.ant.types.Mapper.
@@ -136,6 +138,79 @@
String[] result = fmm.mapFileName("a.java");
assertEquals("a.java should match", 1, result.length);
assertEquals("a.class", result[0]);
+ }
+
+ public void testContainer() {
+ Mapper mapper1 = new Mapper(project);
+ Mapper.MapperType mt = new Mapper.MapperType();
+ mt.setValue("glob");
+ mapper1.setType(mt);
+ mapper1.setFrom("from*");
+ mapper1.setTo("to*");
+
+ //mix element types
+ FileNameMapper mapper2 = new FlatFileNameMapper();
+ FileNameMapper mapper3 = new MergingMapper();
+ mapper3.setTo("mergefile");
+
+ Mapper container = new Mapper(project);
+ container.addConfiguredMapper(mapper1);
+ container.add(mapper2);
+ container.add(mapper3);
+
+ FileNameMapper fileNameMapper = container.getImplementation();
+ String[] targets = fileNameMapper.mapFileName("fromfilename");
+ assertNotNull("no filenames mapped", targets);
+ assertEquals("wrong number of filenames mapped", 3, targets.length);
+ List list = Arrays.asList(targets);
+ assertTrue("cannot find expected target \"tofilename\"",
+ list.contains("tofilename"));
+ assertTrue("cannot find expected target \"fromfilename\"",
+ list.contains("fromfilename"));
+ assertTrue("cannot find expected target \"mergefile\"",
+ list.contains("mergefile"));
+ }
+
+ public void testChainedContainer() {
+
+ // a --> b --> c --- def
+ // \-- ghi
+
+ FileNameMapper mapperAB = new GlobPatternMapper();
+ mapperAB.setFrom("a");
+ mapperAB.setTo("b");
+
+ FileNameMapper mapperBC = new GlobPatternMapper();
+ mapperBC.setFrom("b");
+ mapperBC.setTo("c");
+
+ Mapper mapperCX = new Mapper(project);
+
+ FileNameMapper mapperDEF = new GlobPatternMapper();
+ mapperDEF.setFrom("c");
+ mapperDEF.setTo("def");
+
+ FileNameMapper mapperGHI = new GlobPatternMapper();
+ mapperGHI.setFrom("c");
+ mapperGHI.setTo("ghi");
+
+ mapperCX.add(mapperDEF);
+ mapperCX.add(mapperGHI);
+
+ ContainerMapper chained = new ContainerMapper();
+ chained.setChained(true);
+ chained.add(mapperAB);
+ chained.add(mapperBC);
+ chained.addConfiguredMapper(mapperCX);
+
+ String[] targets = chained.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"));
}
public void testCopyTaskWithTwoFilesets() {
1.16 +100 -5 ant/docs/manual/CoreTypes/mapper.html
Index: mapper.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/CoreTypes/mapper.html,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- mapper.html 9 Feb 2004 21:50:07 -0000 1.15
+++ mapper.html 11 Mar 2004 19:25:48 -0000 1.16
@@ -62,6 +62,12 @@
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
@@ -71,14 +77,30 @@
<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
+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>.
+</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
+ 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/>
+ The <code><mapper type|classname="..."></code> usage
+ form remains valid for reasons of backward compatibility.</p>
<h4><a name="identity-mapper">identity</a></h4>
<p>The target file name is identical to the source file name. Both
<code>to</code> and <code>from</code> will be ignored.</p>
<b>Examples:</b>
<blockquote><pre>
<mapper type="identity"/>
+<identitymapper />
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -109,6 +131,7 @@
<b>Examples:</b>
<blockquote><pre>
<mapper type="flatten"/>
+<flattenmapper />
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -138,6 +161,7 @@
<h5>Examples:</h5>
<blockquote><pre>
<mapper type="merge" to="archive.tar"/>
+<mergemapper to="archive.tar"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -172,6 +196,7 @@
<b>Examples:</b>
<blockquote><pre>
<mapper type="glob" from="*.java"
to="*.java.bak"/>
+<globmapper from="*.java" to="*.java.bak"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -197,6 +222,7 @@
</table>
<blockquote><pre>
<mapper type="glob" from="C*ies"
to="Q*y"/>
+<globmapper from="C*ies" to="Q*y"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -267,6 +293,7 @@
<b>Examples:</b>
<blockquote><pre>
<mapper type="regexp" from="^(.*)\.java$$"
to="\1.java.bak"/>
+<regexpmapper from="^(.*)\.java$$"
to="\1.java.bak"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -292,6 +319,7 @@
</table>
<blockquote><pre>
<mapper type="regexp" from="^(.*)/([^/]+)/([^/]*)$$"
to="\1/\2/\2-\3"/>
+<regexpmapper from="^(.*)/([^/]+)/([^/]*)$$"
to="\1/\2/\2-\3"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -317,6 +345,7 @@
</table>
<blockquote><pre>
<mapper type="regexp" from="^(.*)\.(.*)$$"
to="\2.\1"/>
+<regexpmapper from="^(.*)\.(.*)$$" to="\2.\1"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -349,8 +378,8 @@
with <code><uptodate></code> and <code><junit></code> output.</p>
<b>Example:</b>
<blockquote><pre>
-<mapper type="package"
- from="*Test.java" to="TEST-*Test.xml"/>
+<mapper type="package" from="*Test.java" to="TEST-*Test.xml"/>
+<packagemapper from="*Test.java" to="TEST-*Test.xml"/>
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -375,8 +404,8 @@
</p>
<b>Example:</b>
<blockquote><pre>
-<mapper type="unpackage"
- from="TEST-*Test.xml" to="${test.src.dir}/*Test.java">
+<mapper type="unpackage" from="TEST-*Test.xml"
to="${test.src.dir}/*Test.java">
+<unpackagemapper from="TEST-*Test.xml" to="${test.src.dir}/*Test.java">
</pre></blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -388,7 +417,73 @@
<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>
+<b>Examples:</b>
+<blockquote><pre>
+<containermapper>
+ <identitymapper />
+ <packagemapper from="*.java" to="*"/>
+</containermapper>
+</pre></blockquote>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Source file name</b></td>
+ <td valign="top"><b>Target file names</b></td>
+ </tr>
+ <tr>
+ <td valign="center" rowspan="2"><code>foo/bar/A.java</code></td>
+ <td valign="top"><code>foo/bar/A.java</code></td>
+ </tr>
+ <tr>
+ <td valign="top"><code>foo.bar.A</code></td>
+ </tr>
+</table>
+<blockquote><pre>
+<mapper chained="true">
+ <flattenmapper />
+ <globmapper from="*" to="new/path/*"/>
+ <mapper>
+ <globmapper from="*" to="*1"/>
+ <globmapper from="*" to="*2"/>
+ </mapper>
+</mapper>
+</pre></blockquote>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Source file name</b></td>
+ <td valign="top"><b>Target file names</b></td>
+ </tr>
+ <tr>
+ <td valign="center" rowspan="2"><code>foo/bar/A.java</code></td>
+ <td valign="top"><code>new/path/A.java1</code></td>
+ </tr>
+ <tr>
+ <td valign="top"><code>new/path/A.java2</code></td>
+ </tr>
+ <tr>
+ <td valign="center" rowspan="2"><code>boo/far/B.java</code></td>
+ <td valign="top"><code>new/path/B.java1</code></td>
+ </tr>
+ <tr>
+ <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>
<hr>
<p align="center">Copyright © 2000-2004 The Apache Software Foundation.
All rights
Reserved.</p>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]