You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/10/14 15:08:19 UTC
[3/4] incubator-brooklyn git commit: Not anonymous inner classes in
functions
Not anonymous inner classes in functions
- Anonymous inner classes makes persistence very brittle.
- Adds more tests.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f22b3eb4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f22b3eb4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f22b3eb4
Branch: refs/heads/master
Commit: f22b3eb4319d7c9d6e2604b0266bef8287889b86
Parents: 74207bd
Author: Aled Sage <al...@gmail.com>
Authored: Wed Oct 7 10:20:46 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Oct 12 10:18:15 2015 +0100
----------------------------------------------------------------------
.../brooklyn/core/entity/EntityFunctions.java | 178 ++++++++-
.../brooklyn/feed/http/HttpValueFunctions.java | 3 +
.../brooklyn/feed/http/JsonFunctions.java | 385 ++++++++++++++-----
.../brooklyn/feed/ssh/SshValueFunctions.java | 80 +++-
.../brooklyn/feed/http/JsonFunctionsTest.java | 15 +-
.../feed/ssh/SshValueFunctionsTest.java | 43 +++
.../brooklyn/feed/jmx/JmxValueFunctions.java | 55 ++-
.../feed/jmx/JmxValueFunctionsTest.java | 120 ++++++
.../brooklyn/util/guava/MaybeFunctions.java | 52 ++-
.../brooklyn/util/math/MathFunctions.java | 204 +++++++++-
.../brooklyn/util/text/StringFunctions.java | 301 +++++++++++++--
.../brooklyn/util/guava/MaybeFunctionsTest.java | 47 +++
.../brooklyn/util/math/MathFunctionsTest.java | 16 +-
.../brooklyn/util/text/StringFunctionsTest.java | 41 +-
14 files changed, 1342 insertions(+), 198 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/main/java/org/apache/brooklyn/core/entity/EntityFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityFunctions.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityFunctions.java
index 331fb7d..a4459ed 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityFunctions.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityFunctions.java
@@ -43,7 +43,10 @@ import com.google.common.collect.Iterables;
public class EntityFunctions {
- public static <T> Function<Entity, T> attribute(final AttributeSensor<T> attribute) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<Entity, T> attributeOld(final AttributeSensor<T> attribute) {
+ // TODO PERSISTENCE WORKAROUND
class GetEntityAttributeFunction implements Function<Entity, T> {
@Override public T apply(Entity input) {
return (input == null) ? null : input.getAttribute(attribute);
@@ -52,7 +55,10 @@ public class EntityFunctions {
return new GetEntityAttributeFunction();
}
- public static <T> Function<Entity, T> config(final ConfigKey<T> key) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<Entity, T> configOld(final ConfigKey<T> key) {
+ // TODO PERSISTENCE WORKAROUND
class GetEntityConfigFunction implements Function<Entity, T> {
@Override public T apply(Entity input) {
return (input == null) ? null : input.getConfig(key);
@@ -61,7 +67,10 @@ public class EntityFunctions {
return new GetEntityConfigFunction();
}
- public static Function<Entity, String> displayName() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Entity, String> displayNameOld() {
+ // TODO PERSISTENCE WORKAROUND
class GetEntityDisplayName implements Function<Entity, String> {
@Override public String apply(Entity input) {
return (input == null) ? null : input.getDisplayName();
@@ -70,7 +79,10 @@ public class EntityFunctions {
return new GetEntityDisplayName();
}
- public static Function<Identifiable, String> id() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Identifiable, String> idOld() {
+ // TODO PERSISTENCE WORKAROUND
class GetIdFunction implements Function<Identifiable, String> {
@Override public String apply(Identifiable input) {
return (input == null) ? null : input.getId();
@@ -79,10 +91,10 @@ public class EntityFunctions {
return new GetIdFunction();
}
- /** returns a function which sets the given sensors on the entity passed in,
- * with {@link Entities#UNCHANGED} and {@link Entities#REMOVE} doing those actions. */
- public static Function<Entity,Void> settingSensorsConstant(final Map<AttributeSensor<?>,Object> values) {
- checkNotNull(values, "values");
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Entity,Void> settingSensorsConstantOld(final Map<AttributeSensor<?>,Object> values) {
+ // TODO PERSISTENCE WORKAROUND
class SettingSensorsConstantFunction implements Function<Entity, Void> {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override public Void apply(Entity input) {
@@ -104,14 +116,10 @@ public class EntityFunctions {
return new SettingSensorsConstantFunction();
}
- /** as {@link #settingSensorsConstant(Map)} but as a {@link Runnable} */
- public static Runnable settingSensorsConstant(final Entity entity, final Map<AttributeSensor<?>,Object> values) {
- checkNotNull(entity, "entity");
- checkNotNull(values, "values");
- return Functionals.runnable(Suppliers.compose(settingSensorsConstant(values), Suppliers.ofInstance(entity)));
- }
-
- public static <K,V> Function<Entity, Void> updatingSensorMapEntry(final AttributeSensor<Map<K,V>> mapSensor, final K key, final Supplier<? extends V> valueSupplier) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <K,V> Function<Entity, Void> updatingSensorMapEntryOld(final AttributeSensor<Map<K,V>> mapSensor, final K key, final Supplier<? extends V> valueSupplier) {
+ // TODO PERSISTENCE WORKAROUND
class UpdatingSensorMapEntryFunction implements Function<Entity, Void> {
@Override public Void apply(Entity input) {
ServiceStateLogic.updateMapSensorEntry((EntityLocal)input, mapSensor, key, valueSupplier.get());
@@ -120,11 +128,11 @@ public class EntityFunctions {
}
return new UpdatingSensorMapEntryFunction();
}
- public static <K,V> Runnable updatingSensorMapEntry(final Entity entity, final AttributeSensor<Map<K,V>> mapSensor, final K key, final Supplier<? extends V> valueSupplier) {
- return Functionals.runnable(Suppliers.compose(updatingSensorMapEntry(mapSensor, key, valueSupplier), Suppliers.ofInstance(entity)));
- }
- public static Supplier<Collection<Application>> applications(final ManagementContext mgmt) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of non-static inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Supplier<Collection<Application>> applicationsOld(final ManagementContext mgmt) {
+ // TODO PERSISTENCE WORKAROUND
class AppsSupplier implements Supplier<Collection<Application>> {
@Override
public Collection<Application> get() {
@@ -134,6 +142,136 @@ public class EntityFunctions {
return new AppsSupplier();
}
+ public static <T> Function<Entity, T> attribute(AttributeSensor<T> attribute) {
+ return new GetEntityAttributeFunction<T>(checkNotNull(attribute, "attribute"));
+ }
+
+ protected static class GetEntityAttributeFunction<T> implements Function<Entity, T> {
+ private final AttributeSensor<T> attribute;
+ protected GetEntityAttributeFunction(AttributeSensor<T> attribute) {
+ this.attribute = attribute;
+ }
+ @Override public T apply(Entity input) {
+ return (input == null) ? null : input.getAttribute(attribute);
+ }
+ };
+
+ public static <T> Function<Entity, T> config(ConfigKey<T> key) {
+ return new GetEntityConfigFunction<T>(checkNotNull(key, "key"));
+ }
+
+ protected static class GetEntityConfigFunction<T> implements Function<Entity, T> {
+ private final ConfigKey<T> key;
+
+ protected GetEntityConfigFunction(ConfigKey<T> key) {
+ this.key = key;
+ }
+
+ @Override public T apply(Entity input) {
+ return (input == null) ? null : input.getConfig(key);
+ }
+ };
+
+ public static Function<Entity, String> displayName() {
+ return GetEntityDisplayName.INSTANCE;
+ }
+
+ protected static class GetEntityDisplayName implements Function<Entity, String> {
+ public static final GetEntityDisplayName INSTANCE = new GetEntityDisplayName();
+ @Override public String apply(Entity input) {
+ return (input == null) ? null : input.getDisplayName();
+ }
+ };
+
+ public static Function<Identifiable, String> id() {
+ return GetIdFunction.INSTANCE;
+ }
+
+ protected static class GetIdFunction implements Function<Identifiable, String> {
+ public static final GetIdFunction INSTANCE = new GetIdFunction();
+ @Override public String apply(Identifiable input) {
+ return (input == null) ? null : input.getId();
+ }
+ };
+
+
+ /** returns a function which sets the given sensors on the entity passed in,
+ * with {@link Entities#UNCHANGED} and {@link Entities#REMOVE} doing those actions. */
+ public static Function<Entity,Void> settingSensorsConstant(final Map<AttributeSensor<?>,Object> values) {
+ return new SettingSensorsConstantFunction(checkNotNull(values, "values"));
+ }
+
+ protected static class SettingSensorsConstantFunction implements Function<Entity, Void> {
+ private final Map<AttributeSensor<?>, Object> values;
+
+ protected SettingSensorsConstantFunction(Map<AttributeSensor<?>, Object> values) {
+ this.values = values;
+ }
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override public Void apply(Entity input) {
+ for (Map.Entry<AttributeSensor<?>,Object> entry : values.entrySet()) {
+ AttributeSensor sensor = (AttributeSensor)entry.getKey();
+ Object value = entry.getValue();
+ if (value==Entities.UNCHANGED) {
+ // nothing
+ } else if (value==Entities.REMOVE) {
+ ((EntityInternal)input).sensors().remove(sensor);
+ } else {
+ value = TypeCoercions.coerce(value, sensor.getTypeToken());
+ ((EntityInternal)input).sensors().set(sensor, value);
+ }
+ }
+ return null;
+ }
+ }
+
+ /** as {@link #settingSensorsConstant(Map)} but as a {@link Runnable} */
+ public static Runnable settingSensorsConstant(final Entity entity, final Map<AttributeSensor<?>,Object> values) {
+ checkNotNull(entity, "entity");
+ checkNotNull(values, "values");
+ return Functionals.runnable(Suppliers.compose(settingSensorsConstant(values), Suppliers.ofInstance(entity)));
+ }
+
+ public static <K,V> Function<Entity, Void> updatingSensorMapEntry(final AttributeSensor<Map<K,V>> mapSensor, final K key, final Supplier<? extends V> valueSupplier) {
+ return new UpdatingSensorMapEntryFunction<K,V>(mapSensor, key, valueSupplier);
+ }
+
+ protected static class UpdatingSensorMapEntryFunction<K, V> implements Function<Entity, Void> {
+ private final AttributeSensor<Map<K, V>> mapSensor;
+ private final K key;
+ private final Supplier<? extends V> valueSupplier;
+
+ public UpdatingSensorMapEntryFunction(AttributeSensor<Map<K, V>> mapSensor, K key, Supplier<? extends V> valueSupplier) {
+ this.mapSensor = mapSensor;
+ this.key = key;
+ this.valueSupplier = valueSupplier;
+ }
+ @Override public Void apply(Entity input) {
+ ServiceStateLogic.updateMapSensorEntry((EntityLocal)input, mapSensor, key, valueSupplier.get());
+ return null;
+ }
+ }
+
+ public static <K,V> Runnable updatingSensorMapEntry(final Entity entity, final AttributeSensor<Map<K,V>> mapSensor, final K key, final Supplier<? extends V> valueSupplier) {
+ return Functionals.runnable(Suppliers.compose(updatingSensorMapEntry(mapSensor, key, valueSupplier), Suppliers.ofInstance(entity)));
+ }
+
+ public static Supplier<Collection<Application>> applications(ManagementContext mgmt) {
+ return new AppsSupplier(checkNotNull(mgmt, "mgmt"));
+ }
+
+ protected static class AppsSupplier implements Supplier<Collection<Application>> {
+ private final ManagementContext mgmt;
+
+ public AppsSupplier(ManagementContext mgmt) {
+ this.mgmt = mgmt;
+ }
+ @Override
+ public Collection<Application> get() {
+ return mgmt.getApplications();
+ }
+ }
+
public static Function<Entity, Location> locationMatching(Predicate<? super Location> filter) {
return new LocationMatching(filter);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/main/java/org/apache/brooklyn/feed/http/HttpValueFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/feed/http/HttpValueFunctions.java b/core/src/main/java/org/apache/brooklyn/feed/http/HttpValueFunctions.java
index 75dab74..0fec133 100644
--- a/core/src/main/java/org/apache/brooklyn/feed/http/HttpValueFunctions.java
+++ b/core/src/main/java/org/apache/brooklyn/feed/http/HttpValueFunctions.java
@@ -39,6 +39,7 @@ public class HttpValueFunctions {
/** @deprecated since 0.7.0; only here for deserialization of persisted state */
private static Function<HttpToolResponse, Integer> responseCodeLegacy() {
+ // TODO PERSISTENCE WORKAROUND kept anonymous function in case referenced in persisted state
return new Function<HttpToolResponse, Integer>() {
@Override public Integer apply(HttpToolResponse input) {
return input.getResponseCode();
@@ -70,6 +71,7 @@ public class HttpValueFunctions {
/** @deprecated since 0.7.0; only here for deserialization of persisted state */
private static Function<HttpToolResponse, String> stringContentsFunctionLegacy() {
+ // TODO PERSISTENCE WORKAROUND kept anonymous function in case referenced in persisted state
return new Function<HttpToolResponse, String>() {
@Override public String apply(HttpToolResponse input) {
return input.getContentAsString();
@@ -105,6 +107,7 @@ public class HttpValueFunctions {
/** @deprecated since 0.7.0; only here for deserialization of persisted state */
private static Function<HttpToolResponse, Long> latencyLegacy() {
+ // TODO PERSISTENCE WORKAROUND kept anonymous function in case referenced in persisted state
return new Function<HttpToolResponse, Long>() {
public Long apply(HttpToolResponse input) {
return input.getLatencyFullContent();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/main/java/org/apache/brooklyn/feed/http/JsonFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/feed/http/JsonFunctions.java b/core/src/main/java/org/apache/brooklyn/feed/http/JsonFunctions.java
index a3e04cd..beff29f 100644
--- a/core/src/main/java/org/apache/brooklyn/feed/http/JsonFunctions.java
+++ b/core/src/main/java/org/apache/brooklyn/feed/http/JsonFunctions.java
@@ -34,14 +34,20 @@ import org.apache.brooklyn.util.guava.MaybeFunctions;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
-import com.google.gson.*;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import com.jayway.jsonpath.JsonPath;
public class JsonFunctions {
private JsonFunctions() {} // instead use static utility methods
- public static Function<String, JsonElement> asJson() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String, JsonElement> asJsonOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, JsonElement>() {
@Override public JsonElement apply(String input) {
return new JsonParser().parse(input);
@@ -49,7 +55,10 @@ public class JsonFunctions {
};
}
- public static <T> Function<JsonElement, List<T>> forEach(final Function<JsonElement, T> func) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<JsonElement, List<T>> forEachOld(final Function<JsonElement, T> func) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<JsonElement, List<T>>() {
@Override public List<T> apply(JsonElement input) {
JsonArray array = (JsonArray) input;
@@ -62,7 +71,129 @@ public class JsonFunctions {
};
}
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<JsonElement, JsonElement> walkOld(final Iterable<String> elements) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<JsonElement, JsonElement>() {
+ @Override public JsonElement apply(JsonElement input) {
+ JsonElement curr = input;
+ for (String element : elements) {
+ JsonObject jo = curr.getAsJsonObject();
+ curr = jo.get(element);
+ if (curr==null)
+ throw new NoSuchElementException("No element '"+element+" in JSON, when walking "+elements);
+ }
+ return curr;
+ }
+ };
+ }
+
+ /** as {@link #walk(Iterable))} but if any element is not found it simply returns null */
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<JsonElement, JsonElement> walkNOld(final Iterable<String> elements) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<JsonElement, JsonElement>() {
+ @Override public JsonElement apply(JsonElement input) {
+ JsonElement curr = input;
+ for (String element : elements) {
+ if (curr==null) return null;
+ JsonObject jo = curr.getAsJsonObject();
+ curr = jo.get(element);
+ }
+ return curr;
+ }
+ };
+ }
+
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Maybe<JsonElement>, Maybe<JsonElement>> walkMOld(final Iterable<String> elements) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<Maybe<JsonElement>, Maybe<JsonElement>>() {
+ @Override public Maybe<JsonElement> apply(Maybe<JsonElement> input) {
+ Maybe<JsonElement> curr = input;
+ for (String element : elements) {
+ if (curr.isAbsent()) return curr;
+ JsonObject jo = curr.get().getAsJsonObject();
+ JsonElement currO = jo.get(element);
+ if (currO==null) return Maybe.absent("No element '"+element+" in JSON, when walking "+elements);
+ curr = Maybe.of(currO);
+ }
+ return curr;
+ }
+ };
+ }
+
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<JsonElement,T> getPathOld(final String path) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<JsonElement, T>() {
+ @SuppressWarnings("unchecked")
+ @Override public T apply(JsonElement input) {
+ String jsonString = input.toString();
+ Object rawElement = JsonPath.read(jsonString, path);
+ return (T) rawElement;
+ }
+ };
+ }
+
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<JsonElement, T> castOld(final Class<T> expected) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<JsonElement, T>() {
+ @Override public T apply(JsonElement input) {
+ return doCast(input, expected);
+ }
+ };
+ }
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<Maybe<JsonElement>, T> castMOld(final Class<T> expected, final T defaultValue) {
+ // TODO PERSISTENCE WORKAROUND
+ return new Function<Maybe<JsonElement>, T>() {
+ @Override
+ public T apply(Maybe<JsonElement> input) {
+ if (input.isAbsent()) return defaultValue;
+ return cast(expected).apply(input.get());
+ }
+ };
+ }
+
+ public static Function<String, JsonElement> asJson() {
+ return new AsJson();
+ }
+
+ protected static class AsJson implements Function<String, JsonElement> {
+ @Override public JsonElement apply(String input) {
+ return new JsonParser().parse(input);
+ }
+ }
+
+ public static <T> Function<JsonElement, List<T>> forEach(final Function<JsonElement, T> func) {
+ return new ForEach<T>(func);
+ }
+
+ protected static class ForEach<T> implements Function<JsonElement, List<T>> {
+ private final Function<JsonElement, T> func;
+ public ForEach(Function<JsonElement, T> func) {
+ this.func = func;
+ }
+
+ @Override public List<T> apply(JsonElement input) {
+ JsonArray array = (JsonArray) input;
+ List<T> result = Lists.newArrayList();
+ for (int i = 0; i < array.size(); i++) {
+ result.add(func.apply(array.get(i)));
+ }
+ return result;
+ }
+ }
+
/** as {@link #walkM(Iterable)} taking a single string consisting of a dot separated path */
public static Function<JsonElement, JsonElement> walk(String elementOrDotSeparatedElements) {
return walk( Splitter.on('.').split(elementOrDotSeparatedElements) );
@@ -78,21 +209,25 @@ public class JsonFunctions {
public static Function<JsonElement, JsonElement> walk(final Iterable<String> elements) {
// could do this instead, pointing at Maybe for this, and for walkN, but it's slightly less efficient
// return Functionals.chain(MaybeFunctions.<JsonElement>wrap(), walkM(elements), MaybeFunctions.<JsonElement>get());
+ return new Walk(elements);
+ }
- return new Function<JsonElement, JsonElement>() {
- @Override public JsonElement apply(JsonElement input) {
- JsonElement curr = input;
- for (String element : elements) {
- JsonObject jo = curr.getAsJsonObject();
- curr = jo.get(element);
- if (curr==null)
- throw new NoSuchElementException("No element '"+element+" in JSON, when walking "+elements);
- }
- return curr;
+ protected static class Walk implements Function<JsonElement, JsonElement> {
+ private final Iterable<String> elements;
+ public Walk(Iterable<String> elements) {
+ this.elements = elements;
+ }
+ @Override public JsonElement apply(JsonElement input) {
+ JsonElement curr = input;
+ for (String element : elements) {
+ JsonObject jo = curr.getAsJsonObject();
+ curr = jo.get(element);
+ if (curr==null)
+ throw new NoSuchElementException("No element '"+element+" in JSON, when walking "+elements);
}
- };
+ return curr;
+ }
}
-
/** as {@link #walk(String)} but if any element is not found it simply returns null */
public static Function<JsonElement, JsonElement> walkN(@Nullable String elements) {
@@ -106,17 +241,24 @@ public class JsonFunctions {
/** as {@link #walk(Iterable))} but if any element is not found it simply returns null */
public static Function<JsonElement, JsonElement> walkN(final Iterable<String> elements) {
- return new Function<JsonElement, JsonElement>() {
- @Override public JsonElement apply(JsonElement input) {
- JsonElement curr = input;
- for (String element : elements) {
- if (curr==null) return null;
- JsonObject jo = curr.getAsJsonObject();
- curr = jo.get(element);
- }
- return curr;
+ return new WalkN(elements);
+ }
+
+ protected static class WalkN implements Function<JsonElement, JsonElement> {
+ private final Iterable<String> elements;
+
+ public WalkN(Iterable<String> elements) {
+ this.elements = elements;
+ }
+ @Override public JsonElement apply(JsonElement input) {
+ JsonElement curr = input;
+ for (String element : elements) {
+ if (curr==null) return null;
+ JsonObject jo = curr.getAsJsonObject();
+ curr = jo.get(element);
}
- };
+ return curr;
+ }
}
/** as {@link #walk(String))} and {@link #walk(Iterable)} */
@@ -133,89 +275,116 @@ public class JsonFunctions {
* simply preserving a {@link Maybe#absent()} object if additional walks are requested upon it
* (cf jquery) */
public static Function<Maybe<JsonElement>, Maybe<JsonElement>> walkM(final Iterable<String> elements) {
- return new Function<Maybe<JsonElement>, Maybe<JsonElement>>() {
- @Override public Maybe<JsonElement> apply(Maybe<JsonElement> input) {
- Maybe<JsonElement> curr = input;
- for (String element : elements) {
- if (curr.isAbsent()) return curr;
- JsonObject jo = curr.get().getAsJsonObject();
- JsonElement currO = jo.get(element);
- if (currO==null) return Maybe.absent("No element '"+element+" in JSON, when walking "+elements);
- curr = Maybe.of(currO);
- }
- return curr;
- }
- };
+ return new WalkM(elements);
}
+ protected static class WalkM implements Function<Maybe<JsonElement>, Maybe<JsonElement>> {
+ private final Iterable<String> elements;
+
+ public WalkM(Iterable<String> elements) {
+ this.elements = elements;
+ }
+
+ @Override public Maybe<JsonElement> apply(Maybe<JsonElement> input) {
+ Maybe<JsonElement> curr = input;
+ for (String element : elements) {
+ if (curr.isAbsent()) return curr;
+ JsonObject jo = curr.get().getAsJsonObject();
+ JsonElement currO = jo.get(element);
+ if (currO==null) return Maybe.absent("No element '"+element+" in JSON, when walking "+elements);
+ curr = Maybe.of(currO);
+ }
+ return curr;
+ }
+ }
+
/**
* returns an element from a single json primitive value given a full path {@link com.jayway.jsonpath.JsonPath}
*/
public static <T> Function<JsonElement,T> getPath(final String path) {
- return new Function<JsonElement, T>() {
- @SuppressWarnings("unchecked")
- @Override public T apply(JsonElement input) {
- String jsonString = input.toString();
- Object rawElement = JsonPath.read(jsonString, path);
- return (T) rawElement;
- }
- };
+ return new GetPath<T>(path);
}
- @SuppressWarnings("unchecked")
+ protected static class GetPath<T> implements Function<JsonElement, T> {
+ private final String path;
+
+ public GetPath(String path) {
+ this.path = path;
+ }
+ @SuppressWarnings("unchecked")
+ @Override public T apply(JsonElement input) {
+ String jsonString = input.toString();
+ Object rawElement = JsonPath.read(jsonString, path);
+ return (T) rawElement;
+ }
+ };
+
public static <T> Function<JsonElement, T> cast(final Class<T> expected) {
- return new Function<JsonElement, T>() {
- @Override public T apply(JsonElement input) {
- if (input == null) {
- return (T) null;
- } else if (input.isJsonNull()) {
- return (T) null;
- } else if (expected == boolean.class || expected == Boolean.class) {
- return (T) (Boolean) input.getAsBoolean();
- } else if (expected == char.class || expected == Character.class) {
- return (T) (Character) input.getAsCharacter();
- } else if (expected == byte.class || expected == Byte.class) {
- return (T) (Byte) input.getAsByte();
- } else if (expected == short.class || expected == Short.class) {
- return (T) (Short) input.getAsShort();
- } else if (expected == int.class || expected == Integer.class) {
- return (T) (Integer) input.getAsInt();
- } else if (expected == long.class || expected == Long.class) {
- return (T) (Long) input.getAsLong();
- } else if (expected == float.class || expected == Float.class) {
- return (T) (Float) input.getAsFloat();
- } else if (expected == double.class || expected == Double.class) {
- return (T) (Double) input.getAsDouble();
- } else if (expected == BigDecimal.class) {
- return (T) input.getAsBigDecimal();
- } else if (expected == BigInteger.class) {
- return (T) input.getAsBigInteger();
- } else if (Number.class.isAssignableFrom(expected)) {
- // TODO Will result in a class-cast if it's an unexpected sub-type of Number not handled above
- return (T) input.getAsNumber();
- } else if (expected == String.class) {
- return (T) input.getAsString();
- } else if (expected.isArray()) {
- JsonArray array = input.getAsJsonArray();
- Class<?> componentType = expected.getComponentType();
- if (JsonElement.class.isAssignableFrom(componentType)) {
- JsonElement[] result = new JsonElement[array.size()];
- for (int i = 0; i < array.size(); i++) {
- result[i] = array.get(i);
- }
- return (T) result;
- } else {
- Object[] result = (Object[]) Array.newInstance(componentType, array.size());
- for (int i = 0; i < array.size(); i++) {
- result[i] = cast(componentType).apply(array.get(i));
- }
- return (T) result;
- }
- } else {
- throw new IllegalArgumentException("Cannot cast json element to type "+expected);
+ return new Cast<T>(expected);
+ }
+
+ protected static class Cast<T> implements Function<JsonElement, T> {
+ private final Class<T> expected;
+
+ public Cast(Class<T> expected) {
+ this.expected = expected;
+ }
+
+ @Override public T apply(JsonElement input) {
+ return doCast(input, expected);
+ }
+ };
+
+ @SuppressWarnings("unchecked")
+ protected static <T> T doCast(JsonElement input, Class<T> expected) {
+ if (input == null) {
+ return (T) null;
+ } else if (input.isJsonNull()) {
+ return (T) null;
+ } else if (expected == boolean.class || expected == Boolean.class) {
+ return (T) (Boolean) input.getAsBoolean();
+ } else if (expected == char.class || expected == Character.class) {
+ return (T) (Character) input.getAsCharacter();
+ } else if (expected == byte.class || expected == Byte.class) {
+ return (T) (Byte) input.getAsByte();
+ } else if (expected == short.class || expected == Short.class) {
+ return (T) (Short) input.getAsShort();
+ } else if (expected == int.class || expected == Integer.class) {
+ return (T) (Integer) input.getAsInt();
+ } else if (expected == long.class || expected == Long.class) {
+ return (T) (Long) input.getAsLong();
+ } else if (expected == float.class || expected == Float.class) {
+ return (T) (Float) input.getAsFloat();
+ } else if (expected == double.class || expected == Double.class) {
+ return (T) (Double) input.getAsDouble();
+ } else if (expected == BigDecimal.class) {
+ return (T) input.getAsBigDecimal();
+ } else if (expected == BigInteger.class) {
+ return (T) input.getAsBigInteger();
+ } else if (Number.class.isAssignableFrom(expected)) {
+ // TODO Will result in a class-cast if it's an unexpected sub-type of Number not handled above
+ return (T) input.getAsNumber();
+ } else if (expected == String.class) {
+ return (T) input.getAsString();
+ } else if (expected.isArray()) {
+ JsonArray array = input.getAsJsonArray();
+ Class<?> componentType = expected.getComponentType();
+ if (JsonElement.class.isAssignableFrom(componentType)) {
+ JsonElement[] result = new JsonElement[array.size()];
+ for (int i = 0; i < array.size(); i++) {
+ result[i] = array.get(i);
}
+ return (T) result;
+ } else {
+ Object[] result = (Object[]) Array.newInstance(componentType, array.size());
+ for (int i = 0; i < array.size(); i++) {
+ result[i] = cast(componentType).apply(array.get(i));
+ }
+ return (T) result;
}
- };
+ } else {
+ throw new IllegalArgumentException("Cannot cast json element to type "+expected);
+ }
}
public static <T> Function<Maybe<JsonElement>, T> castM(final Class<T> expected) {
@@ -223,13 +392,21 @@ public class JsonFunctions {
}
public static <T> Function<Maybe<JsonElement>, T> castM(final Class<T> expected, final T defaultValue) {
- return new Function<Maybe<JsonElement>, T>() {
- @Override
- public T apply(Maybe<JsonElement> input) {
- if (input.isAbsent()) return defaultValue;
- return cast(expected).apply(input.get());
- }
- };
+ return new CastM<T>(expected, defaultValue);
}
+ protected static class CastM<T> implements Function<Maybe<JsonElement>, T> {
+ private final Class<T> expected;
+ private final T defaultValue;
+
+ public CastM(Class<T> expected, T defaultValue) {
+ this.expected = expected;
+ this.defaultValue = defaultValue;
+ }
+ @Override
+ public T apply(Maybe<JsonElement> input) {
+ if (input.isAbsent()) return defaultValue;
+ return cast(expected).apply(input.get());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/main/java/org/apache/brooklyn/feed/ssh/SshValueFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/feed/ssh/SshValueFunctions.java b/core/src/main/java/org/apache/brooklyn/feed/ssh/SshValueFunctions.java
index 370c3ce..20a95c2 100644
--- a/core/src/main/java/org/apache/brooklyn/feed/ssh/SshValueFunctions.java
+++ b/core/src/main/java/org/apache/brooklyn/feed/ssh/SshValueFunctions.java
@@ -20,13 +20,18 @@ package org.apache.brooklyn.feed.ssh;
import javax.annotation.Nullable;
+import org.apache.brooklyn.util.guava.Functionals;
+
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicates;
public class SshValueFunctions {
- public static Function<SshPollValue, Integer> exitStatus() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<SshPollValue, Integer> exitStatusOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<SshPollValue, Integer>() {
@Override public Integer apply(SshPollValue input) {
return input.getExitStatus();
@@ -34,7 +39,10 @@ public class SshValueFunctions {
};
}
- public static Function<SshPollValue, String> stdout() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<SshPollValue, String> stdoutOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<SshPollValue, String>() {
@Override public String apply(SshPollValue input) {
return input.getStdout();
@@ -42,7 +50,10 @@ public class SshValueFunctions {
};
}
- public static Function<SshPollValue, String> stderr() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<SshPollValue, String> stderrOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<SshPollValue, String>() {
@Override public String apply(SshPollValue input) {
return input.getStderr();
@@ -50,12 +61,10 @@ public class SshValueFunctions {
};
}
- public static Function<SshPollValue, Boolean> exitStatusEquals(final int expected) {
- return chain(SshValueFunctions.exitStatus(), Functions.forPredicate(Predicates.equalTo(expected)));
- }
-
- // TODO Do we want these chain methods? Does guava have them already? Duplicated in HttpValueFunctions.
- public static <A,B,C> Function<A,C> chain(final Function<A,? extends B> f1, final Function<B,C> f2) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <A,B,C> Function<A,C> chainOld(final Function<A,? extends B> f1, final Function<B,C> f2) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<A,C>() {
@Override public C apply(@Nullable A input) {
return f2.apply(f1.apply(input));
@@ -63,11 +72,62 @@ public class SshValueFunctions {
};
}
- public static <A,B,C,D> Function<A,D> chain(final Function<A,? extends B> f1, final Function<B,? extends C> f2, final Function<C,D> f3) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <A,B,C,D> Function<A,D> chainOld(final Function<A,? extends B> f1, final Function<B,? extends C> f2, final Function<C,D> f3) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<A,D>() {
@Override public D apply(@Nullable A input) {
return f3.apply(f2.apply(f1.apply(input)));
}
};
}
+
+ public static Function<SshPollValue, Integer> exitStatus() {
+ return new ExitStatus();
+ }
+
+ protected static class ExitStatus implements Function<SshPollValue, Integer> {
+ @Override public Integer apply(SshPollValue input) {
+ return input.getExitStatus();
+ }
+ }
+
+ public static Function<SshPollValue, String> stdout() {
+ return new Stdout();
+ }
+
+ protected static class Stdout implements Function<SshPollValue, String> {
+ @Override public String apply(SshPollValue input) {
+ return input.getStdout();
+ }
+ }
+
+ public static Function<SshPollValue, String> stderr() {
+ return new Stderr();
+ }
+
+ protected static class Stderr implements Function<SshPollValue, String> {
+ @Override public String apply(SshPollValue input) {
+ return input.getStderr();
+ }
+ }
+
+ public static Function<SshPollValue, Boolean> exitStatusEquals(final int expected) {
+ return chain(SshValueFunctions.exitStatus(), Functions.forPredicate(Predicates.equalTo(expected)));
+ }
+
+ /**
+ * @deprecated since 0.9.0; use {@link Functionals#chain(Function, Function)}
+ */
+ public static <A,B,C> Function<A,C> chain(final Function<A,? extends B> f1, final Function<B,C> f2) {
+ return Functionals.chain(f1, f2);
+ }
+
+ /**
+ * @deprecated since 0.9.0; use {@link Functionals#chain(Function, Function, Function)}
+ */
+ public static <A,B,C,D> Function<A,D> chain(final Function<A,? extends B> f1, final Function<B,? extends C> f2, final Function<C,D> f3) {
+ return Functionals.chain(f1, f2, f3);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/test/java/org/apache/brooklyn/feed/http/JsonFunctionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/feed/http/JsonFunctionsTest.java b/core/src/test/java/org/apache/brooklyn/feed/http/JsonFunctionsTest.java
index 928035e..ba654a4 100644
--- a/core/src/test/java/org/apache/brooklyn/feed/http/JsonFunctionsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/feed/http/JsonFunctionsTest.java
@@ -20,10 +20,9 @@ package org.apache.brooklyn.feed.http;
import java.util.NoSuchElementException;
-import org.apache.brooklyn.feed.http.JsonFunctions;
import org.apache.brooklyn.util.collections.Jsonya;
-import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.Jsonya.Navigator;
+import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.guava.Functionals;
import org.apache.brooklyn.util.guava.Maybe;
import org.testng.Assert;
@@ -78,12 +77,18 @@ public class JsonFunctionsTest {
Assert.assertTrue(m.isAbsent());
}
- @Test(expectedExceptions=Exception.class)
- public void testWalkMWrong2() {
- Maybe<JsonElement> m = JsonFunctions.walkM("europe", "spain", "barcelona").apply( Maybe.of( europeMap()) );
+ @Test(expectedExceptions=IllegalStateException.class)
+ public void testCastMWhenAbsent() {
+// Maybe<JsonElement> m = JsonFunctions.walkM("europe", "spain", "barcelona").apply( Maybe.of( europeMap()) );
+ Maybe<JsonElement> m = Maybe.absent();
JsonFunctions.castM(String.class).apply(m);
}
+ @Test(expectedExceptions=UnsupportedOperationException.class)
+ public void testCastMWrong() {
+ Maybe<JsonElement> m = JsonFunctions.walkM("europe", "france").apply( Maybe.of( europeMap()) );
+ JsonFunctions.castM(String.class).apply(m);
+ }
@Test
public void testWalkN() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/core/src/test/java/org/apache/brooklyn/feed/ssh/SshValueFunctionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/feed/ssh/SshValueFunctionsTest.java b/core/src/test/java/org/apache/brooklyn/feed/ssh/SshValueFunctionsTest.java
new file mode 100644
index 0000000..51e818f
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/feed/ssh/SshValueFunctionsTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.brooklyn.feed.ssh;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+public class SshValueFunctionsTest {
+
+ private SshPollValue val = new SshPollValue(null, 123, "mystdout", "mystderr");
+
+ @Test
+ public void testExitCode() throws Exception {
+ assertEquals(SshValueFunctions.exitStatus().apply(val), (Integer)123);
+ }
+
+ @Test
+ public void testStdout() throws Exception {
+ assertEquals(SshValueFunctions.stdout().apply(val), "mystdout");
+ }
+
+ @Test
+ public void testStderr() throws Exception {
+ assertEquals(SshValueFunctions.stderr().apply(val), "mystderr");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/software/base/src/main/java/org/apache/brooklyn/feed/jmx/JmxValueFunctions.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/feed/jmx/JmxValueFunctions.java b/software/base/src/main/java/org/apache/brooklyn/feed/jmx/JmxValueFunctions.java
index 5741099..a0549b2 100644
--- a/software/base/src/main/java/org/apache/brooklyn/feed/jmx/JmxValueFunctions.java
+++ b/software/base/src/main/java/org/apache/brooklyn/feed/jmx/JmxValueFunctions.java
@@ -24,40 +24,81 @@ import java.util.Map;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
+import org.apache.brooklyn.api.location.Location;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
+import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
public class JmxValueFunctions {
private static final Logger log = LoggerFactory.getLogger(JmxValueFunctions.class);
-
- /**
- * @return a closure that converts a TabularDataSupport to a map.
- */
- public static Function<TabularData, Map> tabularDataToMap() {
+
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<TabularData, Map> tabularDataToMapOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<TabularData, Map>() {
@Override public Map apply(TabularData input) {
return tabularDataToMap(input);
}};
}
- public static Function<TabularData, Map> tabularDataToMapOfMaps() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<TabularData, Map> tabularDataToMapOfMapsOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<TabularData, Map>() {
@Override public Map apply(TabularData input) {
return tabularDataToMapOfMaps(input);
}};
}
- public static Function<CompositeData,Map> compositeDataToMap() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<CompositeData,Map> compositeDataToMapOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<CompositeData, Map>() {
@Override public Map apply(CompositeData input) {
return compositeDataToMap(input);
}};
}
+ /**
+ * @return a closure that converts a TabularDataSupport to a map.
+ */
+ public static Function<TabularData, Map> tabularDataToMap() {
+ return new TabularDataToMap();
+ }
+
+ protected static class TabularDataToMap implements Function<TabularData, Map> {
+ @Override public Map apply(TabularData input) {
+ return tabularDataToMap(input);
+ }
+ }
+
+ public static Function<TabularData, Map> tabularDataToMapOfMaps() {
+ return new TabularDataToMapOfMaps();
+ }
+
+ protected static class TabularDataToMapOfMaps implements Function<TabularData, Map> {
+ @Override public Map apply(TabularData input) {
+ return tabularDataToMapOfMaps(input);
+ }
+ }
+
+ public static Function<CompositeData,Map> compositeDataToMap() {
+ return new CompositeDataToMap();
+ }
+
+ protected static class CompositeDataToMap implements Function<CompositeData, Map> {
+ @Override public Map apply(CompositeData input) {
+ return compositeDataToMap(input);
+ }
+ }
+
public static Map tabularDataToMap(TabularData table) {
Map<String, Object> result = Maps.newLinkedHashMap();
for (Object entry : table.values()) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxValueFunctionsTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxValueFunctionsTest.java b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxValueFunctionsTest.java
new file mode 100644
index 0000000..83f4899
--- /dev/null
+++ b/software/base/src/test/java/org/apache/brooklyn/feed/jmx/JmxValueFunctionsTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.brooklyn.feed.jmx;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class JmxValueFunctionsTest {
+
+ @Test
+ public void testCompositeDataToMap() throws Exception {
+ CompositeType compositeType = new CompositeType(
+ "MyCompositeType",
+ "my composite descr",
+ new String[] {"key1", "key2"},
+ new String[] {"key1 descr", "key2 descr"},
+ new OpenType[] {SimpleType.STRING, SimpleType.STRING});
+ Map<String, ?> items = ImmutableMap.of(
+ "key1", "val1",
+ "key2", "val2");
+ CompositeData data = new CompositeDataSupport(compositeType, items);
+
+ Map<String,?> result = JmxValueFunctions.compositeDataToMap(data);
+ assertEquals(result, items);
+
+ Map<?,?> result2 = JmxValueFunctions.compositeDataToMap().apply(data);
+ assertEquals(result2, items);
+ }
+
+ @Test
+ public void testTabularDataToMapOfMaps() throws Exception {
+ CompositeType rowType = new CompositeType(
+ "MyRowType",
+ "my row descr",
+ new String[] {"key1", "key2"},
+ new String[] {"key1 descr", "key2 descr"},
+ new OpenType[] {SimpleType.STRING, SimpleType.STRING});
+ TabularType tabularType = new TabularType(
+ "MyTabularType",
+ "my table descr",
+ rowType,
+ new String[] {"key1"});
+ Map<String, ?> row1 = ImmutableMap.of(
+ "key1", "row1.val1",
+ "key2", "row1.val2");
+ Map<String, ?> row2 = ImmutableMap.of(
+ "key1", "row2.val1",
+ "key2", "row2.val2");
+ TabularDataSupport table = new TabularDataSupport(tabularType);
+ table.put(new CompositeDataSupport(rowType, row1));
+ table.put(new CompositeDataSupport(rowType, row2));
+
+ Map<List<?>, Map<String, Object>> result = JmxValueFunctions.tabularDataToMapOfMaps(table);
+ assertEquals(result, ImmutableMap.of(ImmutableList.of("row1.val1"), row1, ImmutableList.of("row2.val1"), row2));
+
+ Map<?,?> result2 = JmxValueFunctions.tabularDataToMapOfMaps().apply(table);
+ assertEquals(result2, ImmutableMap.of(ImmutableList.of("row1.val1"), row1, ImmutableList.of("row2.val1"), row2));
+ }
+
+ @Test
+ public void testTabularDataToMap() throws Exception {
+ CompositeType rowType = new CompositeType(
+ "MyRowType",
+ "my row descr",
+ new String[] {"key1", "key2"},
+ new String[] {"key1 descr", "key2 descr"},
+ new OpenType[] {SimpleType.STRING, SimpleType.STRING});
+ TabularType tabularType = new TabularType(
+ "MyTabularType",
+ "my table descr",
+ rowType,
+ new String[] {"key1"});
+ Map<String, ?> row1 = ImmutableMap.of(
+ "key1", "row1.val1",
+ "key2", "row1.val2");
+ Map<String, ?> row2 = ImmutableMap.of(
+ "key1", "row2.val1",
+ "key2", "row2.val2");
+ TabularDataSupport table = new TabularDataSupport(tabularType);
+ table.put(new CompositeDataSupport(rowType, row1));
+ table.put(new CompositeDataSupport(rowType, row2));
+
+ Map<?,?> result = JmxValueFunctions.tabularDataToMap(table);
+ assertEquals(result, row2);
+
+ Map<?,?> result2 = JmxValueFunctions.tabularDataToMap().apply(table);
+ assertEquals(result2, row2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java
index 905135c..70769dd 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/MaybeFunctions.java
@@ -22,7 +22,10 @@ import com.google.common.base.Function;
public class MaybeFunctions {
- public static <T> Function<T, Maybe<T>> wrap() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<T, Maybe<T>> wrapOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<T, Maybe<T>>() {
@Override
public Maybe<T> apply(T input) {
@@ -31,7 +34,10 @@ public class MaybeFunctions {
};
}
- public static <T> Function<Maybe<T>, T> get() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<Maybe<T>, T> getOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Maybe<T>, T>() {
@Override
public T apply(Maybe<T> input) {
@@ -40,7 +46,10 @@ public class MaybeFunctions {
};
}
- public static <T> Function<Maybe<T>, T> or(final T value) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<Maybe<T>, T> orOld(final T value) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Maybe<T>, T>() {
@Override
public T apply(Maybe<T> input) {
@@ -49,4 +58,41 @@ public class MaybeFunctions {
};
}
+ public static <T> Function<T, Maybe<T>> wrap() {
+ return new WrapMaybe<T>();
+ }
+
+ protected static class WrapMaybe<T> implements Function<T, Maybe<T>> {
+ @Override
+ public Maybe<T> apply(T input) {
+ return Maybe.fromNullable(input);
+ }
+ };
+
+ public static <T> Function<Maybe<T>, T> get() {
+ return new GetMaybe<T>();
+ }
+
+ protected static class GetMaybe<T> implements Function<Maybe<T>, T> {
+ @Override
+ public T apply(Maybe<T> input) {
+ return input.get();
+ }
+ }
+
+ public static <T> Function<Maybe<T>, T> or(final T value) {
+ return new OrMaybe<T>(value);
+ }
+
+ protected static class OrMaybe<T> implements Function<Maybe<T>, T> {
+ private final T value;
+
+ public OrMaybe(T value) {
+ this.value = value;
+ }
+ @Override
+ public T apply(Maybe<T> input) {
+ return input.or(value);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/utils/common/src/main/java/org/apache/brooklyn/util/math/MathFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/math/MathFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/math/MathFunctions.java
index 92dbe36..865aca3 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/math/MathFunctions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/math/MathFunctions.java
@@ -20,13 +20,17 @@ package org.apache.brooklyn.util.math;
import javax.annotation.Nullable;
+import org.apache.brooklyn.util.guava.Functionals;
import org.apache.brooklyn.util.text.Strings;
import com.google.common.base.Function;
public class MathFunctions {
- public static Function<Number, Integer> plus(final int addend) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Integer> plusOld(final int addend) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Integer>() {
public Integer apply(@Nullable Number input) {
if (input==null) return null;
@@ -35,7 +39,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Long> plus(final long addend) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Long> plusOld(final long addend) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Long>() {
public Long apply(@Nullable Number input) {
if (input==null) return null;
@@ -44,7 +51,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Double> plus(final double addend) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Double> plusOld(final double addend) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Double>() {
public Double apply(@Nullable Number input) {
if (input==null) return null;
@@ -53,7 +63,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Integer> times(final int multiplicand) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Integer> timesOld(final int multiplicand) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Integer>() {
public Integer apply(@Nullable Number input) {
if (input==null) return null;
@@ -62,7 +75,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Long> times(final long multiplicand) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Long> timesOld(final long multiplicand) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Long>() {
public Long apply(@Nullable Number input) {
if (input==null) return null;
@@ -71,7 +87,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Double> times(final double multiplicand) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Double> timesOld(final double multiplicand) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Double>() {
public Double apply(@Nullable Number input) {
if (input==null) return null;
@@ -80,7 +99,10 @@ public class MathFunctions {
};
}
- public static Function<Number, Double> divide(final double divisor) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, Double> divideOld(final double divisor) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, Double>() {
public Double apply(@Nullable Number input) {
if (input==null) return null;
@@ -89,7 +111,10 @@ public class MathFunctions {
};
}
- public static <T> Function<T, Double> divide(final Function<T, ? extends Number> input, final double divisor) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static <T> Function<T, Double> divideOld(final Function<T, ? extends Number> input, final double divisor) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<T, Double>() {
public Double apply(@Nullable T input2) {
if (input==null) return null;
@@ -101,7 +126,10 @@ public class MathFunctions {
}
/** returns a string of up to maxLen length (longer in extreme cases) also capped at significantDigits significantDigits */
- public static Function<Number, String> readableString(final int significantDigits, final int maxLen) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, String> readableStringOld(final int significantDigits, final int maxLen) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, String>() {
public String apply(@Nullable Number input) {
if (input==null) return null;
@@ -111,7 +139,10 @@ public class MathFunctions {
}
/** returns a string where the input number is expressed as percent, with given number of significant digits */
- public static Function<Number, String> percent(final int significantDigits) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Number, String> percentOld(final int significantDigits) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Number, String>() {
public String apply(@Nullable Number input) {
if (input==null) return null;
@@ -120,4 +151,157 @@ public class MathFunctions {
};
}
+ public static Function<Number, Integer> plus(int addend) {
+ return new PlusInt(addend);
+ }
+
+ protected static class PlusInt implements Function<Number, Integer> {
+ private final int addend;
+
+ public PlusInt(int addend) {
+ this.addend = addend;
+ }
+ public Integer apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.intValue() + addend;
+ }
+ }
+
+ public static Function<Number, Long> plus(long addend) {
+ return new PlusLong(addend);
+ }
+
+ protected static class PlusLong implements Function<Number, Long> {
+ private final long addend;
+
+ public PlusLong(long addend) {
+ this.addend = addend;
+ }
+ public Long apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.longValue() + addend;
+ }
+ }
+
+ public static Function<Number, Double> plus(final double addend) {
+ return new PlusDouble(addend);
+ }
+
+ protected static class PlusDouble implements Function<Number, Double> {
+ private final double addend;
+
+ public PlusDouble(double addend) {
+ this.addend = addend;
+ }
+ public Double apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.doubleValue() + addend;
+ }
+ }
+
+ public static Function<Number, Integer> times(final int multiplicand) {
+ return new TimesInt(multiplicand);
+ }
+
+ protected static class TimesInt implements Function<Number, Integer> {
+ private final int multiplicand;
+
+ public TimesInt(int multiplicand) {
+ this.multiplicand = multiplicand;
+ }
+ public Integer apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.intValue() * multiplicand;
+ }
+ }
+
+ public static Function<Number, Long> times(long multiplicand) {
+ return new TimesLong(multiplicand);
+ }
+
+ protected static class TimesLong implements Function<Number, Long> {
+ private final long multiplicand;
+
+ public TimesLong(long multiplicand) {
+ this.multiplicand = multiplicand;
+ }
+ public Long apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.longValue() * multiplicand;
+ }
+ }
+
+ public static Function<Number, Double> times(final double multiplicand) {
+ return new TimesDouble(multiplicand);
+ }
+
+ protected static class TimesDouble implements Function<Number, Double> {
+ private final double multiplicand;
+
+ public TimesDouble(double multiplicand) {
+ this.multiplicand = multiplicand;
+ }
+ public Double apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.doubleValue() * multiplicand;
+ }
+ }
+
+ public static Function<Number, Double> divide(double divisor) {
+ return new DivideDouble(divisor);
+ }
+
+ protected static class DivideDouble implements Function<Number, Double> {
+ private final double divisor;
+
+ public DivideDouble(double divisor) {
+ this.divisor = divisor;
+ }
+ public Double apply(@Nullable Number input) {
+ if (input==null) return null;
+ return input.doubleValue() / divisor;
+ }
+ }
+
+ /**
+ * @deprecated since 0.9.0; use {@link Functionals#chain(Function, Function)} and {@link MathFunctions#divide(double)}
+ */
+ public static <T> Function<T, Double> divide(final Function<T, ? extends Number> preprocessor, final double divisor) {
+ return Functionals.chain(preprocessor, divide(divisor));
+ }
+
+ /** returns a string of up to maxLen length (longer in extreme cases) also capped at significantDigits significantDigits */
+ public static Function<Number, String> readableString(int significantDigits, int maxLen) {
+ return new ReadableString(significantDigits, maxLen);
+ }
+
+ protected static class ReadableString implements Function<Number, String> {
+ private final int significantDigits;
+ private final int maxLen;
+ public ReadableString(int significantDigits, int maxLen) {
+ this.significantDigits = significantDigits;
+ this.maxLen = maxLen;
+ }
+ public String apply(@Nullable Number input) {
+ if (input==null) return null;
+ return Strings.makeRealString(input.doubleValue(), maxLen, significantDigits, 0);
+ }
+ };
+
+ /** returns a string where the input number is expressed as percent, with given number of significant digits */
+ public static Function<Number, String> percent(int significantDigits) {
+ return new Percent(significantDigits);
+ }
+
+ private static class Percent implements Function<Number, String> {
+ final int significantDigits;
+ public Percent(int significantDigits) {
+ this.significantDigits = significantDigits;
+ }
+
+ public String apply(@Nullable Number input) {
+ if (input==null) return null;
+ return readableString(significantDigits, significantDigits+3).apply(input.doubleValue() * 100d)+"%";
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f22b3eb4/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
index 8ac249d..dd9a980 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
@@ -18,7 +18,7 @@
*/
package org.apache.brooklyn.util.text;
-import java.util.List;
+import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
@@ -31,7 +31,10 @@ import com.google.common.collect.Iterables;
public class StringFunctions {
- public static Function<String,String> append(final String suffix) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String,String> appendOld(final String suffix) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
@Nullable
@@ -42,7 +45,10 @@ public class StringFunctions {
};
}
- public static Function<String,String> prepend(final String prefix) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String,String> prependOld(final String prefix) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
@Nullable
@@ -53,8 +59,10 @@ public class StringFunctions {
};
}
- /** given e.g. "hello %s" returns a function which will insert a string into that pattern */
- public static Function<Object, String> formatter(final String pattern) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Object, String> formatterOld(final String pattern) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Object, String>() {
public String apply(@Nullable Object input) {
return String.format(pattern, input);
@@ -62,8 +70,10 @@ public class StringFunctions {
};
}
- /** given e.g. "hello %s %s" returns a function which will insert an array of two strings into that pattern */
- public static Function<Object[], String> formatterForArray(final String pattern) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Object[], String> formatterForArrayOld(final String pattern) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Object[], String>() {
public String apply(@Nullable Object[] input) {
return String.format(pattern, input);
@@ -71,18 +81,10 @@ public class StringFunctions {
};
}
- /** given e.g. "hello %s %s" returns a function which will insert an Iterable of two strings into that pattern */
- public static Function<Iterable<?>, String> formatterForIterable(final String pattern) {
- return new Function<Iterable<?>, String>() {
- public String apply(@Nullable Iterable<?> input) {
- Object[] arr = (input == null) ? null : Iterables.toArray(input, Object.class);
- return String.format(pattern, arr);
- }
- };
- }
-
- /** joins the given objects in a collection as a toString with the given separator */
- public static Function<Iterable<?>, String> joiner(final String separator) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Iterable<?>, String> joinerOld(final String separator) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Iterable<?>, String>() {
public String apply(@Nullable Iterable<?> input) {
return Strings.join(input, separator);
@@ -90,8 +92,10 @@ public class StringFunctions {
};
}
- /** joins the given objects as a toString with the given separator, but expecting an array of objects, not a collection */
- public static Function<Object[], String> joinerForArray(final String separator) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<Object[], String> joinerForArrayOld(final String separator) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<Object[], String>() {
public String apply(@Nullable Object[] input) {
if (input == null) return Strings.EMPTY;
@@ -100,13 +104,10 @@ public class StringFunctions {
};
}
- /** provided here as a convenience; prefer {@link Functions#toStringFunction()} */
- public static Function<Object,String> toStringFunction() {
- return Functions.toStringFunction();
- }
-
- /** returns function which gives length of input, with -1 for nulls */
- public static Function<String,Integer> length() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String,Integer> lengthOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String,Integer>() {
@Override
public Integer apply(@Nullable String input) {
@@ -116,10 +117,10 @@ public class StringFunctions {
};
}
- /** Surrounds an input string with the given prefix and suffix */
- public static Function<String,String> surround(final String prefix, final String suffix) {
- Preconditions.checkNotNull(prefix);
- Preconditions.checkNotNull(suffix);
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String,String> surroundOld(final String prefix, final String suffix) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String,String>() {
@Override
public String apply(@Nullable String input) {
@@ -129,7 +130,10 @@ public class StringFunctions {
};
}
- public static Function<String, String> trim() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String, String> trimOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
public String apply(@Nullable String input) {
@@ -140,7 +144,10 @@ public class StringFunctions {
};
}
- public static Function<String, String> toLowerCase() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String, String> toLowerCaseOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
public String apply(String input) {
@@ -149,7 +156,10 @@ public class StringFunctions {
};
}
- public static Function<String, String> toUpperCase() {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String, String> toUpperCaseOld() {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
public String apply(String input) {
@@ -158,7 +168,10 @@ public class StringFunctions {
};
}
- public static Function<String, String> convertCase(final CaseFormat src, final CaseFormat target) {
+ /** @deprecated since 0.9.0 kept only to allow conversion of anonymous inner classes */
+ @SuppressWarnings("unused") @Deprecated
+ private static Function<String, String> convertCaseOld(final CaseFormat src, final CaseFormat target) {
+ // TODO PERSISTENCE WORKAROUND
return new Function<String, String>() {
@Override
public String apply(String input) {
@@ -166,4 +179,220 @@ public class StringFunctions {
}
};
}
+
+ public static Function<String,String> append(final String suffix) {
+ return new AppendFunction(checkNotNull(suffix, "suffix"));
+ }
+
+ private static class AppendFunction implements Function<String, String> {
+ private final String suffix;
+
+ public AppendFunction(String suffix) {
+ this.suffix = suffix;
+ }
+ @Override
+ @Nullable
+ public String apply(@Nullable String input) {
+ if (input==null) return null;
+ return input + suffix;
+ }
+ };
+
+ public static Function<String,String> prepend(final String prefix) {
+ return new PrependFunction(checkNotNull(prefix, "prefix"));
+ }
+
+ protected static class PrependFunction implements Function<String, String> {
+ private final String prefix;
+
+ public PrependFunction(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ @Nullable
+ public String apply(@Nullable String input) {
+ if (input==null) return null;
+ return prefix + input;
+ }
+ }
+
+ /** given e.g. "hello %s" returns a function which will insert a string into that pattern */
+ public static Function<Object, String> formatter(final String pattern) {
+ return new FormatterFunction(pattern);
+ }
+
+ protected static class FormatterFunction implements Function<Object, String> {
+ private final String pattern;
+
+ FormatterFunction(String pattern) {
+ this.pattern = pattern;
+ }
+ public String apply(@Nullable Object input) {
+ return String.format(pattern, input);
+ }
+ };
+
+ /** given e.g. "hello %s %s" returns a function which will insert an array of two strings into that pattern */
+ public static Function<Object[], String> formatterForArray(final String pattern) {
+ return new FormatterForArrayFunction(checkNotNull(pattern, "pattern"));
+ }
+
+ protected static class FormatterForArrayFunction implements Function<Object[], String> {
+ private final String pattern;
+
+ public FormatterForArrayFunction(String pattern) {
+ this.pattern = pattern;
+ }
+ public String apply(@Nullable Object[] input) {
+ return String.format(pattern, input);
+ }
+ }
+
+ /**
+ * Given e.g. "hello %s %s" returns a function which will insert an Iterable of two strings into that pattern
+ *
+ * @since 0.9.0
+ */
+ public static Function<Iterable<?>, String> formatterForIterable(final String pattern) {
+ return new FormatterForIterableFunction(pattern);
+ }
+
+ protected static class FormatterForIterableFunction implements Function<Iterable<?>, String> {
+ final String pattern;
+
+ public FormatterForIterableFunction(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public String apply(@Nullable Iterable<?> input) {
+ Object[] arr = (input == null) ? null : Iterables.toArray(input, Object.class);
+ return String.format(pattern, arr);
+ }
+ }
+
+ /** joins the given objects in a collection as a toString with the given separator */
+ public static Function<Iterable<?>, String> joiner(final String separator) {
+ return new JoinerFunction(separator);
+ }
+
+ private static class JoinerFunction implements Function<Iterable<?>, String> {
+ private final String separator;
+
+ public JoinerFunction(String separator) {
+ this.separator = separator;
+ }
+ public String apply(@Nullable Iterable<?> input) {
+ return Strings.join(input, separator);
+ }
+ }
+
+ /** joins the given objects as a toString with the given separator, but expecting an array of objects, not a collection */
+ public static Function<Object[], String> joinerForArray(final String separator) {
+ return new JoinerForArrayFunction(checkNotNull(separator, "separator"));
+ }
+
+ private static class JoinerForArrayFunction implements Function<Object[], String> {
+ private final String separator;
+
+ protected JoinerForArrayFunction(String separator) {
+ this.separator = separator;
+ }
+ public String apply(@Nullable Object[] input) {
+ if (input == null) return Strings.EMPTY;
+ return Strings.join(input, separator);
+ }
+ }
+
+ /** provided here as a convenience; prefer {@link Functions#toStringFunction()} */
+ public static Function<Object,String> toStringFunction() {
+ return Functions.toStringFunction();
+ }
+
+ /** returns function which gives length of input, with -1 for nulls */
+ public static Function<String,Integer> length() {
+ return new LengthFunction();
+ }
+
+ protected static class LengthFunction implements Function<String,Integer> {
+ @Override
+ public Integer apply(@Nullable String input) {
+ if (input == null) return -1;
+ return input.length();
+ }
+ }
+
+ /** Surrounds an input string with the given prefix and suffix */
+ public static Function<String,String> surround(final String prefix, final String suffix) {
+ Preconditions.checkNotNull(prefix);
+ Preconditions.checkNotNull(suffix);
+ return new SurroundFunction(prefix, suffix);
+ }
+
+ protected static class SurroundFunction implements Function<String,String> {
+ private final String prefix;
+ private final String suffix;
+ public SurroundFunction(String prefix, String suffix) {
+ this.prefix = prefix;
+ this.suffix = suffix;
+ }
+ @Override
+ public String apply(@Nullable String input) {
+ if (input == null) return null;
+ return prefix+input+suffix;
+ }
+ }
+
+ public static Function<String, String> trim() {
+ return new TrimFunction();
+ }
+
+ protected static class TrimFunction implements Function<String, String> {
+ @Override
+ public String apply(@Nullable String input) {
+ if (input == null) return null;
+ if (Strings.isBlank(input)) return Strings.EMPTY;
+ return CharMatcher.BREAKING_WHITESPACE.trimFrom(input);
+ }
+ }
+
+ public static Function<String, String> toLowerCase() {
+ return new LowerCaseFunction();
+ }
+
+ protected static class LowerCaseFunction implements Function<String, String> {
+ @Override
+ public String apply(String input) {
+ return input.toLowerCase();
+ }
+ }
+
+ public static Function<String, String> toUpperCase() {
+ return new UpperCaseFunction();
+ }
+
+ protected static class UpperCaseFunction implements Function<String, String> {
+ @Override
+ public String apply(String input) {
+ return input.toUpperCase();
+ }
+ }
+
+ public static Function<String, String> convertCase(final CaseFormat src, final CaseFormat target) {
+ return new ConvertCaseFunction(checkNotNull(src, "src"), checkNotNull(target, "target"));
+ }
+
+ protected static class ConvertCaseFunction implements Function<String, String> {
+ private final CaseFormat src;
+ private final CaseFormat target;
+
+ public ConvertCaseFunction(CaseFormat src, CaseFormat target) {
+ this.src = src;
+ this.target = target;
+ }
+ @Override
+ public String apply(String input) {
+ return src.to(target, input);
+ }
+ }
}