You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/06/27 14:41:44 UTC

[commons-text] 02/09: Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function).

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-text.git

commit a34ccac32b2e4a0c7f8abc94b4881a3aa91b6c01
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Jun 27 10:02:37 2020 -0400

    Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function<String,
    V>).
---
 src/changes/changes.xml                            |  1 +
 .../commons/text/lookup/FunctionStringLookup.java  | 99 ++++++++++++++++++++++
 .../commons/text/lookup/StringLookupFactory.java   | 21 ++++-
 .../text/lookup/FunctionStringLookupTest.java      | 53 ++++++++++++
 4 files changed, 170 insertions(+), 4 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 434c7f6..d43e07a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -55,6 +55,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action issue="TEXT-177" type="update" dev="ggregory" due-to="Gary Gregory">Update from Apache Commons Lang 3.9 to 3.10.</action>
     <action                  type="add" dev="ggregory">Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int).</action>
     <action                  type="add" dev="ggregory">Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int, int, int).</action>
+    <action                  type="add" dev="ggregory">Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function&lt;String, V&gt;).</action>
     <action                  type="update" dev="ggregory" due-to="Gary Gregory">[test] junit-jupiter 5.5.1 -> 5.5.2.</action>
     <action                  type="update" dev="ggregory" due-to="Gary Gregory">[test] org.assertj:assertj-core 3.13.2 -> 3.16.1.</action>
     <action                  type="update" dev="ggregory" due-to="Gary Gregory">[build] com.puppycrawl.tools:checkstyle 8.23 -> 8.27.</action>
diff --git a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
new file mode 100644
index 0000000..464d1c5
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
@@ -0,0 +1,99 @@
+/*
+ * 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
+ *
+ *      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.commons.text.lookup;
+
+import java.util.Objects;
+import java.util.function.Function;
+
+/**
+ * A function-based lookup where the request for a lookup is answered by applying that function with a key.
+ *
+ * @param <V>
+ *            A function's input type
+ *
+ * @since 1.9
+ */
+final class FunctionStringLookup<V> implements StringLookup {
+
+    /**
+     * Creates a new instance backed by a Function.
+     *
+     * @param <T>
+     *            the function's input type
+     * @param function
+     *            the function, may be null.
+     * @return a new instance backed by the given function.
+     */
+    static <T> FunctionStringLookup<T> on(final Function<String, T> function) {
+        return new FunctionStringLookup<>(function);
+    }
+
+    /**
+     * Function.
+     */
+    private final Function<String, V> function;
+
+    /**
+     * Creates a new instance backed by a Function.
+     *
+     * @param function
+     *            the function, may be null.
+     */
+    private FunctionStringLookup(final Function<String, V> function) {
+        this.function = function;
+    }
+
+    /**
+     * Gets the function used in lookups.
+     *
+     * @return The function used in lookups.
+     */
+    Function<String, V> getFunction() {
+        return function;
+    }
+
+    /**
+     * Looks up a String key by applying the function.
+     * <p>
+     * If the function is null, then null is returned. The function result object is converted to a string using toString().
+     * </p>
+     *
+     * @param key
+     *            the key to be looked up, may be null.
+     * @return The function result as a string, may be null.
+     */
+    @Override
+    public String lookup(final String key) {
+        if (function == null) {
+            return null;
+        }
+        final V obj;
+        try {
+            obj = function.apply(key);
+        } catch (final NullPointerException e) {
+            // Could be a ConcurrentHashMap and a null key request
+            return null;
+        }
+        return Objects.toString(obj, null);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " [map=" + function + "]";
+    }
+
+}
diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
index 0eaa045..fc213d2 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -18,6 +18,7 @@
 package org.apache.commons.text.lookup;
 
 import java.util.Map;
+import java.util.function.Function;
 
 import org.apache.commons.text.StringSubstitutor;
 
@@ -294,7 +295,7 @@ public final class StringLookupFactory {
             stringLookupMap.put("base64", Base64DecoderStringLookup.INSTANCE);
             for (final DefaultStringLookup stringLookup : DefaultStringLookup.values()) {
                 stringLookupMap.put(InterpolatorStringLookup.toKey(stringLookup.getKey()),
-                        stringLookup.getStringLookup());
+                    stringLookup.getStringLookup());
             }
         }
     }
@@ -536,6 +537,18 @@ public final class StringLookupFactory {
     }
 
     /**
+     * Returns a new function-based lookup where the request for a lookup is answered by applying the function with a lookup key.
+     *
+     * @param <V> the function input type.
+     * @param function the function.
+     * @return a new MapStringLookup.
+     * @since 1.9
+     */
+    public <V> StringLookup functionStringLookup(final Function<String, V> function) {
+        return FunctionStringLookup.on(function);
+    }
+
+    /**
      * Returns a new InterpolatorStringLookup using the {@link StringLookupFactory default lookups}.
      * <p>
      * The lookups available to an interpolator are defined in
@@ -571,14 +584,14 @@ public final class StringLookupFactory {
      * {@code stringLookupMap}:
      * </p>
      *
-     * @param stringLookupMap     the map of string lookups.
+     * @param stringLookupMap the map of string lookups.
      * @param defaultStringLookup the default string lookup.
-     * @param addDefaultLookups   whether to use lookups as described above.
+     * @param addDefaultLookups whether to use lookups as described above.
      * @return a new InterpolatorStringLookup.
      * @since 1.4
      */
     public StringLookup interpolatorStringLookup(final Map<String, StringLookup> stringLookupMap,
-            final StringLookup defaultStringLookup, final boolean addDefaultLookups) {
+        final StringLookup defaultStringLookup, final boolean addDefaultLookups) {
         return new InterpolatorStringLookup(stringLookupMap, defaultStringLookup, addDefaultLookups);
     }
 
diff --git a/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java
new file mode 100644
index 0000000..1673096
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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
+ *
+ *      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.commons.text.lookup;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link FunctionStringLookup}.
+ */
+public class FunctionStringLookupTest {
+
+    @Test
+    public void testConcurrentHashMapNull() {
+        final Map<String, Object> map = new ConcurrentHashMap<>();
+        Assertions.assertNull(FunctionStringLookup.on(k -> map.get(k)).lookup(null));
+    }
+
+    @Test
+    public void testHashMapNull() {
+        final Map<String, Object> map = new HashMap<>();
+        Assertions.assertNull(FunctionStringLookup.on(k -> map.get(k)).lookup(null));
+    }
+
+    @Test
+    public void testOne() {
+        final String key = "key";
+        final String value = "value";
+        final Map<String, String> map = new HashMap<>();
+        map.put(key, value);
+        Assertions.assertEquals(value, FunctionStringLookup.on(k -> map.get(k)).lookup(key));
+    }
+
+}