You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/08/30 01:01:08 UTC

[08/26] git commit: rename WhenFunctions class to IfFunctions, and tidies/cleanups there and in enrichers

rename WhenFunctions class to IfFunctions, and tidies/cleanups there and in enrichers


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/bc1d19f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/bc1d19f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/bc1d19f7

Branch: refs/heads/master
Commit: bc1d19f755bc32a5ed5ec84ba50198fa39ba47bb
Parents: c1ebb8f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 12 10:50:46 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Aug 27 02:07:49 2014 -0400

----------------------------------------------------------------------
 .../java/brooklyn/entity/basic/EntityLocal.java |   1 -
 .../enricher/basic/AbstractEnricher.java        |  20 +-
 .../basic/AbstractTypeTransformingEnricher.java |   1 +
 .../brooklyn/enricher/basic/Aggregator.java     |  12 +-
 .../java/brooklyn/enricher/basic/Combiner.java  |  10 +-
 .../brooklyn/enricher/basic/Propagator.java     |   4 +-
 .../basic/SensorPropagatingEnricher.java        |   1 +
 .../brooklyn/enricher/basic/Transformer.java    |  11 +-
 .../entity/basic/ServiceStatusLogic.java        |  31 ++-
 .../policy/basic/AbstractEntityAdjunct.java     |  16 +-
 .../java/brooklyn/enricher/EnrichersTest.java   |   4 +-
 .../entity/basic/SoftwareProcessImpl.java       |  26 ++-
 .../basic/lifecycle/ScriptHelperTest.java       |  36 +++-
 .../entity/webapp/jboss/JBoss7ServerImpl.java   |  10 +-
 .../util/collections/CollectionFunctionals.java |  97 +++++++---
 .../java/brooklyn/util/guava/Functionals.java   |  53 ++++--
 .../java/brooklyn/util/guava/IfFunctions.java   | 158 +++++++++++++++
 .../java/brooklyn/util/guava/WhenFunctions.java | 190 -------------------
 .../collections/CollectionFunctionalsTest.java  |  51 +++++
 .../brooklyn/util/guava/FunctionalsTest.java    |  18 +-
 .../brooklyn/util/guava/IfFunctionsTest.java    | 101 ++++++++++
 .../brooklyn/util/guava/WhenFunctionsTest.java  |  91 ---------
 22 files changed, 536 insertions(+), 406 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/api/src/main/java/brooklyn/entity/basic/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/entity/basic/EntityLocal.java b/api/src/main/java/brooklyn/entity/basic/EntityLocal.java
index c8a18b5..b38a3d8 100644
--- a/api/src/main/java/brooklyn/entity/basic/EntityLocal.java
+++ b/api/src/main/java/brooklyn/entity/basic/EntityLocal.java
@@ -35,7 +35,6 @@ import brooklyn.management.SubscriptionManager;
 import brooklyn.management.Task;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
 
 /** 
  * Extended Entity interface for use in places where the caller should have certain privileges,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
index 52a924a..d462a0c 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractEnricher.java
@@ -24,6 +24,8 @@ import java.util.Map;
 
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.rebind.BasicEnricherRebindSupport;
 import brooklyn.entity.rebind.RebindSupport;
@@ -33,6 +35,7 @@ import brooklyn.mementos.EnricherMemento;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherType;
 import brooklyn.policy.basic.AbstractEntityAdjunct;
+import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.Maps;
@@ -84,20 +87,27 @@ public abstract class AbstractEnricher extends AbstractEntityAdjunct implements
     }
 
     @Override
-    protected <T> void emit(Sensor<T> sensor, T val) {
+    protected <T> void emit(Sensor<T> sensor, Object val) {
         checkState(entity != null, "entity must first be set");
+        if (val == Entities.UNCHANGED) {
+            return;
+        }
+        if (val == Entities.REMOVE) {
+            ((EntityInternal)entity).removeAttribute((AttributeSensor<T>) sensor);
+            return;
+        }
         
+        T newVal = TypeCoercions.coerce(val, sensor.getTypeToken());
         if (sensor instanceof AttributeSensor) {
             if (Boolean.TRUE.equals(suppressDuplicates)) {
                 T oldValue = entity.getAttribute((AttributeSensor<T>)sensor);
-                if (Objects.equal(oldValue, val))
+                if (Objects.equal(oldValue, newVal))
                     return;
             }
-            entity.setAttribute((AttributeSensor<T>)sensor, val);
+            entity.setAttribute((AttributeSensor<T>)sensor, newVal);
         } else { 
-            entity.emit(sensor, val);
+            entity.emit(sensor, newVal);
         }
-
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java b/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
index 05f96cd..27eac93 100644
--- a/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/AbstractTypeTransformingEnricher.java
@@ -51,6 +51,7 @@ public abstract class AbstractTypeTransformingEnricher<T,U> extends AbstractEnri
         this.target = target;
     }
     
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     public void setEntity(EntityLocal entity) {
         super.setEntity(entity);
         if (producer==null) producer = entity;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Aggregator.java b/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
index f5d503f..fed403e 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Aggregator.java
@@ -35,7 +35,6 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.Group;
 import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.trait.Changeable;
 import brooklyn.event.AttributeSensor;
@@ -45,7 +44,6 @@ import brooklyn.event.SensorEventListener;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -53,6 +51,7 @@ import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 import com.google.common.reflect.TypeToken;
 
+@SuppressWarnings("serial")
 public class Aggregator<T,U> extends AbstractEnricher implements SensorEventListener<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(Aggregator.class);
@@ -98,7 +97,7 @@ public class Aggregator<T,U> extends AbstractEnricher implements SensorEventList
     public Aggregator() {
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings({ "unchecked" })
     @Override
     public void setEntity(EntityLocal entity) {
         super.setEntity(entity);
@@ -237,12 +236,7 @@ public class Aggregator<T,U> extends AbstractEnricher implements SensorEventList
      */
     protected void onUpdated() {
         try {
-            Object v = compute();
-            if (v == Entities.UNCHANGED) {
-                // nothing
-            } else {
-                emit(targetSensor, TypeCoercions.coerce(v, targetSensor.getTypeToken()));
-            }
+            emit(targetSensor, compute());
         } catch (Throwable t) {
             LOG.warn("Error calculating and setting aggregate for enricher "+this, t);
             throw Exceptions.propagate(t);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/Combiner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Combiner.java b/core/src/main/java/brooklyn/enricher/basic/Combiner.java
index a49cf87..6876be2 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Combiner.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Combiner.java
@@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.Sensor;
@@ -42,7 +41,6 @@ import brooklyn.event.SensorEventListener;
 import brooklyn.event.basic.BasicSensorEvent;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -50,6 +48,7 @@ import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
 import com.google.common.reflect.TypeToken;
 
+@SuppressWarnings("serial")
 public class Combiner<T,U> extends AbstractEnricher implements SensorEventListener<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(Combiner.class);
@@ -121,12 +120,7 @@ public class Combiner<T,U> extends AbstractEnricher implements SensorEventListen
      */
     protected void onUpdated() {
         try {
-            Object v = compute();
-            if (v == Entities.UNCHANGED) {
-                // nothing
-            } else {
-                emit(targetSensor, TypeCoercions.coerce(v, targetSensor.getTypeToken()));
-            }
+            emit(targetSensor, compute());
         } catch (Throwable t) {
             LOG.warn("Error calculating and setting combination for enricher "+this, t);
             throw Exceptions.propagate(t);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/Propagator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Propagator.java b/core/src/main/java/brooklyn/enricher/basic/Propagator.java
index 7e06aa7..267ba88 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Propagator.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Propagator.java
@@ -43,9 +43,9 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.common.reflect.TypeToken;
 
+@SuppressWarnings("serial")
 public class Propagator extends AbstractEnricher implements SensorEventListener<Object> {
 
-    @SuppressWarnings("unused")
     private static final Logger LOG = LoggerFactory.getLogger(Propagator.class);
 
     @SetFromFlag("producer")
@@ -126,6 +126,7 @@ public class Propagator extends AbstractEnricher implements SensorEventListener<
         emitAllAttributes();
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     @Override
     public void onEvent(SensorEvent<Object> event) {
         // propagate upwards
@@ -147,6 +148,7 @@ public class Propagator extends AbstractEnricher implements SensorEventListener<
         emitAllAttributes(false);
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     public void emitAllAttributes(boolean includeNullValues) {
         Iterable<? extends Sensor<?>> sensorsToPopulate = propagatingAll 
                 ? Iterables.filter(producer.getEntityType().getSensors(), sensorFilter)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java b/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java
index dfaa60f..8e863f7 100644
--- a/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java
+++ b/core/src/main/java/brooklyn/enricher/basic/SensorPropagatingEnricher.java
@@ -158,6 +158,7 @@ public class SensorPropagatingEnricher extends AbstractEnricher implements Senso
         emitAllAttributes(false);
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     public void emitAllAttributes(boolean includeNullValues) {
         for (Sensor s: sensors) {
             if (s instanceof AttributeSensor) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/enricher/basic/Transformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Transformer.java b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
index 6877ec9..c517e88 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Transformer.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
@@ -26,14 +26,12 @@ import org.slf4j.LoggerFactory;
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.Sensor;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.event.basic.BasicSensorEvent;
-import brooklyn.util.flags.TypeCoercions;
 
 import com.google.common.base.Function;
 import com.google.common.reflect.TypeToken;
@@ -104,14 +102,7 @@ public class Transformer<T,U> extends AbstractEnricher implements SensorEventLis
 
     @Override
     public void onEvent(SensorEvent<T> event) {
-        Object v = compute(event);
-        if (v == Entities.UNCHANGED) {
-            // nothing
-        } else {
-            U newValue = TypeCoercions.coerce(v, targetSensor.getTypeToken());
-//            oldValue = entity.
-            emit(targetSensor, newValue);
-        }
+        emit(targetSensor, compute(event));
     }
 
     protected Object compute(SensorEvent<T> event) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/entity/basic/ServiceStatusLogic.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/ServiceStatusLogic.java b/core/src/main/java/brooklyn/entity/basic/ServiceStatusLogic.java
index 056334c..8f4c6b4 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStatusLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStatusLogic.java
@@ -21,11 +21,15 @@ package brooklyn.entity.basic;
 import java.util.Map;
 
 import brooklyn.enricher.Enrichers;
+import brooklyn.enricher.basic.UpdatingMap;
 import brooklyn.event.AttributeSensor;
+import brooklyn.event.Sensor;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.util.collections.CollectionFunctionals;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.guava.Functionals;
 
+import com.google.common.base.Function;
 import com.google.common.base.Functions;
 
 /** Logic, sensors and enrichers, and conveniences, for computing service status */ 
@@ -34,13 +38,28 @@ public class ServiceStatusLogic {
     public static final AttributeSensor<Boolean> SERVICE_UP = Attributes.SERVICE_UP;
     public static final AttributeSensor<Map<String,Object>> SERVICE_NOT_UP_INDICATORS = Attributes.SERVICE_NOT_UP_INDICATORS;
     
-    public static final EnricherSpec<?> newEnricherForServiceUpIfNoNotUpIndicators() {
-        return Enrichers.builder()
-            .transforming(SERVICE_NOT_UP_INDICATORS).publishing(Attributes.SERVICE_UP)
-            .computing( Functions.forPredicate(CollectionFunctionals.<String>mapSizeEquals(0)) )
-            .uniqueTag("service.isUp if no service.notUp.indicators")
-            .build();
+    private ServiceStatusLogic() {}
+    
+    public static class ServiceNotUpLogic {
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        public static final EnricherSpec<?> newEnricherForServiceUpIfNoNotUpIndicators() {
+            return Enrichers.builder()
+                .transforming(SERVICE_NOT_UP_INDICATORS).publishing(Attributes.SERVICE_UP)
+                .computing( /* cast hacks to support removing */ (Function)
+                    Functionals.<Map<String,?>>
+                        ifNotEquals(null).<Object>apply(Functions.forPredicate(CollectionFunctionals.<String>mapSizeEquals(0)))
+                        .defaultValue(Entities.REMOVE) )
+                .uniqueTag("service.isUp if no service.notUp.indicators")
+                .build();
+        }
+        
+        /** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map as if the 
+         * {@link UpdatingMap} enricher for the given sensor reported this value (including {@link Entities#REMOVE}) */
+        public static void updateMapFromSensor(EntityLocal entity, Sensor<?> sensor, Object value) {
+            updateMapSensor(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName(), value);
+        }
     }
+    
 
     @SuppressWarnings("unchecked")
     public static <TKey,TVal> void updateMapSensor(EntityLocal entity, AttributeSensor<Map<TKey,TVal>> sensor,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index 126968e..68f8162 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -39,6 +39,7 @@ import brooklyn.config.ConfigMap;
 import brooklyn.enricher.basic.AbstractEnricher;
 import brooklyn.entity.Entity;
 import brooklyn.entity.Group;
+import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.trait.Configurable;
@@ -240,12 +241,21 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
     }
     
     /** @deprecated since 0.7.0 only {@link AbstractEnricher} has emit convenience */
-    protected <T> void emit(Sensor<T> sensor, T val) {
+    protected <T> void emit(Sensor<T> sensor, Object val) {
         checkState(entity != null, "entity must first be set");
+        if (val == Entities.UNCHANGED) {
+            return;
+        }
+        if (val == Entities.REMOVE) {
+            ((EntityInternal)entity).removeAttribute((AttributeSensor<T>) sensor);
+            return;
+        }
+        
+        T newVal = TypeCoercions.coerce(val, sensor.getTypeToken());
         if (sensor instanceof AttributeSensor) {
-            entity.setAttribute((AttributeSensor<T>)sensor, val);
+            entity.setAttribute((AttributeSensor<T>)sensor, newVal);
         } else { 
-            entity.emit(sensor, val);
+            entity.emit(sensor, newVal);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/core/src/test/java/brooklyn/enricher/EnrichersTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/enricher/EnrichersTest.java b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
index 4257c36..66d1bdd 100644
--- a/core/src/test/java/brooklyn/enricher/EnrichersTest.java
+++ b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
@@ -396,7 +396,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
         entity.addEnricher(Enrichers.builder()
                 .updatingMap(MAP1)
                 .from(LONG1)
-                .computing(Functionals.when(-1L).value("-1 is not allowed"))
+                .computing(Functionals.ifEquals(-1L).value("-1 is not allowed"))
                 .build());
         
         doUpdatingMapChecks(MAP1);
@@ -408,7 +408,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
         entity.addEnricher(Enrichers.builder()
                 .updatingMap((AttributeSensor)MAP2)
                 .from(LONG1)
-                .computing(Functionals.when(-1L).value("-1 is not allowed"))
+                .computing(Functionals.ifEquals(-1L).value("-1 is not allowed"))
                 .build());
         
         doUpdatingMapChecks(MAP2);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
index e376bee..25c23df 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java
@@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.Enrichers;
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ServiceStatusLogic.ServiceNotUpLogic;
 import brooklyn.entity.drivers.DriverDependentEntity;
 import brooklyn.entity.drivers.EntityDriverManager;
 import brooklyn.event.feed.function.FunctionFeed;
@@ -116,6 +117,18 @@ public abstract class SoftwareProcessImpl extends AbstractEntity implements Soft
         return Iterables.get(Iterables.filter(getLocations(), MachineLocation.class), 0, null);
     }
     
+    @Override
+    public void init() {
+        super.init();
+        
+        addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS)
+            .from(SERVICE_PROCESS_IS_RUNNING)
+            .computing(Functionals.ifNotEquals(true).value("The software process for this entity does not appear to be running"))
+            .build());
+        
+        addEnricher(ServiceNotUpLogic.newEnricherForServiceUpIfNoNotUpIndicators());
+    }
+    
   	/**
   	 * Called before driver.start; guarantees the driver will exist, and locations will have been set.
   	 */
@@ -161,14 +174,6 @@ public abstract class SoftwareProcessImpl extends AbstractEntity implements Soft
                             }
                         }))
                 .build();
-
-        addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS)
-            .from(SERVICE_PROCESS_IS_RUNNING)
-            .computing(Functionals.when(false).value("Process not running (according to driver checkRunning)")
-                .when((Boolean)null).value("Process not running (no data for "+SERVICE_PROCESS_IS_RUNNING.getName()+")") )
-            .build());
-        
-        addEnricher(ServiceStatusLogic.newEnricherForServiceUpIfNoNotUpIndicators());
     }
 
     /**
@@ -180,7 +185,10 @@ public abstract class SoftwareProcessImpl extends AbstractEntity implements Soft
      */
     protected void disconnectServiceUpIsRunning() {
         if (serviceProcessIsRunning != null) serviceProcessIsRunning.stop();
-        ServiceStatusLogic.updateMapSensor(this, Attributes.SERVICE_NOT_UP_INDICATORS, SERVICE_PROCESS_IS_RUNNING.getName(), "Disabled checking whether service process is running");
+        // set null so the SERVICE_UP enricher runs (possibly removing it), then remove so everything is removed
+        // TODO race because the is-running check may be mid-task
+        setAttribute(SERVICE_PROCESS_IS_RUNNING, null);
+        removeAttribute(SERVICE_PROCESS_IS_RUNNING);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/software/base/src/test/java/brooklyn/entity/basic/lifecycle/ScriptHelperTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/ScriptHelperTest.java b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/ScriptHelperTest.java
index 9894a9e..6edd9a9 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/lifecycle/ScriptHelperTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/lifecycle/ScriptHelperTest.java
@@ -22,6 +22,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.TestException;
 import org.testng.annotations.BeforeMethod;
@@ -31,8 +33,11 @@ import brooklyn.entity.BrooklynAppUnitTestSupport;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.basic.SoftwareProcess;
 import brooklyn.entity.basic.SoftwareProcessEntityTest;
+import brooklyn.entity.basic.SoftwareProcessEntityTest.MyService;
 import brooklyn.entity.basic.SoftwareProcessEntityTest.MyServiceImpl;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.trait.Startable;
 import brooklyn.event.feed.function.FunctionFeed;
 import brooklyn.event.feed.function.FunctionPollConfig;
@@ -47,6 +52,8 @@ import com.google.common.collect.ImmutableList;
 
 public class ScriptHelperTest extends BrooklynAppUnitTestSupport {
     
+    private static final Logger log = LoggerFactory.getLogger(ScriptHelperTest.class);
+    
     private SshMachineLocation machine;
     private FixedListMachineProvisioningLocation<SshMachineLocation> loc;
     boolean shouldFail = false;
@@ -65,34 +72,47 @@ public class ScriptHelperTest extends BrooklynAppUnitTestSupport {
 
     @Test
     public void testCheckRunningForcesInessential() {
-        MyServiceInessentialDriverImpl entity = new MyServiceInessentialDriverImpl(app);
-        Entities.manage(entity);
+        MyService entity = app.createAndManageChild(EntitySpec.create(MyService.class, MyServiceInessentialDriverImpl.class));
+        
+        // is set false on mgmt starting (probably shouldn't be though)
+        Assert.assertFalse(entity.getAttribute(Startable.SERVICE_UP));
         
         entity.start(ImmutableList.of(loc));
         SimulatedInessentialIsRunningDriver driver = (SimulatedInessentialIsRunningDriver) entity.getDriver();
         Assert.assertTrue(driver.isRunning());
+        // currently, is initially set true after successful start
+        Assert.assertTrue(entity.getAttribute(Startable.SERVICE_UP));
         
-        entity.connectServiceUpIsRunning();
+//        entity.connectServiceUpIsRunning();
         
+        EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, true);
+        log.info("XXX F");
         EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true);
         driver.setFailExecution(true);
+        log.info("XXX G");
+        EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, false);
+        log.info("XXX H");
         EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, false);
         driver.setFailExecution(false);
+        EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, true);
         EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true);
     }
     
-    private class MyServiceInessentialDriverImpl extends MyServiceImpl {
-        public MyServiceInessentialDriverImpl(Entity parent) {
-            super(parent);
-        }
+    public static class MyServiceInessentialDriverImpl extends MyServiceImpl {
         
         @Override public Class<?> getDriverInterface() {
             return SimulatedInessentialIsRunningDriver.class;
         }
 
         @Override
+        protected void connectSensors() {
+            super.connectSensors();
+            connectServiceUpIsRunning();
+        }
+        
+        @Override
         public void connectServiceUpIsRunning() {
-            super.connectServiceUpIsRunning();
+//            super.connectServiceUpIsRunning();
             // run more often
             FunctionFeed.builder()
                 .entity(this)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
index 05421d0..3c8e464 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
@@ -33,11 +33,9 @@ import brooklyn.event.feed.http.HttpFeed;
 import brooklyn.event.feed.http.HttpPollConfig;
 import brooklyn.event.feed.http.HttpValueFunctions;
 import brooklyn.location.access.BrooklynAccessUtils;
-import brooklyn.policy.Enricher;
 import brooklyn.util.guava.Functionals;
 
 import com.google.common.base.Functions;
-import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.net.HostAndPort;
 
@@ -51,16 +49,16 @@ public class JBoss7ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
         super();
     }
 
-    public JBoss7ServerImpl(Map flags){
+    public JBoss7ServerImpl(@SuppressWarnings("rawtypes") Map flags){
         this(flags, null);
     }
 
-    public JBoss7ServerImpl(Map flags, Entity parent) {
+    public JBoss7ServerImpl(@SuppressWarnings("rawtypes") Map flags, Entity parent) {
         super(flags, parent);
     }
 
     @Override
-    public Class getDriverInterface() {
+    public Class<?> getDriverInterface() {
         return JBoss7Driver.class;
     }
 
@@ -120,7 +118,7 @@ public class JBoss7ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
         
         addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS)
             .from(MANAGEMENT_URL_UP)
-            .computing(Functionals.when(Predicates.not(Predicates.equalTo(true))).value("Management URL not reachable") )
+            .computing(Functionals.ifNotEquals(true).value("Management URL not reachable") )
             .build());
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java b/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
index 07088b5..f7b1dd0 100644
--- a/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
+++ b/utils/common/src/main/java/brooklyn/util/collections/CollectionFunctionals.java
@@ -36,38 +36,81 @@ import com.google.common.collect.Sets;
  * @author alex */
 public class CollectionFunctionals {
 
+    private static final class EqualsSetPredicate implements Predicate<Iterable<?>> {
+        private final Iterable<?> target;
+
+        private EqualsSetPredicate(Iterable<?> target) {
+            this.target = target;
+        }
+
+        @Override
+        public boolean apply(@Nullable Iterable<?> input) {
+            if (input==null) return false;
+            return Sets.newHashSet(target).equals(Sets.newHashSet(input));
+        }
+    }
+
+    private static final class KeysOfMapFunction<K> implements Function<Map<K, ?>, Set<K>> {
+        @Override
+        public Set<K> apply(Map<K, ?> input) {
+            if (input==null) return null;
+            return input.keySet();
+        }
+
+        @Override public String toString() { return "keys"; }
+    }
+
+    private static final class SizeSupplier implements Supplier<Integer> {
+        private final Iterable<?> collection;
+
+        private SizeSupplier(Iterable<?> collection) {
+            this.collection = collection;
+        }
+
+        @Override
+        public Integer get() {
+            return Iterables.size(collection);
+        }
+
+        @Override public String toString() { return "sizeSupplier("+collection+")"; }
+    }
+
+    public static final class SizeFunction implements Function<Iterable<?>, Integer> {
+        private final Integer valueIfInputNull;
+
+        private SizeFunction(Integer valueIfInputNull) {
+            this.valueIfInputNull = valueIfInputNull;
+        }
+
+        @Override
+        public Integer apply(Iterable<?> input) {
+            if (input==null) return valueIfInputNull;
+            return Iterables.size(input);
+        }
+
+        @Override public String toString() { return "sizeFunction"; }
+    }
+
     public static Supplier<Integer> sizeSupplier(final Iterable<?> collection) {
-        return new Supplier<Integer>() {
-            @Override
-            public Integer get() {
-                return Iterables.size(collection);
-            }
-            @Override public String toString() { return "sizeSupplier("+collection+")"; }
-        };
+        return new SizeSupplier(collection);
     }
     
-    public static Function<Iterable<?>, Integer> sizeFunction() {
-        return new Function<Iterable<?>, Integer>() {
-            @Override
-            public Integer apply(Iterable<?> input) {
-                return Iterables.size(input);
-            }
-            @Override public String toString() { return "sizeFunction"; }
-        };
+    public static Function<Iterable<?>, Integer> sizeFunction() { return sizeFunction(null); }
+    
+    public static Function<Iterable<?>, Integer> sizeFunction(final Integer valueIfInputNull) {
+        return new SizeFunction(valueIfInputNull);
     }
 
     public static <K> Function<Map<K,?>,Set<K>> keys() {
-        return new Function<Map<K,?>, Set<K>>() {
-            @Override
-            public Set<K> apply(Map<K, ?> input) {
-                return input.keySet();
-            }
-            @Override public String toString() { return "keys"; }
-        };
+        return new KeysOfMapFunction<K>();
     }
 
     public static <K> Function<Map<K, ?>, Integer> mapSize() {
-        return Functions.compose(CollectionFunctionals.sizeFunction(), CollectionFunctionals.<K>keys());
+        return mapSize(null);
+    }
+    
+    public static <K> Function<Map<K, ?>, Integer> mapSize(Integer valueIfNull) {
+        return Functions.compose(CollectionFunctionals.sizeFunction(valueIfNull), CollectionFunctionals.<K>keys());
     }
 
     /** default guava Equals predicate will reflect order of target, and will fail when matching against a list;
@@ -76,13 +119,7 @@ public class CollectionFunctionals {
         return equalsSet(Arrays.asList(target));
     }
     public static Predicate<Iterable<?>> equalsSet(final Iterable<?> target) {
-        return new Predicate<Iterable<?>>() {
-            @Override
-            public boolean apply(@Nullable Iterable<?> input) {
-                if (input==null) return false;
-                return Sets.newHashSet(target).equals(Sets.newHashSet(input));
-            }
-        };
+        return new EqualsSetPredicate(target);
     }
 
     public static Predicate<Iterable<?>> sizeEquals(int targetSize) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
index caebc7b..a93c551 100644
--- a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
+++ b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
@@ -18,13 +18,11 @@
  */
 package brooklyn.util.guava;
 
-import brooklyn.util.guava.WhenFunctions.WhenFunctionBuilder;
-import brooklyn.util.guava.WhenFunctions.WhenFunctionBuilderWhenFirst;
+import brooklyn.util.guava.IfFunctions.IfFunctionBuilderApplyingFirst;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
 
 public class Functionals {
 
@@ -43,24 +41,43 @@ public class Functionals {
         return chain(f1, chain(f2, chain(f3, f4)));
     }
 
-    /** @see WhenFunctions */
-    public static <I> WhenFunctionBuilderWhenFirst<I> when(I test) {
-        return WhenFunctions.when(test);
-    }
-    
-    /** @see WhenFunctions */
-    public static <I> WhenFunctionBuilderWhenFirst<I> when(Predicate<I> test) {
-        return WhenFunctions.when(test);
+    /** @see IfFunctions */
+    public static <I> IfFunctionBuilderApplyingFirst<I> ifEquals(I test) {
+        return IfFunctions.ifEquals(test);
     }
 
-    /** @see WhenFunctions */
-    public static <I,O> WhenFunctionBuilder<I,O> when(Predicate<I> test, Supplier<O> supplier) {
-        return WhenFunctions.when(test, supplier);
+    /** @see IfFunctions */
+    public static <I> IfFunctionBuilderApplyingFirst<I> ifNotEquals(I test) {
+        return IfFunctions.ifNotEquals(test);
     }
     
-    /** @see WhenFunctions */
-    public static <I,O> WhenFunctionBuilder<I,O> when(Predicate<I> test, O value) {
-        return WhenFunctions.when(test, value);
+    /** @see IfFunctions */
+    public static <I> IfFunctionBuilderApplyingFirst<I> ifPredicate(Predicate<I> test) {
+        return IfFunctions.ifPredicate(test);
     }
-    
+
+    /** like guava equivalent but parametrises the input generic type, and allows tostring to be customised */
+    public static final class ConstantFunction<I, O> implements Function<I, O> {
+        private final O constant;
+        private Object toStringDescription;
+
+        public ConstantFunction(O constant) {
+            this(constant, null);
+        }
+        public ConstantFunction(O constant, Object toStringDescription) {
+            this.constant = constant;
+            this.toStringDescription = toStringDescription;
+        }
+
+        @Override
+        public O apply(I input) {
+            return constant;
+        }
+        
+        @Override
+        public String toString() {
+            return toStringDescription==null ? "constant("+constant+")" : toStringDescription.toString();
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/main/java/brooklyn/util/guava/IfFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/IfFunctions.java b/utils/common/src/main/java/brooklyn/util/guava/IfFunctions.java
new file mode 100644
index 0000000..5384436
--- /dev/null
+++ b/utils/common/src/main/java/brooklyn/util/guava/IfFunctions.java
@@ -0,0 +1,158 @@
+/*
+ * 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 brooklyn.util.guava;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+
+/** Utilities for building {@link Function} instances which return specific values
+ * (or {@link Supplier} or {@link Function} instances) when certain predicates are satisfied,
+ * tested in order and returning the first matching,
+ * with support for an "else" default value if none are satisfied (null by default). */
+public class IfFunctions {
+
+    public static <I,O> IfFunctionBuilder<I,O> newInstance(Class<I> testType, Class<O> returnType) {
+        return new IfFunctionBuilder<I,O>();
+    }
+    
+    public static <I,O> IfFunctionBuilderApplyingFirst<I> ifPredicate(Predicate<? super I> test) {
+        return new IfFunctionBuilderApplyingFirst<I>(test);
+    }
+    public static <I,O> IfFunctionBuilderApplyingFirst<I> ifEquals(I test) {
+        return ifPredicate(Predicates.equalTo(test));
+    }
+    public static <I,O> IfFunctionBuilderApplyingFirst<I> ifNotEquals(I test) {
+        return ifPredicate(Predicates.not(Predicates.equalTo(test)));
+    }
+    
+    @Beta
+    public static class IfFunction<I,O> implements Function<I,O> {
+        protected final Map<Predicate<? super I>,Function<? super I,? extends O>> tests = new LinkedHashMap<Predicate<? super I>,Function<? super I,? extends O>>();
+        protected Function<? super I,? extends O> defaultFunction = null;
+        
+        protected IfFunction(IfFunction<I,O> input) {
+            this.tests.putAll(input.tests);
+            this.defaultFunction = input.defaultFunction;
+        }
+
+        protected IfFunction() {
+        }
+        
+        @Override
+        public O apply(I input) {
+            for (Map.Entry<Predicate<? super I>,Function<? super I,? extends O>> test: tests.entrySet()) {
+                if (test.getKey().apply(input)) 
+                    return test.getValue().apply(input);
+            }
+            return defaultFunction==null ? null : defaultFunction.apply(input);
+        }
+        
+        @Override
+        public String toString() {
+            return "if["+tests+"]"+(defaultFunction!=null ? "-else["+defaultFunction+"]" : "");
+        }
+    }
+    
+    @Beta
+    public static class IfFunctionBuilder<I,O> extends IfFunction<I,O> {
+        protected IfFunctionBuilder() { super(); }
+        protected IfFunctionBuilder(IfFunction<I,O> input) { super(input); }
+        
+        public IfFunction<I,O> build() {
+            return new IfFunction<I,O>(this);
+        }
+        
+        public IfFunctionBuilderApplying<I,O> ifPredicate(Predicate<I> test) {
+            return new IfFunctionBuilderApplying<I,O>(this, (Predicate<I>)test);
+        }
+        public IfFunctionBuilderApplying<I,O> ifEquals(I test) {
+            return ifPredicate(Predicates.equalTo(test));
+        }
+        public IfFunctionBuilderApplying<I,O> ifNotEquals(I test) {
+            return ifPredicate(Predicates.not(Predicates.equalTo(test)));
+        }
+
+        public IfFunctionBuilder<I,O> defaultValue(O defaultValue) {
+            return defaultApply(new Functionals.ConstantFunction<I,O>(defaultValue, defaultValue));
+        }
+        @SuppressWarnings("unchecked")
+        public IfFunctionBuilder<I,O> defaultGet(Supplier<? extends O> defaultSupplier) {
+            return defaultApply((Function<I,O>)Functions.forSupplier(defaultSupplier));
+        }
+        public IfFunctionBuilder<I,O> defaultApply(Function<? super I,? extends O> defaultFunction) {
+            IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>(this);
+            result.defaultFunction = defaultFunction;
+            return result;
+        }
+    }
+
+    @Beta
+    public static class IfFunctionBuilderApplying<I,O> {
+        private IfFunction<I, O> input;
+        private Predicate<? super I> test;
+        
+        private IfFunctionBuilderApplying(IfFunction<I,O> input, Predicate<? super I> test) {
+            this.input = input;
+            this.test = test;
+        }
+        
+        public IfFunctionBuilder<I,O> value(O value) {
+            return apply(new Functionals.ConstantFunction<I,O>(value, value));
+        }
+        @SuppressWarnings("unchecked")
+        public IfFunctionBuilder<I,O> get(Supplier<? extends O> supplier) {
+            return apply((Function<I,O>)Functions.forSupplier(supplier));
+        }
+        public IfFunctionBuilder<I,O> apply(Function<? super I,? extends O> function) {
+            IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>(input);
+            result.tests.put(test, function);
+            return result;
+        }
+    }
+
+    @Beta
+    public static class IfFunctionBuilderApplyingFirst<I> {
+        private Predicate<? super I> test;
+        
+        private IfFunctionBuilderApplyingFirst(Predicate<? super I> test) {
+            this.test = test;
+        }
+        
+        public <O> IfFunctionBuilder<I,O> value(O value) {
+            return apply(new Functionals.ConstantFunction<I,O>(value, value));
+        }
+        @SuppressWarnings("unchecked")
+        public <O> IfFunctionBuilder<I,O> get(Supplier<? extends O> supplier) {
+            return apply((Function<I,O>)Functions.forSupplier(supplier));
+        }
+        public <O> IfFunctionBuilder<I,O> apply(Function<? super I,? extends O> function) {
+            IfFunctionBuilder<I, O> result = new IfFunctionBuilder<I,O>();
+            result.tests.put(test, function);
+            return result;
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/main/java/brooklyn/util/guava/WhenFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/WhenFunctions.java b/utils/common/src/main/java/brooklyn/util/guava/WhenFunctions.java
deleted file mode 100644
index 50a1e35..0000000
--- a/utils/common/src/main/java/brooklyn/util/guava/WhenFunctions.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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 brooklyn.util.guava;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-
-/** Utilities for building {@link Function} instances which return specific values
- * (or {@link Supplier} instances) when certain predicates are satisfied,
- * tested in order and returning the first matching,
- * with support for an "else" default value if none are satisfied (null by default). */
-public class WhenFunctions {
-
-    public static <I,O> WhenFunctionBuilder<I,O> newInstance(Class<I> testType, Class<O> returnType) {
-        return new WhenFunctionBuilder<I,O>();
-    }
-    
-    public static <I,O> WhenFunctionBuilderWhenFirst<I> when(Predicate<I> test) {
-        return new WhenFunctionBuilderWhenFirst<I>(test);
-    }
-    public static <I,O> WhenFunctionBuilderWhenFirst<I> when(I test) {
-        return new WhenFunctionBuilderWhenFirst<I>(test);
-    }
-    public static <I,O> WhenFunctionBuilder<I,O> when(Predicate<I> test, Supplier<O> supplier) {
-        return new WhenFunctionBuilder<I,O>().when(test, supplier);
-    }
-    public static <I,O> WhenFunctionBuilder<I,O> when(Predicate<I> test, O value) {
-        return new WhenFunctionBuilder<I,O>().when(test, value);
-    }
-    
-    public static class WhenFunction<I,O> implements Function<I,O> {
-        protected final Map<Predicate<I>,Supplier<O>> tests = new LinkedHashMap<Predicate<I>,Supplier<O>>();
-        protected Supplier<O> defaultValue = null;
-        
-        protected WhenFunction(WhenFunction<I,O> input) {
-            this.tests.putAll(input.tests);
-            this.defaultValue = input.defaultValue;
-        }
-
-        protected WhenFunction() {
-        }
-        
-        @Override
-        public O apply(I input) {
-            for (Map.Entry<Predicate<I>,Supplier<O>> test: tests.entrySet()) {
-                if (test.getKey().apply(input)) 
-                    return test.getValue().get();
-            }
-            return defaultValue==null ? null : defaultValue.get();
-        }
-        
-        @Override
-        public String toString() {
-            return "if["+tests+"]"+(defaultValue!=null ? "-else["+defaultValue+"]" : "");
-        }
-    }
-    
-    public static class WhenFunctionBuilder<I,O> extends WhenFunction<I,O> {
-        protected WhenFunctionBuilder() { super(); }
-        protected WhenFunctionBuilder(WhenFunction<I,O> input) { super(input); }
-        
-        public WhenFunction<I,O> build() {
-            return new WhenFunction<I,O>(this);
-        }
-        
-        public WhenFunctionBuilder<I,O> when(Predicate<I> test, Supplier<O> supplier) {
-            return when(test).value(supplier);
-        }
-
-        public WhenFunctionBuilder<I,O> when(Predicate<I> test, O value) {
-            return when(test).value(value);
-        }
-
-        public WhenFunctionBuilderWhen<I,O> when(Predicate<I> test) {
-            return whenUnchecked(test);
-        }
-        public WhenFunctionBuilderWhen<I,O> when(I test) {
-            return whenUnchecked(test);
-        }
-        @SuppressWarnings("unchecked")
-        protected WhenFunctionBuilderWhen<I,O> whenUnchecked(Object test) {
-            if (!(test instanceof Predicate)) {
-                test = Predicates.equalTo(test);
-            }
-            return new WhenFunctionBuilderWhen<I,O>(this, (Predicate<I>)test);
-        }
-
-        public WhenFunctionBuilder<I,O> defaultValue(O defaultValue) {
-            return defaultValueUnchecked(defaultValue);
-        }
-        public WhenFunctionBuilder<I,O> defaultValue(Supplier<O> defaultValue) {
-            return defaultValueUnchecked(defaultValue);
-        }
-        @SuppressWarnings("unchecked")
-        protected WhenFunctionBuilder<I,O> defaultValueUnchecked(Object defaultValue) {
-            if (!(defaultValue instanceof Supplier)) {
-                defaultValue = Suppliers.ofInstance(defaultValue);
-            }
-            WhenFunctionBuilder<I, O> result = new WhenFunctionBuilder<I,O>(this);
-            result.defaultValue = (Supplier<O>)defaultValue;
-            return result;
-        }
-    }
-
-    public static class WhenFunctionBuilderWhen<I,O> {
-        private WhenFunction<I, O> input;
-        private Predicate<I> test;
-        
-        private WhenFunctionBuilderWhen(WhenFunction<I,O> input, Predicate<I> test) {
-            this.input = input;
-            this.test = test;
-        }
-        
-        public WhenFunctionBuilder<I,O> value(O value) {
-            return valueUnchecked(value);
-        }
-        public WhenFunctionBuilder<I,O> value(Supplier<O> value) {
-            return valueUnchecked(value);
-        }
-        @SuppressWarnings("unchecked")
-        protected WhenFunctionBuilder<I,O> valueUnchecked(Object value) {
-            if (!(value instanceof Supplier)) {
-                value = Suppliers.ofInstance(value);
-            }
-            WhenFunctionBuilder<I, O> result = new WhenFunctionBuilder<I,O>(input);
-            result.tests.put(test, (Supplier<O>) value);
-            return result;
-        }
-    }
-
-    public static class WhenFunctionBuilderWhenFirst<I> {
-        private Predicate<I> test;
-        
-        private WhenFunctionBuilderWhenFirst(Predicate<I> test) {
-            whenUnchecked(test);
-        }
-        
-        public WhenFunctionBuilderWhenFirst(I test) {
-            whenUnchecked(test);
-        }
-
-        @SuppressWarnings("unchecked")
-        protected void whenUnchecked(Object test) {
-            if (!(test instanceof Predicate)) {
-                this.test = Predicates.equalTo((I)test);
-            } else {
-                this.test = (Predicate<I>) test;
-            }
-        }
-        
-        public <O> WhenFunctionBuilder<I,O> value(O value) {
-            return valueUnchecked(value);
-        }
-        public <O> WhenFunctionBuilder<I,O> value(Supplier<O> value) {
-            return valueUnchecked(value);
-        }
-        @SuppressWarnings("unchecked")
-        protected <O> WhenFunctionBuilder<I,O> valueUnchecked(Object value) {
-            if (!(value instanceof Supplier)) {
-                value = Suppliers.ofInstance(value);
-            }
-            WhenFunctionBuilder<I, O> result = new WhenFunctionBuilder<I,O>();
-            result.tests.put(test, (Supplier<O>) value);
-            return result;
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/test/java/brooklyn/util/collections/CollectionFunctionalsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/collections/CollectionFunctionalsTest.java b/utils/common/src/test/java/brooklyn/util/collections/CollectionFunctionalsTest.java
new file mode 100644
index 0000000..6611d9b
--- /dev/null
+++ b/utils/common/src/test/java/brooklyn/util/collections/CollectionFunctionalsTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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 brooklyn.util.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class CollectionFunctionalsTest {
+
+    @Test
+    public void testListSize() {
+        Assert.assertTrue(CollectionFunctionals.sizeEquals(2).apply(ImmutableList.of("x", "y")));
+        Assert.assertFalse(CollectionFunctionals.sizeEquals(2).apply(null));
+        Assert.assertTrue(CollectionFunctionals.sizeEquals(0).apply(ImmutableList.of()));
+        Assert.assertFalse(CollectionFunctionals.sizeEquals(0).apply(null));
+    }
+
+    @Test
+    public void testMapSize() {
+        Assert.assertTrue(CollectionFunctionals.<String>mapSizeEquals(2).apply(ImmutableMap.of("x", "1", "y", "2")));
+        Assert.assertFalse(CollectionFunctionals.<String>mapSizeEquals(2).apply(null));
+        Assert.assertTrue(CollectionFunctionals.mapSizeEquals(0).apply(ImmutableMap.of()));
+        Assert.assertFalse(CollectionFunctionals.mapSizeEquals(0).apply(null));
+    }
+
+    @Test
+    public void testMapSizeOfNull() {
+        Assert.assertEquals(CollectionFunctionals.mapSize().apply(null), null);
+        Assert.assertEquals(CollectionFunctionals.mapSize(-1).apply(null), (Integer)(-1));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/test/java/brooklyn/util/guava/FunctionalsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/guava/FunctionalsTest.java b/utils/common/src/test/java/brooklyn/util/guava/FunctionalsTest.java
index 7e2ab35..3da3532 100644
--- a/utils/common/src/test/java/brooklyn/util/guava/FunctionalsTest.java
+++ b/utils/common/src/test/java/brooklyn/util/guava/FunctionalsTest.java
@@ -35,24 +35,24 @@ public class FunctionalsTest {
     }
 
     @Test
-    public void testWhen() {
-        WhenFunctionsTest.checkTF(Functionals.when(false).value("F").when(true).value("T").defaultValue("?").build(), "?");
+    public void testIf() {
+        IfFunctionsTest.checkTF(Functionals.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
     }
 
     @Test
-    public void testWhenNoBuilder() {
-        WhenFunctionsTest.checkTF(Functionals.when(false).value("F").when(true).value("T").defaultValue("?"), "?");
+    public void testIfNoBuilder() {
+        IfFunctionsTest.checkTF(Functionals.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?"), "?");
     }
     
     @Test
-    public void testWhenPredicateAndSupplier() {
-        WhenFunctionsTest.checkTF(Functionals.when(Predicates.equalTo(false)).value(Suppliers.ofInstance("F"))
-            .when(true).value("T").defaultValue(Suppliers.ofInstance("?")).build(), "?");
+    public void testIfPredicateAndSupplier() {
+        IfFunctionsTest.checkTF(Functionals.ifPredicate(Predicates.equalTo(false)).get(Suppliers.ofInstance("F"))
+            .ifEquals(true).value("T").defaultGet(Suppliers.ofInstance("?")).build(), "?");
     }
 
     @Test
-    public void testWhenTwoArgs() {
-        WhenFunctionsTest.checkTF(Functionals.when(Predicates.equalTo(false), "F").when(Predicates.equalTo(true), "T").defaultValue("?").build(), "?");
+    public void testIfNotEqual() {
+        IfFunctionsTest.checkTF(Functionals.ifNotEquals(false).value("T").defaultValue("F").build(), "T");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/test/java/brooklyn/util/guava/IfFunctionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/guava/IfFunctionsTest.java b/utils/common/src/test/java/brooklyn/util/guava/IfFunctionsTest.java
new file mode 100644
index 0000000..74a5d5b
--- /dev/null
+++ b/utils/common/src/test/java/brooklyn/util/guava/IfFunctionsTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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 brooklyn.util.guava;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.guava.IfFunctions.IfFunctionBuilder;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.base.Suppliers;
+
+public class IfFunctionsTest {
+
+    @Test
+    public void testCommonUsage() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
+    }
+
+    @Test
+    public void testNoBuilder() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?"), "?");
+    }
+    
+    @Test
+    public void testPredicateAndSupplier() {
+        checkTF(IfFunctions.ifPredicate(Predicates.equalTo(false)).get(Suppliers.ofInstance("F"))
+            .ifEquals(true).value("T").defaultGet(Suppliers.ofInstance("?")).build(), "?");
+    }
+
+    @Test
+    public void testNoDefault() {
+        checkTF(IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").build(), null);
+    }
+
+    @Test
+    public void testNotEqual() {
+        checkTF(IfFunctions.ifNotEquals(false).value("T").defaultValue("F").build(), "T");
+    }
+
+    @Test
+    public void testFunction() {
+        checkTF(IfFunctions.ifNotEquals((Boolean)null).apply(new Function<Boolean, String>() {
+            @Override
+            public String apply(Boolean input) {
+                return input.toString().toUpperCase().substring(0, 1);
+            }
+        }).defaultValue("?"), "?");
+    }
+
+    @Test
+    public void testWithCast() {
+        Function<Boolean, String> f = IfFunctions.<Boolean,String>ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build();
+        checkTF(f, "?");
+    }
+
+    @Test
+    public void testWithoutCast() {
+        Function<Boolean, String> f = IfFunctions.newInstance(Boolean.class, String.class).ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build();
+        checkTF(f, "?");
+    }
+
+    @Test
+    public void testSupportsReplace() {
+        checkTF(IfFunctions.ifEquals(false).value("false").ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?").build(), "?");
+    }
+
+    @Test
+    public void testIsImmutableAndSupportsReplace() {
+        IfFunctionBuilder<Boolean, String> f = IfFunctions.ifEquals(false).value("F").ifEquals(true).value("T").defaultValue("?");
+        IfFunctionBuilder<Boolean, String> f2 = f.ifEquals(false).value("false").defaultValue("X");
+        IfFunctionBuilder<Boolean, String> f3 = f2.ifEquals(false).value("F");
+        checkTF(f, "?");
+        checkTF(f3, "X");
+        Assert.assertEquals(f2.apply(false), "false");
+    }
+
+    static void checkTF(Function<Boolean, String> f, Object defaultValue) {
+        Assert.assertEquals(f.apply(true), "T");
+        Assert.assertEquals(f.apply(false), "F");
+        Assert.assertEquals(f.apply(null), defaultValue);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bc1d19f7/utils/common/src/test/java/brooklyn/util/guava/WhenFunctionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/brooklyn/util/guava/WhenFunctionsTest.java b/utils/common/src/test/java/brooklyn/util/guava/WhenFunctionsTest.java
deleted file mode 100644
index 2b01b14..0000000
--- a/utils/common/src/test/java/brooklyn/util/guava/WhenFunctionsTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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 brooklyn.util.guava;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.util.guava.WhenFunctions.WhenFunctionBuilder;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicates;
-import com.google.common.base.Suppliers;
-
-public class WhenFunctionsTest {
-
-    @Test
-    public void testWhen() {
-        checkTF(WhenFunctions.when(false).value("F").when(true).value("T").defaultValue("?").build(), "?");
-    }
-
-    @Test
-    public void testWhenNoBuilder() {
-        checkTF(WhenFunctions.when(false).value("F").when(true).value("T").defaultValue("?"), "?");
-    }
-    
-    @Test
-    public void testWhenPredicateAndSupplier() {
-        checkTF(WhenFunctions.when(Predicates.equalTo(false)).value(Suppliers.ofInstance("F"))
-            .when(true).value("T").defaultValue(Suppliers.ofInstance("?")).build(), "?");
-    }
-
-    @Test
-    public void testWhenTwoArgs() {
-        checkTF(WhenFunctions.when(Predicates.equalTo(false), "F").when(Predicates.equalTo(true), "T").defaultValue("?").build(), "?");
-    }
-    
-    @Test
-    public void testWhenNoDefault() {
-        checkTF(WhenFunctions.when(false).value("F").when(true).value("T").build(), null);
-    }
-
-    @Test
-    public void testWhenWithCast() {
-        Function<Boolean, String> f = WhenFunctions.<Boolean,String>when(false).value("F").when(true).value("T").defaultValue("?").build();
-        checkTF(f, "?");
-    }
-
-    @Test
-    public void testWhenWithoutCast() {
-        Function<Boolean, String> f = WhenFunctions.newInstance(Boolean.class, String.class).when(false).value("F").when(true).value("T").defaultValue("?").build();
-        checkTF(f, "?");
-    }
-
-    @Test
-    public void testWhenSupportsReplace() {
-        checkTF(WhenFunctions.when(false).value("false").when(false).value("F").when(true).value("T").defaultValue("?").build(), "?");
-    }
-
-    @Test
-    public void testWhenIsImmutableAndSupportsReplace() {
-        WhenFunctionBuilder<Boolean, String> f = WhenFunctions.when(false).value("F").when(true).value("T").defaultValue("?");
-        WhenFunctionBuilder<Boolean, String> f2 = f.when(false).value("false").defaultValue("X");
-        WhenFunctionBuilder<Boolean, String> f3 = f2.when(false).value("F");
-        checkTF(f, "?");
-        checkTF(f3, "X");
-        Assert.assertEquals(f2.apply(false), "false");
-    }
-
-    static void checkTF(Function<Boolean, String> f, Object defaultValue) {
-        Assert.assertEquals(f.apply(true), "T");
-        Assert.assertEquals(f.apply(false), "F");
-        Assert.assertEquals(f.apply(null), defaultValue);
-    }
-    
-}