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 18:04:20 UTC
[commons-text] branch master updated: Add BiStringLookup and
implementation BiFunctionStringLookup.
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
The following commit(s) were added to refs/heads/master by this push:
new 54abd28 Add BiStringLookup and implementation BiFunctionStringLookup.
54abd28 is described below
commit 54abd281c8e95637b8a57a75859ddfd77ceff302
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Jun 27 14:04:13 2020 -0400
Add BiStringLookup and implementation BiFunctionStringLookup.
---
src/changes/changes.xml | 7 +-
.../commons/text/lookup/AbstractStringLookup.java | 20 ++---
...ringLookup.java => BiFunctionStringLookup.java} | 57 +++++++------
.../{StringLookup.java => BiStringLookup.java} | 19 +++--
.../commons/text/lookup/FunctionStringLookup.java | 27 +++---
.../apache/commons/text/lookup/StringLookup.java | 5 +-
.../commons/text/lookup/StringLookupFactory.java | 19 ++++-
.../text/lookup/BiFunctionStringLookupTest.java | 98 ++++++++++++++++++++++
.../text/lookup/FunctionStringLookupTest.java | 2 +
9 files changed, 180 insertions(+), 74 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d43e07a..bf5a2d5 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -53,9 +53,10 @@ The <action> type attribute can be add,update,fix,remove.
<action type="add" dev="ggregory" due-to="Gary Gregory">Add StringMatcher.size().</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Refactor TextStringBuilder.readFrom(Readable), extracting readFrom(CharBuffer) and readFrom(Reader).</action>
<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<String, V>).</action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int).</action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.text.matcher.StringMatcher.isMatch(CharSequence, int, int, int).</action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.text.lookup.StringLookupFactory.functionStringLookup(Function<String, V>).</action>
+ <action type="add" dev="ggregory" due-to="Gary Gregory">Add BiStringLookup and implementation BiFunctionStringLookup.</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/AbstractStringLookup.java b/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
index 0819ce6..00e80f2 100644
--- a/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/AbstractStringLookup.java
@@ -26,7 +26,6 @@ import org.apache.commons.lang3.StringUtils;
*/
abstract class AbstractStringLookup implements StringLookup {
-
/**
* The empty string.
*/
@@ -45,10 +44,8 @@ abstract class AbstractStringLookup implements StringLookup {
/**
* Returns the substring after the first occurrence of {@code ch} in {@code value}.
*
- * @param value
- * The source string.
- * @param ch
- * The character to search.
+ * @param value The source string.
+ * @param ch The character to search.
* @return a new string.
*/
protected String substringAfter(final String value, final char ch) {
@@ -59,10 +56,8 @@ abstract class AbstractStringLookup implements StringLookup {
/**
* Returns the substring after the first occurrence of {@code ch} in {@code value}.
*
- * @param value
- * The source string.
- * @param ch
- * The character to search.
+ * @param value The source string.
+ * @param ch The character to search.
* @return a new string.
*/
protected String substringAfterLast(final String value, final char ch) {
@@ -73,13 +68,12 @@ abstract class AbstractStringLookup implements StringLookup {
/**
* Returns the substring after the first occurrence of {@code str} in {@code value}.
*
- * @param value
- * The source string.
- * @param str
- * The string to search.
+ * @param value The source string.
+ * @param str The string to search.
* @return a new string.
*/
protected String substringAfter(final String value, final String str) {
return StringUtils.substringAfter(value, str);
}
+
}
diff --git a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java b/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java
similarity index 64%
copy from src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
copy to src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java
index d262337..e62e601 100644
--- a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/BiFunctionStringLookup.java
@@ -18,58 +18,52 @@ package org.apache.commons.text.lookup;
import java.util.Map;
import java.util.Objects;
-import java.util.function.Function;
+import java.util.function.BiFunction;
/**
* 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
+ * @param <R> A function's return type
+ * @param <P> A function's second input type
*
* @since 1.9
*/
-final class FunctionStringLookup<V> implements StringLookup {
+final class BiFunctionStringLookup<P, R> implements BiStringLookup<P> {
/**
* Creates a new instance backed by a Function.
*
- * @param <T>
- * the function's input type
- * @param function
- * the function, may be null.
+ * @param <T> the function's input type
+ * @param biFunction 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);
+ static <U, T> BiFunctionStringLookup<U, T> on(final BiFunction<String, U, T> biFunction) {
+ return new BiFunctionStringLookup<>(biFunction);
}
/**
* Creates a new instance backed by a Map. Used by the default lookup.
*
- * @param <T>
- * the map's value type.
- * @param map
- * the map of keys to values, may be null.
+ * @param <T> the map's value type.
+ * @param map the map of keys to values, may be null.
* @return a new instance backed by the given map.
*/
- static <T> FunctionStringLookup<T> on(final Map<String, T> map) {
- return on(key -> map.get(key));
+ static <U, T> BiFunctionStringLookup<U, T> on(final Map<String, T> map) {
+ return on((key, u) -> map.get(key));
}
-
/**
* Function.
*/
- private final Function<String, V> function;
+ private final BiFunction<String, P, R> biFunction;
/**
* Creates a new instance backed by a Function.
*
- * @param function
- * the function, may be null.
+ * @param biFunction the function, may be null.
*/
- private FunctionStringLookup(final Function<String, V> function) {
- this.function = function;
+ private BiFunctionStringLookup(final BiFunction<String, P, R> biFunction) {
+ this.biFunction = biFunction;
}
/**
@@ -77,8 +71,8 @@ final class FunctionStringLookup<V> implements StringLookup {
*
* @return The function used in lookups.
*/
- Function<String, V> getFunction() {
- return function;
+ BiFunction<String, P, R> getBiFunction() {
+ return biFunction;
}
/**
@@ -92,13 +86,13 @@ final class FunctionStringLookup<V> implements StringLookup {
* @return The function result as a string, may be null.
*/
@Override
- public String lookup(final String key) {
- if (function == null) {
+ public String lookup(final String key, final P object) {
+ if (biFunction == null) {
return null;
}
- final V obj;
+ final R obj;
try {
- obj = function.apply(key);
+ obj = biFunction.apply(key, object);
} catch (final SecurityException | NullPointerException | IllegalArgumentException e) {
// Squelched. All lookup(String) will return null.
// Could be a ConcurrentHashMap and a null key request
@@ -109,7 +103,12 @@ final class FunctionStringLookup<V> implements StringLookup {
@Override
public String toString() {
- return super.toString() + " [map=" + function + "]";
+ return super.toString() + " [function=" + biFunction + "]";
+ }
+
+ @Override
+ public String lookup(String key) {
+ return lookup(key, null);
}
}
diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookup.java b/src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
similarity index 82%
copy from src/main/java/org/apache/commons/text/lookup/StringLookup.java
copy to src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
index d89fdf2..90a3437 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/BiStringLookup.java
@@ -27,11 +27,13 @@ package org.apache.commons.text.lookup;
* For example, it would be possible to implement a lookup that used the key as a primary key, and looked up the value
* on demand from the database.
* </p>
+ *
+ * @param <U> The second argument type.
*
- * @since 1.3
+ * @since 1.9
*/
@FunctionalInterface
-public interface StringLookup {
+public interface BiStringLookup<U> extends StringLookup {
/**
* Looks up a String key to a String value.
@@ -52,12 +54,15 @@ public interface StringLookup {
* <pre>
* Map<String, Object> map = new HashMap<String, Object>();
* map.put("number", new Integer(2));
- * assertEquals("2", StringLookupFactory.mapStringLookup(map).lookup("number"));
+ * assertEquals("2", StringLookupFactory.biFunctionStringLookup(map).lookup("number", "A context object"));
* </pre>
*
- * @param key
- * the key to look up, may be null
- * @return The matching value, null if no match
+ * @param key the key to look up, may be null.
+ * @param object ignored by default.
+ * @return The matching value, null if no match.
*/
- String lookup(String key);
+ default String lookup(final String key, final U object) {
+ return lookup(key);
+ }
+
}
diff --git a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
index d262337..5fb234c 100644
--- a/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/FunctionStringLookup.java
@@ -23,40 +23,34 @@ 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
+ * @param <V> A function's input type
*
* @since 1.9
*/
-final class FunctionStringLookup<V> implements StringLookup {
+final class FunctionStringLookup<V> extends AbstractStringLookup {
/**
* Creates a new instance backed by a Function.
*
- * @param <T>
- * the function's input type
- * @param function
- * the function, may be null.
+ * @param <R> 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) {
+ static <R> FunctionStringLookup<R> on(final Function<String, R> function) {
return new FunctionStringLookup<>(function);
}
/**
* Creates a new instance backed by a Map. Used by the default lookup.
*
- * @param <T>
- * the map's value type.
- * @param map
- * the map of keys to values, may be null.
+ * @param <V> the map's value type.
+ * @param map the map of keys to values, may be null.
* @return a new instance backed by the given map.
*/
- static <T> FunctionStringLookup<T> on(final Map<String, T> map) {
+ static <V> FunctionStringLookup<V> on(final Map<String, V> map) {
return on(key -> map.get(key));
}
-
/**
* Function.
*/
@@ -65,8 +59,7 @@ final class FunctionStringLookup<V> implements StringLookup {
/**
* Creates a new instance backed by a Function.
*
- * @param function
- * the function, may be null.
+ * @param function the function, may be null.
*/
private FunctionStringLookup(final Function<String, V> function) {
this.function = function;
@@ -109,7 +102,7 @@ final class FunctionStringLookup<V> implements StringLookup {
@Override
public String toString() {
- return super.toString() + " [map=" + function + "]";
+ return super.toString() + " [function=" + function + "]";
}
}
diff --git a/src/main/java/org/apache/commons/text/lookup/StringLookup.java b/src/main/java/org/apache/commons/text/lookup/StringLookup.java
index d89fdf2..9b5e998 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookup.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookup.java
@@ -55,9 +55,8 @@ public interface StringLookup {
* assertEquals("2", StringLookupFactory.mapStringLookup(map).lookup("number"));
* </pre>
*
- * @param key
- * the key to look up, may be null
- * @return The matching value, null if no match
+ * @param key the key to look up, may be null.
+ * @return The matching value, null if no match.
*/
String lookup(String key);
}
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 e0870da..05fc77b 100644
--- a/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
+++ b/src/main/java/org/apache/commons/text/lookup/StringLookupFactory.java
@@ -20,6 +20,7 @@ package org.apache.commons.text.lookup;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
+import java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.commons.text.StringSubstitutor;
@@ -468,6 +469,20 @@ 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 <R> the function return type.
+ * @param <U> the funtion's second paremeter type.
+ * @param biFunction the function.
+ * @return a new MapStringLookup.
+ * @since 1.9
+ */
+ public <R, U> BiStringLookup<U> biFunctionStringLookup(final BiFunction<String, U, R> biFunction) {
+ return BiFunctionStringLookup.on(biFunction);
+ }
+
+ /**
* Returns the ConstantStringLookup singleton instance to look up the value of a fully-qualified static final value.
* <p>
* Sometimes it is necessary in a configuration file to refer to a constant defined in a class. This can be done
@@ -624,12 +639,12 @@ 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 <R> the function return type.
* @param function the function.
* @return a new MapStringLookup.
* @since 1.9
*/
- public <V> StringLookup functionStringLookup(final Function<String, V> function) {
+ public <R> StringLookup functionStringLookup(final Function<String, R> function) {
return FunctionStringLookup.on(function);
}
diff --git a/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java
new file mode 100644
index 0000000..bb16ae8
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/lookup/BiFunctionStringLookupTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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 java.util.function.BiFunction;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link FunctionStringLookup}.
+ */
+public class BiFunctionStringLookupTest {
+
+ @Test
+ public void testConcurrentHashMapNull() {
+ Assertions.assertNull(BiFunctionStringLookup.on(new ConcurrentHashMap<>()).lookup(null));
+ }
+
+ @Test
+ public void testHashMapNull() {
+ Assertions.assertNull(BiFunctionStringLookup.on(new HashMap<>()).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(map).lookup(key));
+ }
+
+ private static final String SEPARATOR = ".";
+
+ @SuppressWarnings("unchecked")
+ private final BiFunction<String, Map<String, Object>, Object> nestedMapBiFunction = (k, m) -> {
+ final String keyCandidate = StringUtils.substringBefore(k, SEPARATOR);
+ if (keyCandidate.isEmpty()) {
+ return m.get(k);
+ }
+ Object value = m.get(keyCandidate);
+ if (value instanceof Map) {
+ return this.nestedMapBiFunction.apply(StringUtils.substringAfter(k, SEPARATOR),
+ (Map<String, Object>) value);
+ }
+ return value;
+ };
+
+ @Test
+ public void testBiFunctionForNestedMap() {
+ final String subSubKey = "subsubkeyMap";
+ final String subSubValue = "subsubvalue";
+ final Map<String, String> subSubMap = new HashMap<>();
+ subSubMap.put(subSubKey, subSubValue);
+ //
+ final String subKey = "subkey";
+ final String subKeyMap = "subkeyMap";
+ final String subValue = "subvalue";
+ final Map<String, Object> rootSubMap = new HashMap<>();
+ rootSubMap.put(subKey, subValue);
+ rootSubMap.put(subKeyMap, subSubMap);
+ //
+ final String rootKey = "keyMap";
+ final String rootKey2 = "key2";
+ final String rootValue2 = "value2";
+ final Map<String, Object> rootMap = new HashMap<>();
+ rootMap.put(rootKey, rootSubMap);
+ rootMap.put(rootKey2, rootValue2);
+ //
+ final BiStringLookup<Map<String, Object>> stringLookup = StringLookupFactory.INSTANCE
+ .biFunctionStringLookup(nestedMapBiFunction);
+ Assertions.assertEquals(rootValue2, stringLookup.lookup(rootKey2, rootMap));
+ Assertions.assertEquals(subValue, stringLookup.lookup(rootKey + SEPARATOR + subKey, rootMap));
+ Assertions.assertEquals(subSubValue,
+ stringLookup.lookup(rootKey + SEPARATOR + subKeyMap + SEPARATOR + subSubKey, rootMap));
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java
index 1ae122e..af10943 100644
--- a/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java
+++ b/src/test/java/org/apache/commons/text/lookup/FunctionStringLookupTest.java
@@ -20,7 +20,9 @@ package org.apache.commons.text.lookup;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiFunction;
+import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;