| @@ -26,8 +26,13 @@ import java.util.Collections; | |||
| import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.NoSuchElementException; | |||
| import java.util.Optional; | |||
| import java.util.Spliterator; | |||
| import java.util.Spliterators; | |||
| import java.util.Stack; | |||
| import java.util.stream.Collectors; | |||
| import java.util.stream.Stream; | |||
| import java.util.stream.StreamSupport; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| @@ -61,10 +66,8 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| public static final Iterator<Resource> EMPTY_ITERATOR = Collections.emptyIterator(); | |||
| private class MyCollection extends AbstractCollection<Resource> { | |||
| private Collection<Resource> cached; | |||
| private volatile Collection<Resource> cached; | |||
| MyCollection() { | |||
| } | |||
| @Override | |||
| public int size() { | |||
| return getCache().size(); | |||
| @@ -74,45 +77,41 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| return getCache().iterator(); | |||
| } | |||
| private synchronized Collection<Resource> getCache() { | |||
| Collection<Resource> coll = cached; | |||
| if (coll == null) { | |||
| coll = new ArrayList<>(); | |||
| new MyIterator().forEachRemaining(coll::add); | |||
| if (cache) { | |||
| cached = coll; | |||
| } | |||
| if (cached == null) { | |||
| cached = internalResources().collect(Collectors.toList()); | |||
| } | |||
| return coll; | |||
| return cached; | |||
| } | |||
| private class MyIterator implements Iterator<Resource> { | |||
| private Iterator<ResourceCollection> rci = getNested().iterator(); | |||
| private Iterator<Resource> ri = null; | |||
| } | |||
| @Override | |||
| public boolean hasNext() { | |||
| boolean result = ri != null && ri.hasNext(); | |||
| while (!result && rci.hasNext()) { | |||
| ri = rci.next().iterator(); | |||
| result = ri.hasNext(); | |||
| } | |||
| return result; | |||
| } | |||
| @Override | |||
| public Resource next() { | |||
| if (!hasNext()) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| return ri.next(); | |||
| private class MyIterator implements Iterator<Resource> { | |||
| private Iterator<ResourceCollection> rci = getNested().iterator(); | |||
| private Iterator<Resource> ri; | |||
| @Override | |||
| public boolean hasNext() { | |||
| boolean result = ri != null && ri.hasNext(); | |||
| while (!result && rci.hasNext()) { | |||
| ri = rci.next().iterator(); | |||
| result = ri.hasNext(); | |||
| } | |||
| @Override | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| return result; | |||
| } | |||
| @Override | |||
| public Resource next() { | |||
| if (!hasNext()) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| return ri.next(); | |||
| } | |||
| @Override | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| } | |||
| private List<ResourceCollection> rc; | |||
| private Collection<Resource> coll; | |||
| private Optional<Collection<Resource>> cacheColl = Optional.empty(); | |||
| private volatile boolean cache = false; | |||
| /** | |||
| @@ -156,7 +155,7 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| } | |||
| rc.add(c); | |||
| invalidateExistingIterators(); | |||
| coll = null; | |||
| cacheColl = Optional.empty(); | |||
| setChecked(false); | |||
| } | |||
| @@ -170,7 +169,7 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| return getRef().iterator(); | |||
| } | |||
| validate(); | |||
| return new FailFast(this, coll.iterator()); | |||
| return new FailFast(this, cacheColl.map(Iterable::iterator).orElseGet(MyIterator::new)); | |||
| } | |||
| /** | |||
| @@ -183,7 +182,7 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| return getRef().size(); | |||
| } | |||
| validate(); | |||
| return coll.size(); | |||
| return cacheColl.isPresent() ? cacheColl.get().size() : (int) internalResources().count(); | |||
| } | |||
| /** | |||
| @@ -196,8 +195,7 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| return getRef().isFilesystemOnly(); | |||
| } | |||
| validate(); | |||
| return getNested().stream() | |||
| .allMatch(ResourceCollection::isFilesystemOnly); | |||
| return getNested().stream().allMatch(ResourceCollection::isFilesystemOnly); | |||
| } | |||
| /** | |||
| @@ -210,11 +208,8 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| return getRef().toString(); | |||
| } | |||
| validate(); | |||
| if (coll == null || coll.isEmpty()) { | |||
| return ""; | |||
| } | |||
| return coll.stream().map(Object::toString) | |||
| .collect(Collectors.joining(File.pathSeparator)); | |||
| final Stream<?> stream = cache ? cacheColl.get().stream() : getNested().stream(); | |||
| return stream.map(String::valueOf).collect(Collectors.joining(File.pathSeparator)); | |||
| } | |||
| /** | |||
| @@ -227,17 +222,13 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| @Override | |||
| protected void dieOnCircularReference(Stack<Object> stk, Project p) | |||
| throws BuildException { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| if (isReference()) { | |||
| super.dieOnCircularReference(stk, p); | |||
| } else { | |||
| for (ResourceCollection resourceCollection : getNested()) { | |||
| if (resourceCollection instanceof DataType) { | |||
| pushAndInvokeCircularReferenceCheck((DataType) resourceCollection, stk, p); | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| if (!isChecked()) { | |||
| getNested().stream().filter(DataType.class::isInstance).map(DataType.class::cast) | |||
| .forEach(dt -> pushAndInvokeCircularReferenceCheck(dt, stk, p)); | |||
| setChecked(true); | |||
| } | |||
| } | |||
| @@ -259,10 +250,17 @@ public class Resources extends DataType implements AppendableResourceCollection | |||
| private synchronized void validate() { | |||
| dieOnCircularReference(); | |||
| coll = (coll == null) ? new MyCollection() : coll; | |||
| if (cache && !cacheColl.isPresent()) { | |||
| cacheColl = Optional.of(new MyCollection()); | |||
| } | |||
| } | |||
| private synchronized List<ResourceCollection> getNested() { | |||
| return rc == null ? Collections.emptyList() : rc; | |||
| } | |||
| private synchronized Stream<Resource> internalResources() { | |||
| return StreamSupport.stream( | |||
| Spliterators.spliteratorUnknownSize(new MyIterator(), Spliterator.NONNULL), false); | |||
| } | |||
| } | |||