You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ad...@apache.org on 2017/11/24 12:40:14 UTC

[32/39] ambari git commit: AMBARI-22297. Rename BlueprintImplV2 to BlueprintV2Impl (adoroszlai)

AMBARI-22297. Rename BlueprintImplV2 to BlueprintV2Impl (adoroszlai)


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

Branch: refs/heads/branch-feature-AMBARI-14714-blueprintv2
Commit: b212ee91c34d5d8d681febb131a73cf46fe272ae
Parents: 94712bc
Author: Attila Doroszlai <ad...@hortonworks.com>
Authored: Sat Nov 18 08:35:57 2017 +0100
Committer: Doroszlai, Attila <ad...@hortonworks.com>
Committed: Fri Nov 24 13:30:46 2017 +0100

----------------------------------------------------------------------
 .../internal/ExportBlueprintRequest.java        |   2 +-
 .../ambari/server/topology/BlueprintImplV2.java | 420 -------------------
 .../server/topology/BlueprintV2Factory.java     |   6 +-
 .../ambari/server/topology/BlueprintV2Impl.java | 420 +++++++++++++++++++
 .../server/topology/BlueprintImplV2Test.java    | 173 --------
 .../server/topology/BlueprintV2FactoryTest.java | 173 ++++++++
 6 files changed, 597 insertions(+), 597 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
index 565369b..6a7a121 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
@@ -144,7 +144,7 @@ public class ExportBlueprintRequest implements TopologyRequest {
       hostGroups.add(new HostGroupImpl(exportedHostGroup.getName(), bpName, stack, componentList,
           exportedHostGroup.getConfiguration(), String.valueOf(exportedHostGroup.getCardinality())));
     }
-    //blueprint = new BlueprintImplV2(bpName, hostGroups, stack, configuration, null);
+    //blueprint = new BlueprintV2Impl(bpName, hostGroups, stack, configuration, null);
   }
 
   private void createHostGroupInfo(Collection<ExportedHostGroup> exportedHostGroups) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
deleted file mode 100644
index 0dd55e8..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImplV2.java
+++ /dev/null
@@ -1,420 +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 distribut
- * ed 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 org.apache.ambari.server.topology;
-
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toMap;
-import static java.util.stream.Collectors.toSet;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-
-import javax.annotation.Nonnull;
-
-import org.apache.ambari.server.controller.StackV2;
-import org.apache.ambari.server.orm.entities.BlueprintEntity;
-import org.apache.ambari.server.state.ConfigHelper;
-import org.apache.ambari.server.state.StackId;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Blueprint implementation.
- */
-public class BlueprintImplV2 implements BlueprintV2 {
-
-  private String name;
-  private SecurityConfiguration securityConfiguration;
-  private Collection<RepositoryVersion> repositoryVersions = new ArrayList<>(0);
-  private Map<String, ServiceGroup> serviceGroups;
-  private Setting setting;
-  private final Configuration configuration = new Configuration(new HashMap<>(), new HashMap<>());;
-
-  // Transient fields
-  @JsonIgnore
-  private Map<String, HostGroupV2Impl> hostGroupMap = new HashMap<>();
-
-  @JsonIgnore
-  private Map<StackId, StackV2> stacks;
-
-  @JsonIgnore
-  private List<RepositorySetting> repoSettings;
-
-  @JsonIgnore
-  private Map<ServiceId, Service> services = new HashMap<>();
-
-  public void setStacks(Map<StackId, StackV2> stacks) {
-    this.stacks = stacks;
-    getAllServices().forEach(s -> s.setStackFromBlueprint(this));
-  }
-
-  @JsonProperty("Blueprints")
-  public void setBlueprints(Blueprints blueprints) {
-    this.name = blueprints.name;
-    this.securityConfiguration = blueprints.securityConfiguration;
-  }
-
-  @JsonProperty("Blueprints")
-  public Blueprints getBlueprints() {
-    Blueprints blueprints = new Blueprints();
-    blueprints.name = this.name;
-    blueprints.securityConfiguration = this.securityConfiguration;
-    return blueprints;
-  }
-
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public void setSecurityConfiguration(SecurityConfiguration securityConfiguration) {
-    this.securityConfiguration = securityConfiguration;
-  }
-
-  @JsonProperty("repository_versions")
-  public void setRepositoryVersions(Collection<RepositoryVersion> repositoryVersions) {
-    this.repositoryVersions = repositoryVersions;
-  }
-
-  @JsonProperty("repository_versions")
-  public Collection<RepositoryVersion> getRepositoryVersions() {
-    return this.repositoryVersions;
-  }
-
-  @JsonProperty("service_groups")
-  public void setServiceGroups(Collection<ServiceGroup> serviceGroups) {
-    this.serviceGroups = serviceGroups.stream().collect(toMap(ServiceGroup::getName, Function.identity()));
-  }
-
-  @JsonProperty("host_groups")
-  public void setHostGroups(Collection<HostGroupV2Impl> hostGroups) {
-    this.hostGroupMap = hostGroups.stream().collect(toMap(
-      HostGroupV2Impl::getName,
-      Function.identity()
-    ));
-  }
-
-  @JsonProperty("cluster_settings")
-  public void setClusterSettings(Map<String, Set<HashMap<String, String>>> properties) {
-    this.setting = new Setting(properties);
-  }
-
-  @Override
-  @JsonIgnore
-  public String getName() {
-    return name;
-  }
-
-  @Override
-  public HostGroupV2 getHostGroup(String name) {
-    return hostGroupMap.get(name);
-  }
-
-  @Override
-  @JsonIgnore
-  public Map<String, ? extends HostGroupV2> getHostGroups() {
-    return hostGroupMap;
-  }
-
-  @JsonProperty("host_groups")
-  public Collection<? extends HostGroupV2> getHostGroupsForSerialization() {
-    return hostGroupMap.values();
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<StackV2> getStacks() {
-    return stacks.values();
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<String> getStackIds() {
-    return repositoryVersions.stream().map(RepositoryVersion::getStackId).collect(toList());
-  }
-
-  @Override
-  public Collection<ServiceGroup> getServiceGroups() {
-    return serviceGroups.values();
-  }
-
-  @Override
-  public ServiceGroup getServiceGroup(String name) {
-    return serviceGroups.get(name);
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<ServiceId> getAllServiceIds() {
-    return getHostGroups().values().stream().flatMap(hg -> hg.getServiceIds().stream()).collect(toSet());
-  }
-
-  @Override
-  public Service getServiceById(ServiceId serviceId) {
-    return null;
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<Service> getServicesFromServiceGroup(ServiceGroup serviceGroup, String serviceType) {
-    if (serviceType == null) {
-      return serviceGroup.getServices();
-    } else {
-      return serviceGroup.getServices().stream().filter(
-              service -> service.getType().equalsIgnoreCase(serviceType)).collect(toList());
-    }
-  }
-
-  @Override
-  @JsonIgnore
-  public StackV2 getStackById(String stackId) {
-    return stacks.get(new StackId(stackId));
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<Service> getAllServices() {
-    return services.values();
-  }
-
-  @Override
-  @JsonIgnore
-  public Service getService(ServiceId serviceId) {
-    return services.get(serviceId);
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<String> getAllServiceTypes() {
-    return getServiceGroups().stream().flatMap(sg -> sg.getServices().stream()).map(Service::getType).collect(toSet());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<Service> getServicesByType(String serviceType) {
-    return serviceGroups.values().stream().flatMap(sg -> sg.getServiceByType(serviceType).stream()).collect(toList());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<ComponentV2> getComponents(Service service) {
-    return getHostGroupsForService(service.getId()).stream().flatMap(
-      hg -> hg.getComponents().stream()).
-      collect(toList());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<ComponentV2> getComponentsByType(Service service, String componentType) {
-    return getComponents(service).stream().filter(
-            compnoent -> compnoent.getType().equalsIgnoreCase(componentType)).collect(toList());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<ComponentV2> getComponents(ServiceId serviceId) {
-    return getHostGroupsForService(serviceId).stream().flatMap(hg -> hg.getComponents().stream()).collect(toSet());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<HostGroupV2> getHostGroupsForService(ServiceId serviceId) {
-    return getHostGroups().values().stream().filter(hg -> !hg.getComponentsByServiceId(serviceId).isEmpty()).collect(toList());
-  }
-
-  @Override
-  @JsonIgnore
-  public Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component) {
-    return hostGroupMap.values().stream().filter(hg -> hg.getComponents().contains(component)).collect(toList());
-  }
-
-  @Override
-  @JsonIgnore
-  public Configuration getConfiguration() {
-    return configuration;
-  }
-
-  private void addChildConfiguration(Configuration parent, Configuration child) {
-    child.setParentConfiguration(parent);
-    parent.getProperties().putAll(child.getProperties());
-    parent.getAttributes().putAll(child.getAttributes());
-  }
-
-  @Override
-  @JsonIgnore
-  public Setting getSetting() {
-    return this.setting;
-  }
-
-  @JsonProperty("cluster_settings")
-  public Map<String, Set<HashMap<String, String>>> getSettingForSerialization() {
-    return this.setting.getProperties();
-  }
-
-  @Nonnull
-  @Override
-  @JsonIgnore
-  public Collection<String> getAllServiceNames() {
-    return getAllServices().stream().map(Service::getName).collect(toList());
-  }
-
-  @Nonnull
-  @Override
-  public Set<String> getComponentNames(ServiceId serviceId) {
-    return getComponents(serviceId).stream().map(ComponentV2::getName).collect(toSet());
-  }
-
-  @Override
-  public String getRecoveryEnabled(ComponentV2 component) {
-    Optional<String> value =
-      setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS, Setting.SETTING_NAME_RECOVERY_ENABLED);
-    // TODO: handle service and component level settings
-    return value.orElse(null);
-  }
-
-//  private Optional<String> getSettingValue(String settingCategory, String settingName, Optional<String> nameFilter) {
-//    if (this.setting != null) {
-//      Set<HashMap<String, String>> settingValue = this.setting.getSettingValue(settingCategory);
-//      for (Map<String, String> setting : settingValue) {
-//        String name = setting.get(Setting.SETTING_NAME_NAME);
-//        if (!nameFilter.isPresent() || StringUtils.equals(name, nameFilter.get())) {
-//          String value = setting.get(settingName);
-//          if (!StringUtils.isEmpty(value)) {
-//            return Optional.of(value);
-//          }
-//        }
-//      }
-//    }
-//    return Optional.empty();
-//  }
-
-  @Override
-  public String getCredentialStoreEnabled(String serviceName) {
-    // TODO: this is a service level level setting, handle appropriately
-    return null;
-  }
-
-  @Override
-  public boolean shouldSkipFailure() {
-    Optional<String> shouldSkipFailure = setting.getSettingValue(
-      Setting.SETTING_NAME_DEPLOYMENT_SETTINGS,
-      Setting.SETTING_NAME_SKIP_FAILURE);
-    return shouldSkipFailure.isPresent() ? shouldSkipFailure.get().equalsIgnoreCase("true") : false;
-  }
-
-  @Override
-  @JsonIgnore
-  public SecurityConfiguration getSecurity() {
-    return this.securityConfiguration;
-  }
-
-  @Override
-  public void validateRequiredProperties() throws InvalidTopologyException {
-    // TODO implement
-  }
-
-  @Override
-  public void validateTopology() throws InvalidTopologyException {
-    // TODO implement
-  }
-
-
-  @Override
-  public boolean isValidConfigType(String configType) {
-    if (ConfigHelper.CLUSTER_ENV.equals(configType) || "global".equals(configType)) {
-      return true;
-    }
-    final Set<String> serviceNames =
-      getAllServices().stream().map(Service::getName).collect(toSet());
-    return getStacks().stream().anyMatch(
-      stack -> {
-        String service = stack.getServiceForConfigType(configType);
-        return serviceNames.contains(service);
-      }
-    );
-  }
-
-  public void postDeserialization() {
-    // Maintain a ServiceId -> Service map
-    this.services = getAllServiceIds().stream().collect(toMap(
-      Function.identity(),
-      serviceId -> {
-        ServiceGroup sg = getServiceGroup(serviceId.getServiceGroup());
-        Service service = null != sg ? sg.getServiceByName(serviceId.getName()) : null;
-        if (null == service) {
-          throw new IllegalStateException("Cannot find service for service id: " + serviceId);
-        }
-        return service;
-      }
-    ));
-
-    // Set Service -> ServiceGroup references and Service -> Service dependencies
-    getAllServices().forEach( s -> {
-      s.setServiceGroup(serviceGroups.get(s.getServiceGroupId()));
-      Map<ServiceId, Service> dependencies = s.getDependentServiceIds().stream().collect(toMap(
-        Function.identity(),
-        this::getService
-      ));
-      s.setDependencyMap(dependencies);
-    });
-
-
-    // Set HostGroup -> Services and Component -> Service references
-    for (HostGroupV2Impl hg: hostGroupMap.values()) {
-      hg.setServiceMap(hg.getServiceIds().stream().collect(toMap(
-        Function.identity(),
-        serviceId -> this.services.get(serviceId)
-      )));
-      for (ComponentV2 comp: hg.getComponents()) {
-        comp.setService(hg.getService(comp.getServiceId()));
-      }
-    }
-  }
-
-  @Override
-  public BlueprintEntity toEntity() {
-    throw new UnsupportedOperationException("This is not supported here and will be removed. Pls. use BlueprintV2Factory");
-  }
-
-  @Override
-  public List<RepositorySetting> getRepositorySettings() {
-    return repoSettings;
-  }
-
-  /**
-   * Class to support Jackson data binding. Instances are used only temporarily during serialization
-   */
-  public class Blueprints {
-    @JsonProperty("blueprint_name")
-    public String name;
-    @JsonProperty("security")
-    public SecurityConfiguration securityConfiguration;
-
-    public Blueprints() { }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
index 3262c54..8971399 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Factory.java
@@ -102,13 +102,13 @@ public class BlueprintV2Factory {
   }
 
   public BlueprintV2 convertFromJson(String json) throws IOException {
-    BlueprintImplV2 blueprintV2 = getObjectMapper().readValue(json, BlueprintImplV2.class);
+    BlueprintV2Impl blueprintV2 = getObjectMapper().readValue(json, BlueprintV2Impl.class);
     blueprintV2.postDeserialization();
     updateStacks(blueprintV2);
     return blueprintV2;
   }
 
-  private void updateStacks(BlueprintImplV2 blueprintV2) {
+  private void updateStacks(BlueprintV2Impl blueprintV2) {
     Map<StackId, StackV2> stacks = blueprintV2.getRepositoryVersions().stream().collect(Collectors.toMap(
       rv -> new StackId(rv.getStackId()),
       rv -> parseStack(new StackId(rv.getStackId()), rv.getRepositoryVersion())
@@ -165,7 +165,7 @@ public class BlueprintV2Factory {
     }
     ObjectMapper om = getObjectMapper();
     String json = om.writeValueAsString(properties);
-    BlueprintImplV2 blueprint = om.readValue(json, BlueprintImplV2.class);
+    BlueprintV2Impl blueprint = om.readValue(json, BlueprintV2Impl.class);
     blueprint.postDeserialization();
     updateStacks(blueprint);
     blueprint.setSecurityConfiguration(securityConfiguration);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Impl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Impl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Impl.java
new file mode 100644
index 0000000..edab552
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintV2Impl.java
@@ -0,0 +1,420 @@
+/*
+ * 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 distribut
+ * ed 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 org.apache.ambari.server.topology;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.apache.ambari.server.controller.StackV2;
+import org.apache.ambari.server.orm.entities.BlueprintEntity;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.StackId;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Blueprint implementation.
+ */
+public class BlueprintV2Impl implements BlueprintV2 {
+
+  private String name;
+  private SecurityConfiguration securityConfiguration;
+  private Collection<RepositoryVersion> repositoryVersions = new ArrayList<>(0);
+  private Map<String, ServiceGroup> serviceGroups;
+  private Setting setting;
+  private final Configuration configuration = new Configuration(new HashMap<>(), new HashMap<>());;
+
+  // Transient fields
+  @JsonIgnore
+  private Map<String, HostGroupV2Impl> hostGroupMap = new HashMap<>();
+
+  @JsonIgnore
+  private Map<StackId, StackV2> stacks;
+
+  @JsonIgnore
+  private List<RepositorySetting> repoSettings;
+
+  @JsonIgnore
+  private Map<ServiceId, Service> services = new HashMap<>();
+
+  public void setStacks(Map<StackId, StackV2> stacks) {
+    this.stacks = stacks;
+    getAllServices().forEach(s -> s.setStackFromBlueprint(this));
+  }
+
+  @JsonProperty("Blueprints")
+  public void setBlueprints(Blueprints blueprints) {
+    this.name = blueprints.name;
+    this.securityConfiguration = blueprints.securityConfiguration;
+  }
+
+  @JsonProperty("Blueprints")
+  public Blueprints getBlueprints() {
+    Blueprints blueprints = new Blueprints();
+    blueprints.name = this.name;
+    blueprints.securityConfiguration = this.securityConfiguration;
+    return blueprints;
+  }
+
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public void setSecurityConfiguration(SecurityConfiguration securityConfiguration) {
+    this.securityConfiguration = securityConfiguration;
+  }
+
+  @JsonProperty("repository_versions")
+  public void setRepositoryVersions(Collection<RepositoryVersion> repositoryVersions) {
+    this.repositoryVersions = repositoryVersions;
+  }
+
+  @JsonProperty("repository_versions")
+  public Collection<RepositoryVersion> getRepositoryVersions() {
+    return this.repositoryVersions;
+  }
+
+  @JsonProperty("service_groups")
+  public void setServiceGroups(Collection<ServiceGroup> serviceGroups) {
+    this.serviceGroups = serviceGroups.stream().collect(toMap(ServiceGroup::getName, Function.identity()));
+  }
+
+  @JsonProperty("host_groups")
+  public void setHostGroups(Collection<HostGroupV2Impl> hostGroups) {
+    this.hostGroupMap = hostGroups.stream().collect(toMap(
+      HostGroupV2Impl::getName,
+      Function.identity()
+    ));
+  }
+
+  @JsonProperty("cluster_settings")
+  public void setClusterSettings(Map<String, Set<HashMap<String, String>>> properties) {
+    this.setting = new Setting(properties);
+  }
+
+  @Override
+  @JsonIgnore
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public HostGroupV2 getHostGroup(String name) {
+    return hostGroupMap.get(name);
+  }
+
+  @Override
+  @JsonIgnore
+  public Map<String, ? extends HostGroupV2> getHostGroups() {
+    return hostGroupMap;
+  }
+
+  @JsonProperty("host_groups")
+  public Collection<? extends HostGroupV2> getHostGroupsForSerialization() {
+    return hostGroupMap.values();
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<StackV2> getStacks() {
+    return stacks.values();
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<String> getStackIds() {
+    return repositoryVersions.stream().map(RepositoryVersion::getStackId).collect(toList());
+  }
+
+  @Override
+  public Collection<ServiceGroup> getServiceGroups() {
+    return serviceGroups.values();
+  }
+
+  @Override
+  public ServiceGroup getServiceGroup(String name) {
+    return serviceGroups.get(name);
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<ServiceId> getAllServiceIds() {
+    return getHostGroups().values().stream().flatMap(hg -> hg.getServiceIds().stream()).collect(toSet());
+  }
+
+  @Override
+  public Service getServiceById(ServiceId serviceId) {
+    return null;
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<Service> getServicesFromServiceGroup(ServiceGroup serviceGroup, String serviceType) {
+    if (serviceType == null) {
+      return serviceGroup.getServices();
+    } else {
+      return serviceGroup.getServices().stream().filter(
+              service -> service.getType().equalsIgnoreCase(serviceType)).collect(toList());
+    }
+  }
+
+  @Override
+  @JsonIgnore
+  public StackV2 getStackById(String stackId) {
+    return stacks.get(new StackId(stackId));
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<Service> getAllServices() {
+    return services.values();
+  }
+
+  @Override
+  @JsonIgnore
+  public Service getService(ServiceId serviceId) {
+    return services.get(serviceId);
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<String> getAllServiceTypes() {
+    return getServiceGroups().stream().flatMap(sg -> sg.getServices().stream()).map(Service::getType).collect(toSet());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<Service> getServicesByType(String serviceType) {
+    return serviceGroups.values().stream().flatMap(sg -> sg.getServiceByType(serviceType).stream()).collect(toList());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<ComponentV2> getComponents(Service service) {
+    return getHostGroupsForService(service.getId()).stream().flatMap(
+      hg -> hg.getComponents().stream()).
+      collect(toList());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<ComponentV2> getComponentsByType(Service service, String componentType) {
+    return getComponents(service).stream().filter(
+            compnoent -> compnoent.getType().equalsIgnoreCase(componentType)).collect(toList());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<ComponentV2> getComponents(ServiceId serviceId) {
+    return getHostGroupsForService(serviceId).stream().flatMap(hg -> hg.getComponents().stream()).collect(toSet());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<HostGroupV2> getHostGroupsForService(ServiceId serviceId) {
+    return getHostGroups().values().stream().filter(hg -> !hg.getComponentsByServiceId(serviceId).isEmpty()).collect(toList());
+  }
+
+  @Override
+  @JsonIgnore
+  public Collection<HostGroupV2> getHostGroupsForComponent(ComponentV2 component) {
+    return hostGroupMap.values().stream().filter(hg -> hg.getComponents().contains(component)).collect(toList());
+  }
+
+  @Override
+  @JsonIgnore
+  public Configuration getConfiguration() {
+    return configuration;
+  }
+
+  private void addChildConfiguration(Configuration parent, Configuration child) {
+    child.setParentConfiguration(parent);
+    parent.getProperties().putAll(child.getProperties());
+    parent.getAttributes().putAll(child.getAttributes());
+  }
+
+  @Override
+  @JsonIgnore
+  public Setting getSetting() {
+    return this.setting;
+  }
+
+  @JsonProperty("cluster_settings")
+  public Map<String, Set<HashMap<String, String>>> getSettingForSerialization() {
+    return this.setting.getProperties();
+  }
+
+  @Nonnull
+  @Override
+  @JsonIgnore
+  public Collection<String> getAllServiceNames() {
+    return getAllServices().stream().map(Service::getName).collect(toList());
+  }
+
+  @Nonnull
+  @Override
+  public Set<String> getComponentNames(ServiceId serviceId) {
+    return getComponents(serviceId).stream().map(ComponentV2::getName).collect(toSet());
+  }
+
+  @Override
+  public String getRecoveryEnabled(ComponentV2 component) {
+    Optional<String> value =
+      setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS, Setting.SETTING_NAME_RECOVERY_ENABLED);
+    // TODO: handle service and component level settings
+    return value.orElse(null);
+  }
+
+//  private Optional<String> getSettingValue(String settingCategory, String settingName, Optional<String> nameFilter) {
+//    if (this.setting != null) {
+//      Set<HashMap<String, String>> settingValue = this.setting.getSettingValue(settingCategory);
+//      for (Map<String, String> setting : settingValue) {
+//        String name = setting.get(Setting.SETTING_NAME_NAME);
+//        if (!nameFilter.isPresent() || StringUtils.equals(name, nameFilter.get())) {
+//          String value = setting.get(settingName);
+//          if (!StringUtils.isEmpty(value)) {
+//            return Optional.of(value);
+//          }
+//        }
+//      }
+//    }
+//    return Optional.empty();
+//  }
+
+  @Override
+  public String getCredentialStoreEnabled(String serviceName) {
+    // TODO: this is a service level level setting, handle appropriately
+    return null;
+  }
+
+  @Override
+  public boolean shouldSkipFailure() {
+    Optional<String> shouldSkipFailure = setting.getSettingValue(
+      Setting.SETTING_NAME_DEPLOYMENT_SETTINGS,
+      Setting.SETTING_NAME_SKIP_FAILURE);
+    return shouldSkipFailure.isPresent() ? shouldSkipFailure.get().equalsIgnoreCase("true") : false;
+  }
+
+  @Override
+  @JsonIgnore
+  public SecurityConfiguration getSecurity() {
+    return this.securityConfiguration;
+  }
+
+  @Override
+  public void validateRequiredProperties() throws InvalidTopologyException {
+    // TODO implement
+  }
+
+  @Override
+  public void validateTopology() throws InvalidTopologyException {
+    // TODO implement
+  }
+
+
+  @Override
+  public boolean isValidConfigType(String configType) {
+    if (ConfigHelper.CLUSTER_ENV.equals(configType) || "global".equals(configType)) {
+      return true;
+    }
+    final Set<String> serviceNames =
+      getAllServices().stream().map(Service::getName).collect(toSet());
+    return getStacks().stream().anyMatch(
+      stack -> {
+        String service = stack.getServiceForConfigType(configType);
+        return serviceNames.contains(service);
+      }
+    );
+  }
+
+  public void postDeserialization() {
+    // Maintain a ServiceId -> Service map
+    this.services = getAllServiceIds().stream().collect(toMap(
+      Function.identity(),
+      serviceId -> {
+        ServiceGroup sg = getServiceGroup(serviceId.getServiceGroup());
+        Service service = null != sg ? sg.getServiceByName(serviceId.getName()) : null;
+        if (null == service) {
+          throw new IllegalStateException("Cannot find service for service id: " + serviceId);
+        }
+        return service;
+      }
+    ));
+
+    // Set Service -> ServiceGroup references and Service -> Service dependencies
+    getAllServices().forEach( s -> {
+      s.setServiceGroup(serviceGroups.get(s.getServiceGroupId()));
+      Map<ServiceId, Service> dependencies = s.getDependentServiceIds().stream().collect(toMap(
+        Function.identity(),
+        this::getService
+      ));
+      s.setDependencyMap(dependencies);
+    });
+
+
+    // Set HostGroup -> Services and Component -> Service references
+    for (HostGroupV2Impl hg: hostGroupMap.values()) {
+      hg.setServiceMap(hg.getServiceIds().stream().collect(toMap(
+        Function.identity(),
+        serviceId -> this.services.get(serviceId)
+      )));
+      for (ComponentV2 comp: hg.getComponents()) {
+        comp.setService(hg.getService(comp.getServiceId()));
+      }
+    }
+  }
+
+  @Override
+  public BlueprintEntity toEntity() {
+    throw new UnsupportedOperationException("This is not supported here and will be removed. Pls. use BlueprintV2Factory");
+  }
+
+  @Override
+  public List<RepositorySetting> getRepositorySettings() {
+    return repoSettings;
+  }
+
+  /**
+   * Class to support Jackson data binding. Instances are used only temporarily during serialization
+   */
+  public class Blueprints {
+    @JsonProperty("blueprint_name")
+    public String name;
+    @JsonProperty("security")
+    public SecurityConfiguration securityConfiguration;
+
+    public Blueprints() { }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplV2Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplV2Test.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplV2Test.java
deleted file mode 100644
index 548ee18..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintImplV2Test.java
+++ /dev/null
@@ -1,173 +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 org.apache.ambari.server.topology;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.ambari.server.controller.StackV2;
-import org.apache.ambari.server.controller.StackV2Factory;
-import org.apache.ambari.server.state.StackId;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.io.Resources;
-
-public class BlueprintImplV2Test {
-
-  static String BLUEPRINTV2_JSON;
-  static String BLUEPRINTV2_2_JSON;
-
-  BlueprintV2Factory blueprintFactory;
-
-  @BeforeClass
-  public static void setUpClass() throws Exception {
-    BLUEPRINTV2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2.json"), Charsets.UTF_8);
-    BLUEPRINTV2_2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2_2.json"), Charsets.UTF_8);
-  }
-
-  @Before
-  public void setUp() throws Exception {
-    StackV2Factory stackFactory = mock(StackV2Factory.class);
-    when(stackFactory.create(any(StackId.class))).thenAnswer(invocation -> {
-      StackId stackId = invocation.getArgumentAt(0, StackId.class);
-      StackV2 stack = new StackV2(stackId.getStackName(), stackId.getStackVersion(), stackId.getStackVersion() + ".0-1",
-        new HashMap<>(), new HashMap<>(), new HashMap<>(),
-        new HashMap<>(), new HashMap<>(), new HashMap<>(),
-        new HashMap<>(), new HashMap<>(), new HashMap<>());
-      return stack;
-    });
-    blueprintFactory = BlueprintV2Factory.create(stackFactory);
-    blueprintFactory.setPrettyPrintJson(true);
-  }
-
-  @Test
-  public void testSerialization_parseJsonAsBlueprint() throws Exception {
-    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
-    assertEquals(new StackId("HDPCORE", "3.0.0"),
-      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
-    assertEquals(2, bp.getStackIds().size());
-    assertEquals(7, bp.getAllServiceIds().size());
-    assertEquals(2, bp.getServiceGroups().size());
-  }
-
-  @Test
-  public void testSerialization_parseJsonAsMap() throws Exception {
-    ObjectMapper mapper = blueprintFactory.getObjectMapper();
-    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_JSON, HashMap.class);
-    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
-    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
-    assertEquals("blueprint-def", getByPath(blueprintAsMap,
-      ImmutableList.of("Blueprints", "blueprint_name")));
-    assertEquals(2, getAsList(blueprintAsMap, "service_groups").size());
-    assertEquals("StreamSG", getByPath(blueprintAsMap,
-      ImmutableList.of("service_groups", 1, "name")));
-    assertEquals(2, getAsList(blueprintAsMap, "repository_versions").size());
-    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
-    assertEquals("host_group_1", getByPath(blueprintAsMap,
-      ImmutableList.of("host_groups", 0, "name")));
-    System.out.println(blueprintAsMap);
-  }
-
-  @Test
-  public void testSerialization_serializeBlueprint() throws Exception {
-    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
-    String serialized = blueprintFactory.convertToJson(bp);
-    // Test that serialized blueprint can be read again
-    bp = blueprintFactory.convertFromJson(serialized);
-    assertEquals(2, bp.getStackIds().size());
-    assertEquals(7, bp.getAllServiceIds().size());
-    assertEquals(2, bp.getServiceGroups().size());
-  }
-
-  @Test
-  public void testSerialization2_parseJsonAsBlueprint() throws Exception {
-    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
-    assertEquals(new StackId("HDP", "3.0.0"),
-      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
-    assertEquals(1, bp.getStackIds().size());
-    assertEquals(4, bp.getAllServiceIds().size());
-    assertEquals(1, bp.getServiceGroups().size());
-  }
-
-  @Test
-  public void testSerialization2_parseJsonAsMap() throws Exception {
-    ObjectMapper mapper = blueprintFactory.getObjectMapper();
-    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_2_JSON, HashMap.class);
-    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
-    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
-    assertEquals("blueprint-def", getByPath(blueprintAsMap,
-      ImmutableList.of("Blueprints", "blueprint_name")));
-    assertEquals(1, getAsList(blueprintAsMap, "service_groups").size());
-    assertEquals("CoreSG", getByPath(blueprintAsMap,
-      ImmutableList.of("service_groups", 0, "name")));
-    assertEquals(1, getAsList(blueprintAsMap, "repository_versions").size());
-    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
-    assertEquals("host_group_1", getByPath(blueprintAsMap,
-      ImmutableList.of("host_groups", 0, "name")));
-    System.out.println(blueprintAsMap);
-  }
-
-  @Test
-  public void testSerialization2_serializeBlueprint() throws Exception {
-    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
-    String serialized = blueprintFactory.convertToJson(bp);
-    // Test that serialized blueprint can be read again
-    bp = blueprintFactory.convertFromJson(serialized);
-    assertEquals(1, bp.getStackIds().size());
-    assertEquals(4, bp.getAllServiceIds().size());
-    assertEquals(1, bp.getServiceGroups().size());
-  }
-
-  private static Map<String, Object> getAsMap(Map<String, Object> parentMap, String key) {
-    return (Map<String, Object>)parentMap.get(key);
-  }
-
-  private static List<Object> getAsList(Map<String, Object> parentMap, String key) {
-    return (List<Object>)parentMap.get(key);
-  }
-
-  private static Object getByPath(Map<String, Object> initialMap, List<Object> path) {
-    Object returnValue = initialMap;
-    for(Object key: path) {
-      if (key instanceof String) { // this element is a map
-        returnValue = ((Map<String, Object>)returnValue).get(key);
-        Preconditions.checkNotNull(returnValue, "No value for key: " + key);
-      }
-      else if (key instanceof Integer) { // this element is an arraylist
-        returnValue = ((List<Object>)returnValue).get((Integer)key);
-      }
-      else {
-        throw new IllegalArgumentException("Invalid path element: " + key);
-      }
-    }
-    return returnValue;
-  }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b212ee91/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintV2FactoryTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintV2FactoryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintV2FactoryTest.java
new file mode 100644
index 0000000..6ae8039
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/BlueprintV2FactoryTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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 org.apache.ambari.server.topology;
+
+import static org.easymock.EasyMock.anyString;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ambari.server.controller.StackV2;
+import org.apache.ambari.server.controller.StackV2Factory;
+import org.apache.ambari.server.state.StackId;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.Resources;
+
+public class BlueprintV2FactoryTest {
+
+  static String BLUEPRINTV2_JSON;
+  static String BLUEPRINTV2_2_JSON;
+
+  BlueprintV2Factory blueprintFactory;
+
+  @BeforeClass
+  public static void setUpClass() throws Exception {
+    BLUEPRINTV2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2.json"), Charsets.UTF_8);
+    BLUEPRINTV2_2_JSON = Resources.toString(Resources.getResource("blueprintv2/blueprintv2_2.json"), Charsets.UTF_8);
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    StackV2Factory stackFactory = mock(StackV2Factory.class);
+    when(stackFactory.create(any(StackId.class), anyString())).thenAnswer(invocation -> {
+      StackId stackId = invocation.getArgumentAt(0, StackId.class);
+      return new StackV2(stackId.getStackName(), stackId.getStackVersion(), invocation.getArgumentAt(1, String.class),
+        new HashMap<>(), new HashMap<>(), new HashMap<>(),
+        new HashMap<>(), new HashMap<>(), new HashMap<>(),
+        new HashMap<>(), new HashMap<>(), new HashMap<>());
+    });
+    blueprintFactory = BlueprintV2Factory.create(stackFactory);
+    blueprintFactory.setPrettyPrintJson(true);
+  }
+
+  @Test
+  public void testSerialization_parseJsonAsBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
+    assertEquals(new StackId("HDPCORE", "3.0.0"),
+      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
+    assertEquals(2, bp.getStackIds().size());
+    assertEquals(7, bp.getAllServiceIds().size());
+    assertEquals(2, bp.getServiceGroups().size());
+  }
+
+  @Test
+  public void testSerialization_parseJsonAsMap() throws Exception {
+    ObjectMapper mapper = blueprintFactory.getObjectMapper();
+    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_JSON, HashMap.class);
+    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
+    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
+    assertEquals("blueprint-def", getByPath(blueprintAsMap,
+      ImmutableList.of("Blueprints", "blueprint_name")));
+    assertEquals(2, getAsList(blueprintAsMap, "service_groups").size());
+    assertEquals("StreamSG", getByPath(blueprintAsMap,
+      ImmutableList.of("service_groups", 1, "name")));
+    assertEquals(2, getAsList(blueprintAsMap, "repository_versions").size());
+    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
+    assertEquals("host_group_1", getByPath(blueprintAsMap,
+      ImmutableList.of("host_groups", 0, "name")));
+    System.out.println(blueprintAsMap);
+  }
+
+  @Test
+  public void testSerialization_serializeBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_JSON);
+    String serialized = blueprintFactory.convertToJson(bp);
+    // Test that serialized blueprint can be read again
+    bp = blueprintFactory.convertFromJson(serialized);
+    assertEquals(2, bp.getStackIds().size());
+    assertEquals(7, bp.getAllServiceIds().size());
+    assertEquals(2, bp.getServiceGroups().size());
+  }
+
+  @Test
+  public void testSerialization2_parseJsonAsBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
+    assertEquals(new StackId("HDP", "3.0.0"),
+      bp.getServiceGroups().iterator().next().getServices().iterator().next().getStack().getStackId());
+    assertEquals(1, bp.getStackIds().size());
+    assertEquals(4, bp.getAllServiceIds().size());
+    assertEquals(1, bp.getServiceGroups().size());
+  }
+
+  @Test
+  public void testSerialization2_parseJsonAsMap() throws Exception {
+    ObjectMapper mapper = blueprintFactory.getObjectMapper();
+    Map<String, Object> blueprintAsMap = mapper.readValue(BLUEPRINTV2_2_JSON, HashMap.class);
+    assertEquals(2, getAsMap(blueprintAsMap, "cluster_settings").size());
+    assertEquals(2, getAsMap(blueprintAsMap, "Blueprints").size());
+    assertEquals("blueprint-def", getByPath(blueprintAsMap,
+      ImmutableList.of("Blueprints", "blueprint_name")));
+    assertEquals(1, getAsList(blueprintAsMap, "service_groups").size());
+    assertEquals("CoreSG", getByPath(blueprintAsMap,
+      ImmutableList.of("service_groups", 0, "name")));
+    assertEquals(1, getAsList(blueprintAsMap, "repository_versions").size());
+    assertEquals(1, getAsList(blueprintAsMap, "host_groups").size());
+    assertEquals("host_group_1", getByPath(blueprintAsMap,
+      ImmutableList.of("host_groups", 0, "name")));
+    System.out.println(blueprintAsMap);
+  }
+
+  @Test
+  public void testSerialization2_serializeBlueprint() throws Exception {
+    BlueprintV2 bp = blueprintFactory.convertFromJson(BLUEPRINTV2_2_JSON);
+    String serialized = blueprintFactory.convertToJson(bp);
+    // Test that serialized blueprint can be read again
+    bp = blueprintFactory.convertFromJson(serialized);
+    assertEquals(1, bp.getStackIds().size());
+    assertEquals(4, bp.getAllServiceIds().size());
+    assertEquals(1, bp.getServiceGroups().size());
+  }
+
+  private static Map<String, Object> getAsMap(Map<String, Object> parentMap, String key) {
+    return (Map<String, Object>)parentMap.get(key);
+  }
+
+  private static List<Object> getAsList(Map<String, Object> parentMap, String key) {
+    return (List<Object>)parentMap.get(key);
+  }
+
+  private static Object getByPath(Map<String, Object> initialMap, List<Object> path) {
+    Object returnValue = initialMap;
+    for(Object key: path) {
+      if (key instanceof String) { // this element is a map
+        returnValue = ((Map<String, Object>)returnValue).get(key);
+        Preconditions.checkNotNull(returnValue, "No value for key: " + key);
+      }
+      else if (key instanceof Integer) { // this element is an arraylist
+        returnValue = ((List<Object>)returnValue).get((Integer)key);
+      }
+      else {
+        throw new IllegalArgumentException("Invalid path element: " + key);
+      }
+    }
+    return returnValue;
+  }
+
+}
\ No newline at end of file