This is an automated email from the ASF dual-hosted git repository. bodewig pushed a commit to branch property-enumerator in repository https://gitbox.apache.org/repos/asf/ant.git
commit 0bd346c5c36d939959e5616cf22ae9408ee52c69 Author: Stefan Bodewig <[email protected]> AuthorDate: Sun Aug 2 15:11:05 2020 +0200 add a PropertyEnumerator delegate to better support PropertySet --- manual/properties.html | 14 ++++++ src/main/org/apache/tools/ant/Project.java | 14 +++++- src/main/org/apache/tools/ant/PropertyHelper.java | 28 ++++++++++- .../apache/tools/ant/property/LocalProperties.java | 9 +++- .../tools/ant/property/LocalPropertyStack.java | 18 +++++++ .../org/apache/tools/ant/PropertyHelperTest.java | 55 ++++++++++++++++++++++ 6 files changed, 133 insertions(+), 5 deletions(-) diff --git a/manual/properties.html b/manual/properties.html index c058af9..22476c4 100644 --- a/manual/properties.html +++ b/manual/properties.html @@ -154,6 +154,20 @@ this would be <code class="code">org.apache.tools.ant.property.LocalProperties</code> which implements storage for <a href="Tasks/local.html">local properties</a>.</p> </li> + + <li><code class="code">org.apache.tools.ant.PropertyHelper$PropertyEnumerator</code> + is responsible for enumerating property names. + + <p>This is the interface you'd implement if you want to provide + your own storage independent of Ant's project + instance—the interface represents part of the reading + end. An example for this would + be <code class="code">org.apache.tools.ant.property.LocalProperties</code> + which implements storage for <a href="Tasks/local.html">local + properties</a>.</p> + + <p><em>This interface has been added with Ant 1.10.9.</em></p> + </li> </ul> <p>The default <code class="code">PropertyExpander</code> looks similar to:</p> diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index 3f34736..6104e53 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -642,14 +642,24 @@ public class Project implements ResourceFactory { /** * Return a copy of the properties table. - * @return a hashtable containing all properties - * (including user properties). + * @return a hashtable containing all properties (including user + * properties) known to the project directly, does not + * contain local properties. */ public Hashtable<String, Object> getProperties() { return PropertyHelper.getPropertyHelper(this).getProperties(); } /** + * Returns the names of all known properties. + * @since 1.10.9 + * @return the names of all known properties including local user and local properties. + */ + public Set<String> getPropertyNames() { + return PropertyHelper.getPropertyHelper(this).getPropertyNames(); + } + + /** * Return a copy of the user property hashtable. * @return a hashtable containing just the user properties. */ diff --git a/src/main/org/apache/tools/ant/PropertyHelper.java b/src/main/org/apache/tools/ant/PropertyHelper.java index 154ffdf..53ec6ee 100644 --- a/src/main/org/apache/tools/ant/PropertyHelper.java +++ b/src/main/org/apache/tools/ant/PropertyHelper.java @@ -161,7 +161,19 @@ public class PropertyHelper implements GetProperty { String property, Object value, PropertyHelper propertyHelper); } - //TODO PropertyEnumerator Delegate type, would improve PropertySet + /** + * Obtains the names of all known properties. + * + * @since 1.10.9 + */ + public interface PropertyEnumerator extends Delegate { + /** + * Returns the names of all properties known to this delegate. + * + * @return the names of all properties known to this delegate. + */ + Set<String> getPropertyNames(); + } // -------------------------------------------------------- // @@ -843,6 +855,18 @@ public class PropertyHelper implements GetProperty { } /** + * Returns the names of all known properties. + * @since 1.10.9 + * @return the names of all known properties. + */ + public Set<String> getPropertyNames() { + final Set<String> names = new HashSet<>(properties.keySet()); + getDelegates(PropertyEnumerator.class) + .forEach(e -> names.addAll(e.getPropertyNames())); + return Collections.unmodifiableSet(names); + } + + /** * Returns the value of a user property, if it is set. * * <p>Delegates to the one-arg version ignoring the ns parameter.</p> @@ -1014,7 +1038,7 @@ public class PropertyHelper implements GetProperty { // Moved from ProjectHelper. You can override the static method - // this is used for backward compatibility (for code that calls // the parse method in ProjectHelper). - + /** * Default parsing method. It is here only to support backward compatibility * for the static ProjectHelper.parsePropertyString(). diff --git a/src/main/org/apache/tools/ant/property/LocalProperties.java b/src/main/org/apache/tools/ant/property/LocalProperties.java index 1dcbc26..327f978 100644 --- a/src/main/org/apache/tools/ant/property/LocalProperties.java +++ b/src/main/org/apache/tools/ant/property/LocalProperties.java @@ -21,6 +21,8 @@ import org.apache.tools.ant.MagicNames; import org.apache.tools.ant.Project; import org.apache.tools.ant.PropertyHelper; +import java.util.Set; + /** * Thread local class containing local properties. * @since Ant 1.8.0 @@ -28,7 +30,7 @@ import org.apache.tools.ant.PropertyHelper; public class LocalProperties extends InheritableThreadLocal<LocalPropertyStack> implements PropertyHelper.PropertyEvaluator, - PropertyHelper.PropertySetter { + PropertyHelper.PropertySetter, PropertyHelper.PropertyEnumerator { /** * Get a localproperties for the given project. @@ -147,4 +149,9 @@ public class LocalProperties String property, Object value, PropertyHelper propertyHelper) { return get().set(property, value, propertyHelper); } + + @Override + public Set<String> getPropertyNames() { + return get().getPropertyNames(); + } } diff --git a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java index 3b80b43..95b301f 100644 --- a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java +++ b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java @@ -17,10 +17,14 @@ */ package org.apache.tools.ant.property; +import java.util.Collections; import java.util.Deque; +import java.util.HashSet; import java.util.LinkedList; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collector; import org.apache.tools.ant.PropertyHelper; @@ -148,6 +152,20 @@ public class LocalPropertyStack { return true; } + /** + * Returns the names of all known local properties. + * @since 1.10.9 + * @return the names of all known local properties. + */ + public Set<String> getPropertyNames() { + final Set<String> names = stack.stream().map(Map::keySet) + .collect(Collector.of(() -> new HashSet<String>(), + (ns, ks) -> ns.addAll(ks), + (ns1, ns2) -> { ns1.addAll(ns2); return ns1; }, + Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); + return Collections.unmodifiableSet(names); + } + private Map<String, Object> getMapForProperty(String property) { synchronized (LOCK) { for (Map<String, Object> map : stack) { diff --git a/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java new file mode 100644 index 0000000..883e5f1 --- /dev/null +++ b/src/tests/junit/org/apache/tools/ant/PropertyHelperTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * https://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; + +import org.apache.tools.ant.property.LocalProperties; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class PropertyHelperTest { + + @Test + public void findsPropertyNamesSetDirectly() { + Project p = new Project(); + p.setNewProperty("foo", "bar"); + assertTrue(p.getPropertyNames().contains("foo")); + } + + @Test + public void findsPropertyNamesSetForLocalProperties() { + Project p = new Project(); + p.setNewProperty("foo", "bar"); + + LocalProperties localProperties = LocalProperties.get(p); + localProperties.enterScope(); + localProperties.addLocal("baz"); + p.setNewProperty("baz", "xyzzy"); + + assertTrue(p.getPropertyNames().contains("foo")); + assertTrue(p.getPropertyNames().contains("baz")); + assertTrue(p.getProperties().keySet().contains("foo")); + assertFalse(p.getProperties().keySet().contains("baz")); + localProperties.exitScope(); + + assertTrue(p.getPropertyNames().contains("foo")); + assertFalse(p.getPropertyNames().contains("baz")); + } +}
