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&mdash;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"));
+    }
+}

Reply via email to