brooklyn.util.internal.LanguageUtils.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of brooklyn-utils-groovy
Show all versions of brooklyn-utils-groovy
Groovy extensions and utility classes and methods developed for Brooklyn but not dependendent on Brooklyn or much else
package brooklyn.util.internal
import java.lang.reflect.Field
import java.lang.reflect.Method;
import java.lang.reflect.Modifier
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong
import brooklyn.util.javalang.Reflections;
import brooklyn.util.text.Identifiers
import com.google.common.annotations.Beta
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.thoughtworks.xstream.XStream
/**
* Useful Groovy utility methods.
*
* @deprecated since 0.5; requires thorough review for what will be kept.
* e.g. consider instead using guava's {@link com.google.common.collect.Multimap} instead of addToMapOfSets etc
*/
@Deprecated
@Beta
public class LanguageUtils {
// For unique identifiers
private static final AtomicLong seed = new AtomicLong(0L)
public static T getRequiredField(String name, Map,?> m) {
if (!m.containsKey(name))
throw new IllegalArgumentException("a parameter '"+name+"' was required in the argument to this function")
m.get name
}
public static T getOptionalField(String name, Map,?> m, T defaultValue=null) {
m.get(name) ?: defaultValue
}
public static T getPropertySafe(Object target, String name, T defaultValue=null) {
target.hasProperty(name)?.getProperty(target) ?: defaultValue
}
//TODO find with annotation
public static byte[] serialize(Object orig) {
if (orig == null) return null;
// Write the object out to a byte array
ByteArrayOutputStream fbos = []
ObjectOutputStream out = new ObjectOutputStream(fbos);
out.writeObject(orig);
out.flush();
out.close();
return fbos.toByteArray();
}
public static T deserialize(byte[] bytes, ClassLoader classLoader) {
if (bytes == null) return null;
ObjectInputStream ins =
//new ObjectInputStreamWithLoader(new FastByteArrayInputStream(bytes, bytes.length), classLoader);
new ObjectInputStream(new ByteArrayInputStream(bytes));
(T) ins.readObject();
}
public static T clone(T src) {
XStream xstream = new XStream();
xstream.setClassLoader(src.getClass().getClassLoader())
xstream.fromXML(xstream.toXML(src))
}
/**
* @deprecated use Identifiers.makeRandomId(8)
*/
@Deprecated
public static String newUid() { Identifiers.makeRandomId(8) }
public static Map setFieldsFromMap(Object target, Map fieldValues) {
Map unused = [:]
fieldValues.each {
// println "looking for "+it.key+" in "+target+": "+target.metaClass.hasProperty(it.key)
target.hasProperty(it.key) ? target.(it.key) = it.value : unused << it
}
unused
}
/**
* Adds the given value to a collection in the map under the key.
*
* A collection (as {@link LinkedHashMap}) will be created if necessary,
* synchronized on map for map access/change and set for addition there
*
* @return the updated set (instance, not copy)
*
* @deprecated since 0.5; use {@link HashMultimap}, and {@link Multimaps#synchronizedSetMultimap(com.google.common.collect.SetMultimap)}
*/
@Deprecated
public static Set addToMapOfSets(Map> map, K key, V valueInCollection) {
Set coll;
synchronized (map) {
coll = map.get(key)
if (coll==null) {
coll = new LinkedHashSet()
map.put(key, coll)
}
if (coll.isEmpty()) {
synchronized (coll) {
coll.add(valueInCollection)
}
//if collection was empty then add to the collection while holding the map lock, to prevent removal
return coll
}
}
synchronized (coll) {
if (!coll.isEmpty()) {
coll.add(valueInCollection)
return coll;
}
}
//if was empty, recurse, because someone else might be removing the collection
return addToMapOfSets(map, key, valueInCollection);
}
/**
* as {@link #addToMapOfSets(Map, Object, Object)} but for {@link ArrayList}
*
* @deprecated since 0.5; use {@link ArrayListMultimap}, and {@link Multimaps#synchronizedListMultimap(com.google.common.collect.ListMultimap)}
*/
@Deprecated
public static List addToMapOfLists(Map> map, K key, V valueInCollection) {
List coll;
synchronized (map) {
coll = map.get(key)
if (coll==null) {
coll = new ArrayList()
map.put(key, coll)
}
if (coll.isEmpty()) {
synchronized (coll) {
coll.add(valueInCollection)
}
//if collection was empty then add to the collection while holding the map lock, to prevent removal
return coll
}
}
synchronized (coll) {
if (!coll.isEmpty()) {
coll.add(valueInCollection)
return coll;
}
}
//if was empty, recurse, because someone else might be removing the collection
return addToMapOfLists(map, key, valueInCollection);
}
/**
* Removes the given value from a collection in the map under the key.
*
* @return the updated set (instance, not copy)
*
* @deprecated since 0.5; use {@link ArrayListMultimap} or {@link HashMultimap}, and {@link Multimaps#synchronizedListMultimap(com.google.common.collect.ListMultimap)} etc
*/
@Deprecated
public static boolean removeFromMapOfCollections(Map> map, K key, V valueInCollection) {
Collection coll;
synchronized (map) {
coll = map.get(key)
if (coll==null) return false;
}
boolean result;
synchronized (coll) {
result = coll.remove(valueInCollection)
}
if (coll.isEmpty()) {
synchronized (map) {
synchronized (coll) {
if (coll.isEmpty()) {
//only remove from the map if no one is adding to the collection or to the map, and the collection is still in the map
if (map.get(key)==coll) {
map.remove(key)
}
}
}
}
}
return result;
}
/**
* Visits all fields of a given object, recursively.
*
* For collections, arrays, and maps it visits the items within, passing null for keys where it isn't a map.
*/
public static void visitFields(Object o, FieldVisitor fv, Collection