support prescanning entities for dynamic group

to see if there are changes
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroup.java b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroup.java
index a4fdace..3e61ec8 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroup.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroup.java
@@ -70,6 +70,8 @@
     /** Rescans <em>all</em> entities to determine whether they match the filter. */
     @Effector(description = "Rescans all entities to determine whether they match the configured filter.")
     void rescanEntities();
+    /** return true/false whether there are any changes detected */
+    boolean prescanEntities();
 
     /** Sets {@link #ENTITY_FILTER}, overriding (and rescanning all) if already set. */
     void setEntityFilter(Predicate<? super Entity> filter);
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroupImpl.java b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroupImpl.java
index abeaaee..b755b1f 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroupImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicGroupImpl.java
@@ -205,15 +205,23 @@
 
     @Override
     public void rescanEntities() {
+        rescanEntitiesInternal(true);
+    }
+
+    public boolean prescanEntities() {
+        return rescanEntitiesInternal(false);
+    }
+
+    protected boolean rescanEntitiesInternal(boolean makeChanges) {
         synchronized (memberChangeMutex) {
             if (!isRunning() || !getManagementSupport().isDeployed()) {
                 if (log.isDebugEnabled()) log.debug("{} not scanning for children: stopped", this);
-                return;
+                return false;
             }
             if (getAncestorToScan() == null) {
                 BrooklynLogging.log(log, BrooklynLogging.levelDependingIfReadOnly(this, LoggingLevel.WARN, LoggingLevel.TRACE, LoggingLevel.TRACE),
                     "{} not (yet) scanning for children: no application defined", this);
-                return;
+                return false;
             }
             boolean changed = false;
             Collection<Entity> currentMembers = getMembers();
@@ -225,17 +233,20 @@
                 toRemove.remove(it);
                 if (!currentMembers.contains(it)) {
                     if (log.isDebugEnabled()) log.debug("{} rescan detected new item {}", this, it);
+                    if (!makeChanges) return true;
                     addMember(it);
                     changed = true;
                 }
             }
             for (Entity it : toRemove) {
                 if (log.isDebugEnabled()) log.debug("{} rescan detected vanished item {}", this, it);
+                if (!makeChanges) return true;
                 removeMember(it);
                 changed = true;
             }
             if (changed && log.isDebugEnabled())
                 log.debug("{} rescan complete, members now {}", this, getMembers());
+            return changed;
         }
     }
 
diff --git a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowConfigSensorEffectorTest.java b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowConfigSensorEffectorTest.java
index ea02bc1..d1b81f6 100644
--- a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowConfigSensorEffectorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowConfigSensorEffectorTest.java
@@ -194,6 +194,9 @@
         Entity chilld = Iterables.getOnlyElement(app.getChildren());
         Asserts.assertEquals(lastInvocation.getUnchecked(), chilld);
 
+        runWorkflow(MutableList.of("let entity x = "+chilld.getId(), "return ${x}"));
+        Asserts.assertEquals(lastInvocation.getUnchecked(), chilld);
+
         runWorkflow(MutableList.of("let entity x = chilldx",
                         "let y = ${x} ?? missing",
                         "return ${y}"));