This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new d67d033  when unwrapping, excuse parent having subset of children 
initializers/policies/enrichers
d67d033 is described below

commit d67d0332d2a9f3b686006d905d6232b9160d9236
Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com>
AuthorDate: Wed Jan 13 09:55:28 2021 +0000

    when unwrapping, excuse parent having subset of children 
initializers/policies/enrichers
---
 .../brooklyn/core/mgmt/EntityManagementUtils.java  | 46 +++++++++++++++-------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index 8d5a07e..a1ee6b9 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -18,11 +18,13 @@
  */
 package org.apache.brooklyn.core.mgmt;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Callable;
 
+import java.util.function.Function;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.Application;
@@ -42,6 +44,7 @@ import 
org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.task.TaskBuilder;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -327,22 +330,37 @@ public class EntityManagementUtils {
      * see {@link #canUnwrapApplication(EntitySpec)} if that is required).
      * <p>
      * Note callers will normally use one of {@link #unwrapEntity(EntitySpec)} 
or {@link #unwrapApplication(EntitySpec)}.
-     * 
-     * @see #WRAPPER_APP_MARKER for an overview */
+     *
+     * @see #WRAPPER_APP_MARKER  */
     public static boolean canUnwrapEntity(EntitySpec<? extends Entity> spec, 
boolean allowUnwrappingApplicationsWithoutWrapperAppMarker) {
         return ((allowUnwrappingApplicationsWithoutWrapperAppMarker && 
Application.class.isAssignableFrom(spec.getType())) 
-                || isWrapperApp(spec)) && 
-            hasSingleChild(spec) &&
-            // these "brooklyn.*" items on the app rather than the child 
absolutely prevent unwrapping
-            // as their semantics could well be different whether they are on 
the parent or the child
-            spec.getEnricherSpecs().isEmpty() &&
-            spec.getInitializers().isEmpty() &&
-            spec.getPolicySpecs().isEmpty() &&
-            // prevent merge only if a location is defined at both levels
-            ((spec.getLocations().isEmpty() && 
spec.getLocationSpecs().isEmpty()) || 
-                
(Iterables.getOnlyElement(spec.getChildren()).getLocations().isEmpty()) && 
Iterables.getOnlyElement(spec.getChildren()).getLocationSpecs().isEmpty())
-            // parameters are collapsed on merge so don't need to be 
considered here
-            ;
+                || isWrapperApp(spec)) &&
+            hasMergeableSingleChild(spec);
+    }
+
+    private static boolean hasMergeableSingleChild(EntitySpec<? extends 
Entity> spec) {
+        if (!hasSingleChild(spec)) return false;
+        // these "brooklyn.*" items on the app rather than the child 
absolutely prevent unwrapping
+        // as their semantics could well be different whether they are on the 
parent or the child
+        EntitySpec<? extends Entity> child = 
Iterables.getOnlyElement(spec.getChildren());
+        if (!allParentSubsetOfChild(spec, child, EntitySpec::getEnricherSpecs, 
EntitySpec::getInitializers, EntitySpec::getPolicySpecs)) return false;
+
+        // prevent merge only if a location is defined at both levels
+        if (! ((spec.getLocations().isEmpty() && 
spec.getLocationSpecs().isEmpty()) ||
+                
(Iterables.getOnlyElement(spec.getChildren()).getLocations().isEmpty()) && 
Iterables.getOnlyElement(spec.getChildren()).getLocationSpecs().isEmpty())) {
+            return false;
+        }
+
+        // parameters are collapsed on merge so don't need to be considered 
here
+
+        return true;
+    }
+
+    private static boolean allParentSubsetOfChild(EntitySpec<? extends Entity> 
spec, EntitySpec<? extends Entity> child, Function<EntitySpec<? extends 
Entity>, Collection<?>> ...getters) {
+        for (Function<EntitySpec<? extends Entity>, Collection<?>> getter: 
getters) {
+            if (! (MutableSet.copyOf( getter.apply(child) ).containsAll( 
getter.apply(spec) )) ) return false;
+        }
+        return true;
     }
 
     public static boolean isWrapperApp(EntitySpec<?> spec) {

Reply via email to