| @@ -285,6 +285,7 @@ Matthew Watson | |||||
| Matthew Yanos | Matthew Yanos | ||||
| Matthias Bhend | Matthias Bhend | ||||
| Matthias Gutheil | Matthias Gutheil | ||||
| Matthias Johann Vill | |||||
| Michael Bayne | Michael Bayne | ||||
| Michael Clarke | Michael Clarke | ||||
| Michael Davey | Michael Davey | ||||
| @@ -1183,6 +1183,11 @@ | |||||
| <first>Matthias</first> | <first>Matthias</first> | ||||
| <last>Gutheil</last> | <last>Gutheil</last> | ||||
| </name> | </name> | ||||
| <name> | |||||
| <first>Matthias</first> | |||||
| <middle>Johann</middle> | |||||
| <last>Vill</last> | |||||
| </name> | |||||
| <name> | <name> | ||||
| <first>Michael</first> | <first>Michael</first> | ||||
| <last>Bayne</last> | <last>Bayne</last> | ||||
| @@ -1419,6 +1419,14 @@ of <a href="filelist.html"><code><filelist></code></a>.</p> | |||||
| </td> | </td> | ||||
| <td>No</td> | <td>No</td> | ||||
| </tr> | </tr> | ||||
| <tr> | |||||
| <td>preserveduplicates</td> | |||||
| <td>Makes this <code>resourcelist</code> return all resources as | |||||
| many times as they are specified. Otherwise | |||||
| <code>resourcelist</code> will only return each resource, in the | |||||
| order they first appear. <em>Since Ant 1.10.10</em></td> | |||||
| <td>No</td> | |||||
| </tr> | |||||
| <tr> | <tr> | ||||
| <td>refid</td> | <td>refid</td> | ||||
| <td>Makes this <code>resourcelist</code> | <td>Makes this <code>resourcelist</code> | ||||
| @@ -0,0 +1,21 @@ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * Interface describing a collection of Resources, to which elements can be | |||||
| * appended. | |||||
| * | |||||
| * @since Ant 1.10.10 | |||||
| */ | |||||
| public interface AppendableResourceCollection extends ResourceCollection { | |||||
| /** | |||||
| Add a ResourceCollection to the container. | |||||
| @param c the ResourceCollection to add. | |||||
| @throws BuildException on error. | |||||
| @since Ant 1.10.10 | |||||
| */ | |||||
| void add(ResourceCollection c) throws BuildException; | |||||
| } | |||||
| @@ -37,7 +37,7 @@ import org.apache.tools.ant.types.ResourceCollection; | |||||
| * @since Ant 1.7 | * @since Ant 1.7 | ||||
| */ | */ | ||||
| public abstract class BaseResourceCollectionContainer | public abstract class BaseResourceCollectionContainer | ||||
| extends DataType implements ResourceCollection, Cloneable { | |||||
| extends DataType implements AppendableResourceCollection, Cloneable { | |||||
| private List<ResourceCollection> rc = new ArrayList<>(); | private List<ResourceCollection> rc = new ArrayList<>(); | ||||
| private Collection<Resource> coll = null; | private Collection<Resource> coll = null; | ||||
| private boolean cache = true; | private boolean cache = true; | ||||
| @@ -92,6 +92,7 @@ public abstract class BaseResourceCollectionContainer | |||||
| * @param c the ResourceCollection to add. | * @param c the ResourceCollection to add. | ||||
| * @throws BuildException on error. | * @throws BuildException on error. | ||||
| */ | */ | ||||
| @Override | |||||
| public synchronized void add(ResourceCollection c) throws BuildException { | public synchronized void add(ResourceCollection c) throws BuildException { | ||||
| if (isReference()) { | if (isReference()) { | ||||
| throw noChildrenAllowed(); | throw noChildrenAllowed(); | ||||
| @@ -47,14 +47,10 @@ import org.apache.tools.ant.types.ResourceCollection; | |||||
| public class ResourceList extends DataType implements ResourceCollection { | public class ResourceList extends DataType implements ResourceCollection { | ||||
| private final Vector<FilterChain> filterChains = new Vector<>(); | private final Vector<FilterChain> filterChains = new Vector<>(); | ||||
| private final ArrayList<ResourceCollection> textDocuments = new ArrayList<>(); | private final ArrayList<ResourceCollection> textDocuments = new ArrayList<>(); | ||||
| private final Union cachedResources = new Union(); | |||||
| private volatile boolean cached = false; | |||||
| private AppendableResourceCollection cachedResources = null; | |||||
| private String encoding = null; | private String encoding = null; | ||||
| private File baseDir; | private File baseDir; | ||||
| public ResourceList() { | |||||
| cachedResources.setCache(true); | |||||
| } | |||||
| private boolean preserveDuplicates = false; | |||||
| /** | /** | ||||
| * Adds a source. | * Adds a source. | ||||
| @@ -116,6 +112,22 @@ public class ResourceList extends DataType implements ResourceCollection { | |||||
| this.baseDir = baseDir; | this.baseDir = baseDir; | ||||
| } | } | ||||
| /** | |||||
| * Makes this <code>resourcelist</code> return all resources as | |||||
| * many times as they are specified. Otherwise | |||||
| * <code>resourcelist</code> will only return each resource, in the | |||||
| * order they first appear. | |||||
| * | |||||
| * @param preserveDuplicates boolean | |||||
| * @since Ant 1.10.10 | |||||
| */ | |||||
| public final void setPreserveDuplicates(boolean preserveDuplicates) { | |||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| this.preserveDuplicates = preserveDuplicates; | |||||
| } | |||||
| /** | /** | ||||
| * Makes this instance in effect a reference to another ResourceList | * Makes this instance in effect a reference to another ResourceList | ||||
| * instance. | * instance. | ||||
| @@ -207,20 +219,31 @@ public class ResourceList extends DataType implements ResourceCollection { | |||||
| return getCheckedRef(ResourceList.class); | return getCheckedRef(ResourceList.class); | ||||
| } | } | ||||
| private AppendableResourceCollection newResourceCollection() { | |||||
| if (preserveDuplicates) { | |||||
| final Resources resources = new Resources(); | |||||
| resources.setCache(true); | |||||
| return resources; | |||||
| } else { | |||||
| final Union union = new Union(); | |||||
| union.setCache(true); | |||||
| return union; | |||||
| } | |||||
| } | |||||
| private synchronized ResourceCollection cache() { | private synchronized ResourceCollection cache() { | ||||
| if (!cached) { | |||||
| if (cachedResources == null) { | |||||
| dieOnCircularReference(); | dieOnCircularReference(); | ||||
| this.cachedResources = newResourceCollection(); | |||||
| textDocuments.stream().flatMap(ResourceCollection::stream) | textDocuments.stream().flatMap(ResourceCollection::stream) | ||||
| .map(this::read).forEach(cachedResources::add); | .map(this::read).forEach(cachedResources::add); | ||||
| cached = true; | |||||
| } | } | ||||
| return cachedResources; | return cachedResources; | ||||
| } | } | ||||
| private ResourceCollection read(Resource r) { | private ResourceCollection read(Resource r) { | ||||
| try (BufferedReader reader = new BufferedReader(open(r))) { | try (BufferedReader reader = new BufferedReader(open(r))) { | ||||
| Union streamResources = new Union(); | |||||
| streamResources.setCache(true); | |||||
| final AppendableResourceCollection streamResources = newResourceCollection(); | |||||
| reader.lines().map(this::parse).forEach(streamResources::add); | reader.lines().map(this::parse).forEach(streamResources::add); | ||||
| return streamResources; | return streamResources; | ||||
| } catch (final IOException ioe) { | } catch (final IOException ioe) { | ||||
| @@ -40,7 +40,7 @@ import org.apache.tools.ant.types.ResourceCollection; | |||||
| * making no attempt to remove duplicates, or references another ResourceCollection. | * making no attempt to remove duplicates, or references another ResourceCollection. | ||||
| * @since Ant 1.7 | * @since Ant 1.7 | ||||
| */ | */ | ||||
| public class Resources extends DataType implements ResourceCollection { | |||||
| public class Resources extends DataType implements AppendableResourceCollection { | |||||
| /** static empty ResourceCollection */ | /** static empty ResourceCollection */ | ||||
| public static final ResourceCollection NONE = new ResourceCollection() { | public static final ResourceCollection NONE = new ResourceCollection() { | ||||
| @Override | @Override | ||||
| @@ -156,6 +156,7 @@ public class Resources extends DataType implements ResourceCollection { | |||||
| * Add a ResourceCollection. | * Add a ResourceCollection. | ||||
| * @param c the ResourceCollection to add. | * @param c the ResourceCollection to add. | ||||
| */ | */ | ||||
| @Override | |||||
| public synchronized void add(ResourceCollection c) { | public synchronized void add(ResourceCollection c) { | ||||
| if (isReference()) { | if (isReference()) { | ||||
| throw noChildrenAllowed(); | throw noChildrenAllowed(); | ||||
| @@ -101,4 +101,41 @@ ${input}/c.txt</echo> | |||||
| </copy> | </copy> | ||||
| <au:assertFileExists file="${output}/antlib.xml"/> | <au:assertFileExists file="${output}/antlib.xml"/> | ||||
| </target> | </target> | ||||
| <target name="testDuplicatesRemoved" depends="setUp"> | |||||
| <echo file="${input}/a.txt">${input}/b.txt | |||||
| ${input}/b.txt</echo> | |||||
| <echo file="${input}/b.txt">Demo content</echo> | |||||
| <echo file="${input}/c.txt">${input}/b.txt | |||||
| ${input}/b.txt</echo> | |||||
| <pathconvert property="1b" pathsep="|" preserveduplicates="true"> | |||||
| <flattenmapper/> | |||||
| <resourcelist> | |||||
| <resources> | |||||
| <file file="${input}/a.txt"/> | |||||
| <file file="${input}/c.txt"/> | |||||
| </resources> | |||||
| </resourcelist> | |||||
| </pathconvert> | |||||
| <au:assertPropertyEquals name="1b" value="b.txt"/> | |||||
| </target> | |||||
| <target name="testDuplicatesPreserved" depends="setUp"> | |||||
| <echo file="${input}/a.txt">${input}/b.txt | |||||
| ${input}/b.txt</echo> | |||||
| <echo file="${input}/b.txt">Demo content</echo> | |||||
| <echo file="${input}/c.txt">${input}/b.txt | |||||
| ${input}/b.txt</echo> | |||||
| <pathconvert property="4bs" pathsep="|" preserveduplicates="true"> | |||||
| <flattenmapper/> | |||||
| <resourcelist preserveduplicates="true"> | |||||
| <resources> | |||||
| <file file="${input}/a.txt"/> | |||||
| <file file="${input}/a.txt"/> | |||||
| <file file="${input}/c.txt"/> | |||||
| </resources> | |||||
| </resourcelist> | |||||
| </pathconvert> | |||||
| <au:assertPropertyEquals name="4bs" value="b.txt|b.txt|b.txt|b.txt|b.txt|b.txt"/> | |||||
| </target> | |||||
| </project> | </project> | ||||