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]