tidy up of entity/app unwrapping
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/b35188c6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/b35188c6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/b35188c6 Branch: refs/heads/master Commit: b35188c684575eff3422f0acd06356c5dc824a94 Parents: 9fac9c4 Author: Alex Heneveld <[email protected]> Authored: Wed Jan 13 16:40:24 2016 +0000 Committer: Alex Heneveld <[email protected]> Committed: Wed Jan 13 16:40:24 2016 +0000 ---------------------------------------------------------------------- .../BrooklynAssemblyTemplateInstantiator.java | 23 ++-- .../BrooklynComponentTemplateResolver.java | 23 +--- .../brooklyn/spi/creation/CampResolver.java | 8 +- .../core/mgmt/EntityManagementUtils.java | 108 +++++++++++-------- 4 files changed, 72 insertions(+), 90 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b35188c6/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java index 4d2ca82..931c2e7 100644 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java +++ b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java @@ -40,7 +40,6 @@ import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator { @@ -90,30 +89,20 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe // first build the children into an empty shell app List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, encounteredTypeSymbolicNames); for (EntitySpec<?> childSpec : childSpecs) { - - if (Application.class.isAssignableFrom(childSpec.getType())) { - EntitySpec<? extends Application> appSpec = (EntitySpec<? extends Application>) childSpec; - if (EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec)) { - EntitySpec<?> appChildSpec = Iterables.getOnlyElement(appSpec.getChildren()); - EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, appChildSpec); - childSpec = appChildSpec; - } - } - - app.child(childSpec); + // children get parsed and unwrapped irrespective of the NEVER_UNWRAP_APPS setting; + // we could support a NEVER_UNWRAP_NESTED_ENTITIES item but i don't know if there's a use case + app.child(EntityManagementUtils.unwrapEntity(childSpec)); } - if (shouldUnwrap(template, app)) { + if (allowedToUnwrap(template, app)) { app = EntityManagementUtils.unwrapApplication(app); } return app; } - private boolean shouldUnwrap(AssemblyTemplate template, EntitySpec<? extends Application> app) { - if (Boolean.TRUE.equals(TypeCoercions.coerce(template.getCustomAttributes().get(NEVER_UNWRAP_APPS_PROPERTY), Boolean.class))) - return false; - return EntityManagementUtils.canPromoteWrappedApplication(app); + private boolean allowedToUnwrap(AssemblyTemplate template, EntitySpec<? extends Application> app) { + return !(Boolean.TRUE.equals(TypeCoercions.coerce(template.getCustomAttributes().get(NEVER_UNWRAP_APPS_PROPERTY), Boolean.class))); } private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredRegisteredTypeIds) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b35188c6/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java index 304a523..78f78e4 100644 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java +++ b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java @@ -209,17 +209,7 @@ public class BrooklynComponentTemplateResolver { // encounteredRegisteredTypeIds must contain the items currently being loaded (the dependency chain), // but not parent items in this type already resolved. EntitySpec<? extends Entity> childSpec = entityResolver.resolveSpec(encounteredRegisteredTypeIds); - - if (Application.class.isAssignableFrom(childSpec.getType())) { - EntitySpec<? extends Application> appSpec = (EntitySpec<? extends Application>) childSpec; - if (EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec)) { - EntitySpec<?> appChildSpec = Iterables.getOnlyElement(appSpec.getChildren()); - EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, appChildSpec); - childSpec = appChildSpec; - } - } - - spec.child(childSpec); + spec.child(EntityManagementUtils.unwrapEntity(childSpec)); } } @@ -379,16 +369,7 @@ public class BrooklynComponentTemplateResolver { specConfig.setSpecConfiguration(resolvedConfig); EntitySpec<?> entitySpec = Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveSpec(encounteredRegisteredTypeIds); - if (Application.class.isAssignableFrom(entitySpec.getType())) { - EntitySpec<? extends Application> appSpec = (EntitySpec<? extends Application>) entitySpec; - if (EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec)) { - EntitySpec<?> childSpec = Iterables.getOnlyElement(appSpec.getChildren()); - EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec); - entitySpec = childSpec; - } - } - return entitySpec; - + return EntityManagementUtils.unwrapEntity(entitySpec); } if (flag instanceof ManagementContextInjectable) { log.debug("Injecting Brooklyn management context info object: {}", flag); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b35188c6/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java index 602baa3..56914db 100644 --- a/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java +++ b/brooklyn-server/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java @@ -131,12 +131,8 @@ class CampResolver { if (instantiator instanceof AssemblyTemplateSpecInstantiator) { EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes); - if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec)) { - EntitySpec<?> childSpec = Iterables.getOnlyElement(appSpec.getChildren()); - EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec); - return childSpec; - } - return appSpec; + if (isApplication) return EntityManagementUtils.unwrapApplication(appSpec); + return EntityManagementUtils.unwrapEntity(appSpec); } else { throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b35188c6/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java index ef461db..4b6b8ce 100644 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java +++ b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java @@ -50,7 +50,6 @@ import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.annotations.Beta; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -67,11 +66,12 @@ public class EntityManagementUtils { /** * A marker config value which indicates that an {@link Application} entity was created automatically, * needed because a plan might give multiple top-level entities or a non-Application top-level entity, - * but brooklyn requires an {@link Application} at the root. + * in a context where Brooklyn requires an {@link Application} at the root. * <p> * Typically when such a wrapper app wraps another {@link Application} - * (or when we are adding to an existing entity and it wraps multiple {@link Entity} instances) - * it will be unwrapped. See {@link #newWrapperApp()} and {@link #unwrapApplication(EntitySpec)}. + * (or where we are looking for a single {@link Entity}, or a list to add, and they are so wrapped) + * it will be unwrapped. + * See {@link #newWrapperApp()} and {@link #unwrapApplication(EntitySpec)}. */ public static final ConfigKey<Boolean> WRAPPER_APP_MARKER = ConfigKeys.newBooleanConfigKey("brooklyn.wrapper_app"); @@ -159,21 +159,16 @@ public class EntityManagementUtils { // see whether we can promote children List<EntitySpec<?>> specs = MutableList.of(); - if (canPromoteChildrenInWrappedApplication(specA)) { - // we can promote - for (EntitySpec<?> specC: specA.getChildren()) { - mergeWrapperParentSpecToChildEntity(specA, specC); - specs.add(specC); - } - } else { + if (!canUnwrapEntity(specA)) { // if not promoting, set a nice name if needed if (Strings.isEmpty(specA.getDisplayName())) { int size = specA.getChildren().size(); String childrenCountString = size+" "+(size!=1 ? "children" : "child"); specA.displayName("Dynamically added "+childrenCountString); } - specs.add(specA); } + + specs.add(unwrapEntity(specA)); final List<Entity> children = MutableList.of(); for (EntitySpec<?> spec: specs) { @@ -219,27 +214,37 @@ public class EntityManagementUtils { return CreationResult.of(children, task); } - - /** if an application should be unwrapped, it does so, returning the child; otherwise returns the argument passed in. - * use {@link #canPromoteWrappedApplication(EntitySpec)} to test whether it will unwrap. */ + + /** Unwraps a single {@link Entity} if appropriate. See {@link #WRAPPER_APP_MARKER}. + * Also see {@link #canUnwrapEntity(EntitySpec)} to test whether it will unwrap. */ + public static EntitySpec<? extends Entity> unwrapEntity(EntitySpec<? extends Entity> wrapperApplication) { + if (!canUnwrapEntity(wrapperApplication)) { + return wrapperApplication; + } + EntitySpec<?> wrappedEntity = Iterables.getOnlyElement(wrapperApplication.getChildren()); + @SuppressWarnings("unchecked") + EntitySpec<? extends Application> wrapperApplicationTyped = (EntitySpec<? extends Application>) wrapperApplication; + EntityManagementUtils.mergeWrapperParentSpecToChildEntity(wrapperApplicationTyped, wrappedEntity); + return wrappedEntity; + } + + /** Unwraps a wrapped {@link Application} if appropriate. + * This is like {@link #canUnwrapEntity(EntitySpec)} with an additional check that the wrapped child is an {@link Application}. + * See {@link #WRAPPER_APP_MARKER} for an overview. + * Also see {@link #canUnwrapApplication(EntitySpec)} to test whether it will unwrap. */ public static EntitySpec<? extends Application> unwrapApplication(EntitySpec<? extends Application> wrapperApplication) { - if (canPromoteWrappedApplication(wrapperApplication)) { - @SuppressWarnings("unchecked") - EntitySpec<? extends Application> wrappedApplication = (EntitySpec<? extends Application>) Iterables.getOnlyElement( wrapperApplication.getChildren() ); - - // if promoted, apply the transformations done to the app - // (transformations will be done by the resolveSpec call above, but we are collapsing oldApp so transfer to app=newApp) - EntityManagementUtils.mergeWrapperParentSpecToChildEntity(wrapperApplication, wrappedApplication); - return wrappedApplication; + if (!canUnwrapApplication(wrapperApplication)) { + return wrapperApplication; } - return wrapperApplication; + @SuppressWarnings("unchecked") + EntitySpec<? extends Application> wrappedApplication = (EntitySpec<? extends Application>) unwrapEntity(wrapperApplication); + return wrappedApplication; } /** Modifies the child so it includes the inessential setup of its parent, * for use when unwrapping specific children, but a name or other item may have been set on the parent. * See {@link #WRAPPER_APP_MARKER}. */ - @Beta //where should this live long-term? - public static void mergeWrapperParentSpecToChildEntity(EntitySpec<? extends Application> wrapperParent, EntitySpec<?> wrappedChild) { + private static void mergeWrapperParentSpecToChildEntity(EntitySpec<? extends Application> wrapperParent, EntitySpec<?> wrappedChild) { if (Strings.isNonEmpty(wrapperParent.getDisplayName())) wrappedChild.displayName(wrapperParent.getDisplayName()); if (!wrapperParent.getLocations().isEmpty()) @@ -263,31 +268,42 @@ public class EntityManagementUtils { return EntitySpec.create(BasicApplication.class).configure(WRAPPER_APP_MARKER, true); } - /** returns true if the spec is for an empty-ish wrapper app contianing an application, - * for use when adding from a plan specifying an application which was wrapped because it had to be. + /** As {@link #canUnwrapEntity(EntitySpec)} + * but additionally requiring that the wrapped item is an {@link Application}, + * for use when the context requires an {@link Application} ie a root of a spec. * @see #WRAPPER_APP_MARKER */ - public static boolean canPromoteWrappedApplication(EntitySpec<? extends Application> app) { - if (!hasSingleChild(app)) - return false; + public static boolean canUnwrapApplication(EntitySpec<? extends Application> wrapperApplication) { + if (!canUnwrapEntity(wrapperApplication)) return false; - EntitySpec<?> childSpec = Iterables.getOnlyElement(app.getChildren()); - if (childSpec.getType()==null || !Application.class.isAssignableFrom(childSpec.getType())) - return false; - - return canPromoteChildrenInWrappedApplication(app); + EntitySpec<?> childSpec = Iterables.getOnlyElement(wrapperApplication.getChildren()); + return (childSpec.getType()!=null && Application.class.isAssignableFrom(childSpec.getType())); + } + /** @deprecated since 0.9.0 use {@link #canUnwrapApplication(EntitySpec)} */ @Deprecated + public static boolean canPromoteWrappedApplication(EntitySpec<? extends Application> app) { + return canUnwrapApplication(app); } - /** returns true if the spec is for a wrapper app with no important settings, wrapping a single child. - * for use when adding from a plan specifying multiple entities but nothing significant at the application level. - * @see #WRAPPER_APP_MARKER */ - public static boolean canPromoteChildrenInWrappedApplication(EntitySpec<? extends Application> spec) { + /** Returns true if the spec is for a wrapper app with no important settings, wrapping a single child entity. + * for use when adding from a plan specifying multiple entities but there is nothing significant at the application level, + * and the context would like to flatten it to remove the wrapper yielding just a single entity. + * (but note the result is not necessarily an {@link Application}; + * 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 */ + public static boolean canUnwrapEntity(EntitySpec<? extends Entity> spec) { return isWrapperApp(spec) && hasSingleChild(spec) && - //equivalent to no keys starting with "brooklyn." - spec.getEnrichers().isEmpty() && - spec.getEnricherSpecs().isEmpty() && - spec.getInitializers().isEmpty() && - spec.getPolicies().isEmpty() && - spec.getPolicySpecs().isEmpty(); + //equivalent to no keys starting with "brooklyn." + spec.getEnrichers().isEmpty() && + spec.getEnricherSpecs().isEmpty() && + spec.getInitializers().isEmpty() && + spec.getPolicies().isEmpty() && + spec.getPolicySpecs().isEmpty(); + } + /** @deprecated since 0.9.0 use {@link #canUnwrapEntity(EntitySpec)} */ @Deprecated + public static boolean canPromoteChildrenInWrappedApplication(EntitySpec<? extends Application> spec) { + return canUnwrapEntity(spec); } public static boolean isWrapperApp(EntitySpec<?> spec) {
