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/11/13 23:23:41 UTC

[08/18] incubator-brooklyn git commit: Catalog versioning - Clean up the CatalogItem interface

Catalog versioning - Clean up the CatalogItem interface

  * override id to return getCatalogItemId()
  * introduce symbolicName (analogous to old id/registeredTypeName)
  * deprecate registeredTypeName in favor of symbolicName
  * getCatalogItemId() should return symbolicName:version
  * deprecate useless CatalogLibraries interface
  * keep backwards compatibility for deserialization (registeredTypeName, libraries)
  * remove CONGIGURATION catalog item type

Clean up the CatalogItemSymmary REST interface and udate JSGUI to match

  * add symbolicName
  * remove registeredTypeName
  * keep id, but construct from other arguments
  * keep type, but alias to symbolicName


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

Branch: refs/heads/master
Commit: 5661ac492962a6a2b4b672b28d19a6698d26734b
Parents: 8d3a8c9
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Mon Nov 10 17:27:56 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Nov 13 11:49:51 2014 +0200

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |  26 +--
 .../main/java/brooklyn/catalog/CatalogItem.java |  20 +-
 .../brooklyn/mementos/CatalogItemMemento.java   |   8 +-
 .../java/brooklyn/catalog/CatalogLoadMode.java  |   1 -
 .../brooklyn/catalog/CatalogPredicates.java     |  16 +-
 .../catalog/internal/BasicBrooklynCatalog.java  |  83 ++++----
 .../catalog/internal/CatalogBundleDto.java      |   8 +
 .../catalog/internal/CatalogClasspathDo.java    |  17 +-
 .../internal/CatalogConfigurationDto.java       |  44 -----
 .../brooklyn/catalog/internal/CatalogDo.java    |  36 +---
 .../catalog/internal/CatalogItemBuilder.java    |  46 +++--
 .../catalog/internal/CatalogItemDo.java         |  14 +-
 .../internal/CatalogItemDtoAbstract.java        | 189 ++++++++++++++-----
 .../catalog/internal/CatalogItemId.java         |  67 -------
 .../catalog/internal/CatalogLibrariesDo.java    |   1 +
 .../catalog/internal/CatalogLibrariesDto.java   |  70 +------
 .../brooklyn/catalog/internal/CatalogUtils.java |  32 ++--
 .../catalog/internal/CatalogXmlSerializer.java  |   5 +-
 .../rebind/BasicCatalogItemRebindSupport.java   |   5 +-
 .../rebind/dto/BasicCatalogItemMemento.java     |  55 ++++--
 .../entity/rebind/dto/MementosGenerators.java   |  19 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  15 +-
 .../BrooklynMementoPersisterToObjectStore.java  |   4 +-
 .../brooklyn/camp/lite/CampYamlLiteTest.java    |  32 ++--
 .../catalog/internal/CatalogDtoTest.java        |  12 +-
 .../catalog/internal/CatalogLoadTest.java       |   6 +-
 .../catalog/internal/CatalogScanTest.java       |  13 +-
 .../entity/rebind/RebindCatalogItemTest.java    |   2 +-
 ...talogWhenCatalogPersistenceDisabledTest.java |   2 +-
 .../entity/rebind/RebindTestFixture.java        |  16 +-
 .../persister/XmlMementoSerializerTest.java     |   6 +-
 .../osgi/OsgiVersionMoreEntityTest.java         |  18 +-
 .../CatalogOsgiVersionMoreEntityTest.java       |  12 +-
 .../brooklyn/catalog/CatalogYamlEntityTest.java |  84 ++++-----
 .../brooklyn/catalog/CatalogYamlPolicyTest.java |  36 ++--
 .../src/main/webapp/assets/js/model/entity.js   |   2 +-
 .../src/main/webapp/assets/js/view/catalog.js   |   9 +-
 .../rest/domain/CatalogEntitySummary.java       |   4 +-
 .../rest/domain/CatalogItemSummary.java         |  32 ++--
 .../rest/domain/CatalogPolicySummary.java       |   4 +-
 .../rest/resources/CatalogResource.java         |   4 -
 .../rest/transform/CatalogTransformer.java      |  24 +--
 .../rest/resources/CatalogResourceTest.java     |  39 ++--
 .../main/java/brooklyn/util/io/FileUtil.java    |  10 +
 44 files changed, 546 insertions(+), 602 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 5b0a5cc..ce0d928 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -25,35 +25,37 @@ import com.google.common.base.Predicate;
 
 public interface BrooklynCatalog {
 
-    /** @return The item with the given ID or {@link brooklyn.catalog.CatalogItem#getRegisteredTypeName()
-     * registeredTypeName}, or null if not found.
+    /** @return The item with the given {@link brooklyn.catalog.CatalogItem#getSymbolicName()
+     * symbolicName}, or null if not found.
      * @deprecated since 0.7.0 use {@link #getCatalogItem(String, String)} */
     @Deprecated
-    CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName);
+    CatalogItem<?,?> getCatalogItem(String symbolicName);
 
-    /** @return The item with the given ID or {@link brooklyn.catalog.CatalogItem#getRegisteredTypeName()
-     * registeredTypeName}, or null if not found. */
-    CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName, String version);
+    /** @return The item with the given {@link brooklyn.catalog.CatalogItem#getSymbolicName()
+     * symbolicName}, or null if not found. */
+    CatalogItem<?,?> getCatalogItem(String symbolicName, String version);
 
-    /** @return Deletes the item with the given ID
+    /** @return Deletes the item with the given
+     *  {@link brooklyn.catalog.CatalogItem#getSymbolicName() symbolicName}
      * @throws NoSuchElementException if not found
      * @deprecated since 0.7.0 use {@link #deleteCatalogItem(String, String)} */
     @Deprecated
-    void deleteCatalogItem(String id);
+    void deleteCatalogItem(String symbolicName);
 
-    /** @return Deletes the item with the given ID and version
+    /** @return Deletes the item with the given {@link brooklyn.catalog.CatalogItem#getSymbolicName()
+     * symbolicName} and version
      * @throws NoSuchElementException if not found */
-    void deleteCatalogItem(String id, String version);
+    void deleteCatalogItem(String symbolicName, String version);
 
     /** variant of {@link #getCatalogItem(String)} which checks (and casts) type for convenience
      * (returns null if type does not match)
      * @deprecated since 0.7.0 use {@link #getCatalogItem(Class<T>, String, String)} */
     @Deprecated
-    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id);
+    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String symbolicName);
 
     /** variant of {@link #getCatalogItem(String, String)} which checks (and casts) type for convenience
      * (returns null if type does not match) */
-    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id, String version);
+    <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String symbolicName, String version);
 
     /** @return All items in the catalog */
     <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index 1f67ccd..c58dcd3 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -20,7 +20,6 @@ package brooklyn.catalog;
 
 import java.util.Collection;
 
-import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import brooklyn.basic.BrooklynObject;
@@ -34,7 +33,7 @@ import com.google.common.annotations.Beta;
 public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
     
     public static enum CatalogItemType {
-        TEMPLATE, ENTITY, POLICY, CONFIGURATION
+        TEMPLATE, ENTITY, POLICY
     }
     
     public static interface CatalogBundle {
@@ -46,7 +45,7 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
         public boolean isNamed();
     }
 
-    @Beta
+    @Deprecated
     public static interface CatalogItemLibraries {
         Collection<CatalogBundle> getBundles();
     }
@@ -59,25 +58,22 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
     /** @return The type of the spec e.g. EntitySpec corresponding to {@link #getCatalogItemJavaType()} */
     public Class<SpecT> getSpecType();
     
-    /** @return The type name registered in the catalog for this item */
-    @Nonnull
-    public String getRegisteredTypeName();
-    
     /** @return The underlying java type of the item represented, or null if not known (e.g. if it comes from yaml) */
-    // TODO references to this should probably query getRegisteredType
     @Nullable public String getJavaType();
 
     /** @deprecated since 0.7.0. Use {@link #getDisplayName} */
     @Deprecated
     public String getName();
 
-    public String getDescription();
+    @Nullable public String getDescription();
+
+    @Nullable public String getIconUrl();
 
-    public String getIconUrl();
+    public String getSymbolicName();
 
     public String getVersion();
 
-    public CatalogItemLibraries getLibraries();
+    public Collection<CatalogBundle> getLibraries();
 
     public String toXmlString();
 
@@ -87,7 +83,7 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
     @Override
     RebindSupport<CatalogItemMemento> getRebindSupport();
     
-    /** Built up from {@link #getId()} and {@link #getVersion()}.
+    /** Built up from {@link #getSymbolicName()} and {@link #getVersion()}.
      * 
      * (It is a bit self-referential having this method on this type of {@link BrooklynObject},
      * but it is easier this than making the interface hierarchy more complicated.) */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/api/src/main/java/brooklyn/mementos/CatalogItemMemento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/CatalogItemMemento.java b/api/src/main/java/brooklyn/mementos/CatalogItemMemento.java
index 9140d24..d3163e5 100644
--- a/api/src/main/java/brooklyn/mementos/CatalogItemMemento.java
+++ b/api/src/main/java/brooklyn/mementos/CatalogItemMemento.java
@@ -18,7 +18,7 @@
  */
 package brooklyn.mementos;
 
-import com.google.common.annotations.Beta;
+import java.util.Collection;
 
 import brooklyn.catalog.CatalogItem;
 
@@ -26,7 +26,7 @@ public interface CatalogItemMemento extends Memento {
 
     String getDescription();
 
-    String getRegisteredTypeName();
+    String getSymbolicName();
 
     String getIconUrl();
 
@@ -36,9 +36,7 @@ public interface CatalogItemMemento extends Memento {
 
     String getJavaType();
 
-    // necessary or part of plan yaml? Necessary for now, but .. ?
-    @Beta
-    CatalogItem.CatalogItemLibraries getLibraries();
+    Collection<CatalogItem.CatalogBundle> getBundles();
 
     CatalogItem.CatalogItemType getCatalogItemType();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java b/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
index 9ea449a..259f545 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
@@ -18,7 +18,6 @@
  */
 package brooklyn.catalog;
 
-import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.rebind.persister.PersistMode;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
index 5f9499a..25b943e 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
@@ -56,20 +56,30 @@ public class CatalogPredicates {
         }
     };
 
+    @Deprecated
     public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> name(final Predicate<? super String> filter) {
+        return displayName(filter);
+    }
+
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> displayName(final Predicate<? super String> filter) {
         return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
             public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
-                return (item != null) && filter.apply(item.getName());
+                return (item != null) && filter.apply(item.getDisplayName());
             }
         };
     }
 
-    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredType(final Predicate<? super String> filter) {
+    @Deprecated
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredTypeName(final Predicate<? super String> filter) {
+        return symbolicName(filter);
+    }
+
+    public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> symbolicName(final Predicate<? super String> filter) {
         return new Predicate<CatalogItem<T,SpecT>>() {
             @Override
             public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
-                return (item != null) && filter.apply(item.getRegisteredTypeName());
+                return (item != null) && filter.apply(item.getSymbolicName());
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index e560ae2..43da70f 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -27,7 +27,7 @@ import io.brooklyn.camp.spi.pdp.Service;
 
 import java.io.FileNotFoundException;
 import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
@@ -40,6 +40,7 @@ import brooklyn.basic.AbstractBrooklynObjectSpec;
 import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogItem.CatalogBundle;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.entity.proxying.EntitySpec;
@@ -51,7 +52,6 @@ import brooklyn.policy.Policy;
 import brooklyn.policy.PolicySpec;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.LoadedClassLoader;
@@ -167,15 +167,12 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return catalog;
     }
 
-    protected CatalogItemDo<?,?> getCatalogItemDo(String idOrRegisteredTypeName, String version) {
-        CatalogItemId versionedId = new CatalogItemId(idOrRegisteredTypeName, version);
+    protected CatalogItemDo<?,?> getCatalogItemDo(String symbolicName, String version) {
+        String versionedId = CatalogUtils.getVersionedId(symbolicName, version);
         CatalogItemDo<?, ?> item = null;
-        // TODO really need to remove redundancy of id v registered type;
-        // should also remove "manual additions" bucket; just have one map a la osgi
+        //TODO should remove "manual additions" bucket; just have one map a la osgi
         if (manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getIdCache().get(versionedId);
         if (item == null) item = catalog.getIdCache().get(versionedId);
-        if (item == null && manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getRegisteredTypeNameCache().get(versionedId);
-        if (item == null) item = catalog.getRegisteredTypeNameCache().get(versionedId);
         return item;
     }
     
@@ -186,10 +183,10 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
     
     @Override
-    public CatalogItem<?,?> getCatalogItem(String idOrRegisteredTypeName, String version) {
-        if (idOrRegisteredTypeName == null) return null;
+    public CatalogItem<?,?> getCatalogItem(String symbolicName, String version) {
+        if (symbolicName == null) return null;
         checkNotNull(version, "version");
-        CatalogItemDo<?, ?> itemDo = getCatalogItemDo(idOrRegisteredTypeName, version);
+        CatalogItemDo<?, ?> itemDo = getCatalogItemDo(symbolicName, version);
         if (itemDo == null) return null;
         return itemDo.getDto();
     }
@@ -260,7 +257,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     @SuppressWarnings("unchecked")
     @Override
     public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
-        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getId(), item.getVersion());
+        CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getSymbolicName(), item.getVersion());
+        if (loadedItem == null) return null;
         Class<SpecT> specType = loadedItem.getSpecType();
         if (specType==null) return null;
 
@@ -364,7 +362,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (log.isDebugEnabled())
             log.debug("Loading class for catalog item " + item);
         checkNotNull(item);
-        CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getId(), item.getVersion());
+        CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getSymbolicName(), item.getVersion());
         if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");
         return (Class<? extends T>) loadedItem.getJavaClass();
     }
@@ -394,7 +392,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     private CatalogItemDtoAbstract<?,?> getAbstractCatalogItem(String yaml) {
         DeploymentPlan plan = makePlanFromYaml(yaml);
 
-        CatalogLibrariesDto libraries = null;
+        Collection<CatalogBundle> libraries = Collections.emptyList();
 
         @SuppressWarnings("rawtypes")
         Maybe<Map> possibleCatalog = plan.getCustomAttribute("brooklyn.catalog", Map.class, true);
@@ -408,47 +406,60 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         Maybe<Object> possibleLibraries = catalog.getMaybe("libraries");
         if (possibleLibraries.isAbsent()) possibleLibraries = catalog.getMaybe("brooklyn.libraries");
         if (possibleLibraries.isPresentAndNonNull()) {
-            if (!(possibleLibraries.get() instanceof List))
+            if (!(possibleLibraries.get() instanceof Collection))
                 throw new IllegalArgumentException("Libraries should be a list, not "+possibleLibraries.get());
-            libraries = CatalogLibrariesDto.from((List<?>) possibleLibraries.get());
+            libraries = CatalogItemDtoAbstract.parseLibraries((Collection<?>) possibleLibraries.get());
         }
 
-        // TODO clear up the abundance of id, name, registered type, java type
-        String registeredTypeName = (String) catalog.getMaybe("id").orNull();
-        if (Strings.isBlank(registeredTypeName))
-            registeredTypeName = (String) catalog.getMaybe("name").orNull();
+        String symbolicName;
+        String version = null;
+
+        symbolicName = (String) catalog.getMaybe("symbolicName").orNull();
+        if (Strings.isBlank(symbolicName)) {
+            symbolicName = (String) catalog.getMaybe("id").orNull();
+            if (Strings.isNonBlank(symbolicName) && symbolicName.indexOf(CatalogUtils.VERSION_DELIMITER) != -1) {
+                symbolicName = CatalogUtils.getIdFromVersionedId(symbolicName);
+                version = CatalogUtils.getVersionFromVersionedId(symbolicName);
+            }
+        }
+        if (Strings.isBlank(symbolicName))
+            symbolicName = (String) catalog.getMaybe("name").orNull();
         // take name from plan if not specified in brooklyn.catalog section not supplied
-        if (Strings.isBlank(registeredTypeName)) {
-            registeredTypeName = plan.getName();
-            if (Strings.isBlank(registeredTypeName)) {
+        if (Strings.isBlank(symbolicName)) {
+            symbolicName = plan.getName();
+            if (Strings.isBlank(symbolicName)) {
                 if (plan.getServices().size()==1) {
                     Service svc = Iterables.getOnlyElement(plan.getServices());
-                    registeredTypeName = svc.getServiceType();
+                    symbolicName = svc.getServiceType();
                 }
             }
         }
 
         Maybe<Object> possibleVersion = catalog.getMaybe("version");
-        String version;
-        if (possibleVersion.isAbsent()) {
+        if (possibleVersion.isAbsent() && Strings.isBlank(version)) {
             throw new IllegalArgumentException("'version' attribute missing in 'brooklyn.catalog' section.");
+        } else if (possibleVersion.isPresent()) {
+            if (Strings.isNonBlank(version)) {
+                throw new IllegalArgumentException("Can't use both attribute 'version' and versioned id");
+            }
+            //could be coalesced to a number - can be one of Integer, Double, String
+            version = possibleVersion.get().toString();
         }
 
-        //could be coalesced to a number - can be one of Integer, Double, String
-        version = possibleVersion.get().toString();
-
         CatalogUtils.installLibraries(mgmt, libraries);
 
-        AbstractBrooklynObjectSpec<?, ?> spec = createSpec(plan, CatalogUtils.newClassLoadingContext(mgmt, "<not created yet>", libraries, getRootClassLoader()));
+        AbstractBrooklynObjectSpec<?, ?> spec = createSpec(plan, CatalogUtils.newClassLoadingContext(mgmt, CatalogUtils.getVersionedId(symbolicName, version), libraries, getRootClassLoader()));
 
-        CatalogItemBuilder<?> builder = createItemBuilder(spec, registeredTypeName, version)
+        CatalogItemBuilder<?> builder = createItemBuilder(spec, symbolicName, version)
             .libraries(libraries)
             .displayName(plan.getName())
             .description(plan.getDescription())
             .plan(yaml);
 
         // and populate other fields
-        Maybe<Object> name = catalog.getMaybe("name");
+        Maybe<Object> name = catalog.getMaybe("displayName");
+        if (name.isAbsent()) name = catalog.getMaybe("name");
+        if (name.isAbsent()) name = Maybe.<Object>fromNullable(plan.getName());
         if (name.isPresent()) builder.displayName((String) name.get());
 
         Maybe<Object> description = catalog.getMaybe("description");
@@ -460,12 +471,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
         CatalogItemDtoAbstract<?, ?> dto = builder.build();
         // Overwrite generated ID
-        if (catalog.getMaybe("id").isPresent()) {
-            String id = (String) catalog.getMaybe("id").get();
-            log.info("Overwriting id {} with id from yaml: {}", dto.getId(), id);
-            FlagUtils.setFieldsFromFlags(MutableMap.of("id", id), dto);
-        }
-        // TODO: Necessary?
         dto.setManagementContext((ManagementContextInternal) mgmt);
         return dto;
     }
@@ -533,7 +538,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     private void checkItemNotExists(CatalogItem<?,?> itemDto, boolean forceUpdate) {
-        if (!forceUpdate && getCatalogItemDo(itemDto.getId(), itemDto.getVersion()) != null) {
+        if (!forceUpdate && getCatalogItemDo(itemDto.getSymbolicName(), itemDto.getVersion()) != null) {
             throw new IllegalStateException("Updating existing catalog entries is forbidden: " +
                     itemDto.getId() + ":" + itemDto.getVersion() + ". Use forceUpdate argument to override.");
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
index 6ef148e..9f65f80 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
@@ -19,6 +19,7 @@
 package brooklyn.catalog.internal;
 
 import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
 
 import brooklyn.catalog.CatalogItem.CatalogBundle;
 
@@ -30,6 +31,13 @@ public class CatalogBundleDto implements CatalogBundle {
     public CatalogBundleDto() {}
 
     public CatalogBundleDto(String name, String version, String url) {
+        if (name == null && version == null) {
+            Preconditions.checkNotNull(url, "url");
+        } else {
+            Preconditions.checkNotNull(name, "name");
+            Preconditions.checkNotNull(version, "version");
+        }
+
         this.name = name;
         this.version = version;
         this.url = url;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index 4ecca28..f6569d7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -22,7 +22,6 @@ import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Arrays;
-import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Nullable;
@@ -39,9 +38,7 @@ import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.proxying.ImplementedBy;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.policy.Policy;
-import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
 import brooklyn.util.javalang.AggregateClassLoader;
 import brooklyn.util.javalang.ReflectionScanner;
 import brooklyn.util.javalang.UrlClassLoader;
@@ -244,15 +241,13 @@ public class CatalogClasspathDo {
     @Deprecated
     public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
         Catalog annotations = c.getAnnotation(Catalog.class);
-        Map<String, Object> flags = MutableMap.<String, Object>of("id", c.getName());
-        FlagUtils.setFieldsFromFlags(flags, item);
-        item.registeredType = c.getName();
-        item.javaType = c.getName();
-        item.name = firstNonEmpty(c.getSimpleName(), c.getName());
+        item.setSymbolicName(c.getName());
+        item.setJavaType(c.getName());
+        item.setDisplayName(firstNonEmpty(c.getSimpleName(), c.getName()));
         if (annotations!=null) {
-            item.name = firstNonEmpty(annotations.name(), item.name);
-            item.description = firstNonEmpty(annotations.description());
-            item.iconUrl = firstNonEmpty(annotations.iconUrl());
+            item.setDisplayName(firstNonEmpty(annotations.name(), item.getDisplayName()));
+            item.setDescription(firstNonEmpty(annotations.description()));
+            item.setIconUrl(firstNonEmpty(annotations.iconUrl()));
         }
         if (log.isTraceEnabled())
             log.trace("adding to catalog: "+c+" (from catalog "+catalog+")");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
deleted file mode 100644
index 977fd36..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogConfigurationDto.java
+++ /dev/null
@@ -1,44 +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.catalog.internal;
-
-import brooklyn.config.ConfigKey;
-
-
-@SuppressWarnings("rawtypes")
-public class CatalogConfigurationDto extends CatalogItemDtoAbstract<ConfigKey,Void> {
-    
-    @Override
-    public CatalogItemType getCatalogItemType() {
-        return CatalogItemType.CONFIGURATION;
-    }
-
-    public Class<ConfigKey> getCatalogItemJavaType() { return ConfigKey.class; }
-
-    @Override
-    public String getRegisteredTypeName() {
-        return getJavaType();
-    }
-    
-    @Override
-    public Class<Void> getSpecType() {
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index e2249e0..0ea741d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -37,7 +37,6 @@ import brooklyn.util.net.Urls;
 import brooklyn.util.time.CountdownTimer;
 import brooklyn.util.time.Duration;
 
-import com.google.api.client.util.Maps;
 import com.google.common.base.Preconditions;
 
 public class CatalogDo {
@@ -51,8 +50,7 @@ public class CatalogDo {
     
     List<CatalogDo> childrenCatalogs = new ArrayList<CatalogDo>();
     CatalogClasspathDo classpath;
-    private Map<CatalogItemId, CatalogItemDo<?,?>> cacheById;
-    private Map<CatalogItemId, CatalogItemDo<?,?>> cacheByRegisteredTypeName;
+    private Map<String, CatalogItemDo<?,?>> cacheById;
 
     AggregateClassLoader childrenClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
     ClassLoader recursiveClassLoader;
@@ -125,7 +123,7 @@ public class CatalogDo {
         Iterable<CatalogItemDtoAbstract<?, ?>> entries = dto.getUniqueEntries();
         if (entries!=null) {
             for (CatalogItemDtoAbstract<?,?> entry : entries) {
-                CatalogUtils.installLibraries(mgmt, entry.getLibrariesDto());
+                CatalogUtils.installLibraries(mgmt, entry.getLibraries());
             }
         }
     }
@@ -159,26 +157,20 @@ public class CatalogDo {
         return childL;
     }
 
-    protected Map<CatalogItemId, CatalogItemDo<?,?>> getIdCache() {
-        Map<CatalogItemId, CatalogItemDo<?,?>> cache = this.cacheById;
-        if (cache==null) cache = buildCaches();
-        return cache;
-    }
-
-    protected Map<CatalogItemId, CatalogItemDo<?,?>> getRegisteredTypeNameCache() {
-        Map<CatalogItemId, CatalogItemDo<?,?>> cache = this.cacheByRegisteredTypeName;
+    protected Map<String, CatalogItemDo<?,?>> getIdCache() {
+        Map<String, CatalogItemDo<?,?>> cache = this.cacheById;
         if (cache==null) cache = buildCaches();
         return cache;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    protected synchronized Map<CatalogItemId, CatalogItemDo<?,?>> buildCaches() {
+    protected synchronized Map<String, CatalogItemDo<?,?>> buildCaches() {
         if (cacheById != null) return cacheById;
         CatalogUtils.logDebugOrTraceIfRebinding(log, "Building cache for {}", this);
         if (!isLoaded()) 
             log.debug("Catalog not fully loaded when loading cache of "+this);
         
-        Map<CatalogItemId, CatalogItemDo<?,?>> cache = new LinkedHashMap<CatalogItemId, CatalogItemDo<?,?>>();
+        Map<String, CatalogItemDo<?,?>> cache = new LinkedHashMap<String, CatalogItemDo<?,?>>();
         
         // build the cache; first from children catalogs, then from local entities
         // so that root and near-root takes precedence over deeper items;
@@ -196,20 +188,14 @@ public class CatalogDo {
             List<CatalogItemDtoAbstract<?,?>> entriesReversed = MutableList.copyOf(dto.getUniqueEntries());
             Collections.reverse(entriesReversed);
             for (CatalogItemDtoAbstract<?,?> entry: entriesReversed)
-                cache.put(new CatalogItemId(entry), new CatalogItemDo(this, entry));
-        }
-        Map<CatalogItemId, CatalogItemDo<?, ?>> typeNameCache = Maps.newHashMap();
-        for (CatalogItemDo<?, ?> entry : cache.values()) {
-            typeNameCache.put(new CatalogItemId(entry.getRegisteredTypeName(), entry.getVersion()), entry);
+                cache.put(entry.getId(), new CatalogItemDo(this, entry));
         }
         this.cacheById = cache;
-        this.cacheByRegisteredTypeName = typeNameCache;
         return cache;
     }
     
     protected synchronized void clearCache(boolean deep) {
         this.cacheById = null;
-        this.cacheByRegisteredTypeName = null;
         if (deep) {
             for (CatalogDo child : childrenCatalogs) {
                 child.clearCache(true);
@@ -225,11 +211,8 @@ public class CatalogDo {
     public synchronized void addEntry(CatalogItemDtoAbstract<?,?> entry) {
         dto.addEntry(entry);
         if (cacheById != null) {
-            CatalogItemId cdoId = new CatalogItemId(entry);
             CatalogItemDo<?, ?> cdo = new CatalogItemDo(this, entry);
-            cacheById.put(cdoId, cdo);
-            CatalogItemId cdoTypeId = new CatalogItemId(entry.getRegisteredTypeName(), cdo.getVersion());
-            cacheByRegisteredTypeName.put(cdoTypeId, cdo);
+            cacheById.put(entry.getId(), cdo);
         }
         if (mgmt != null) {
             mgmt.getRebindManager().getChangeListener().onManaged(entry);
@@ -242,8 +225,7 @@ public class CatalogDo {
     public synchronized void deleteEntry(CatalogItemDtoAbstract<?, ?> entry) {
         dto.removeEntry(entry);
         if (cacheById != null) {
-            cacheById.remove(new CatalogItemId(entry));
-            cacheByRegisteredTypeName.remove(new CatalogItemId(entry.getRegisteredTypeName(), entry.getVersion()));
+            cacheById.remove(entry.getId());
         }
         if (mgmt != null) {
             // TODO: Can the entry be in more than one catalogue? The management context has no notion of

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
index 8d2513b..722220b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
@@ -18,42 +18,47 @@
  */
 package brooklyn.catalog.internal;
 
+import java.util.Collection;
+import java.util.Collections;
+
+import brooklyn.catalog.CatalogItem.CatalogBundle;
+
 import com.google.common.base.Preconditions;
 
 public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
     private CatalogItemType dto;
 
-    public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String registeredTypeName, String version) {
+    public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String symbolicName, String version) {
         return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
-                .registeredTypeName(registeredTypeName)
+                .symbolicName(symbolicName)
                 .version(version);
     }
 
-    public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String registeredTypeName, String version) {
+    public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String symbolicName, String version) {
         return new CatalogItemBuilder<CatalogTemplateItemDto>(new CatalogTemplateItemDto())
-                .registeredTypeName(registeredTypeName)
+                .symbolicName(symbolicName)
                 .version(version);
     }
 
-    public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String registeredTypeName, String version) {
+    public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String symbolicName, String version) {
         return new CatalogItemBuilder<CatalogPolicyItemDto>(new CatalogPolicyItemDto())
-                .registeredTypeName(registeredTypeName)
+                .symbolicName(symbolicName)
                 .version(version);
     }
 
     public CatalogItemBuilder(CatalogItemType dto) {
         this.dto = dto;
-        this.dto.libraries = new CatalogLibrariesDto();
+        this.dto.setLibraries(Collections.<CatalogBundle>emptyList());
     }
 
-    public CatalogItemBuilder<CatalogItemType> registeredTypeName(String registeredType) {
-        dto.registeredType = registeredType;
+    public CatalogItemBuilder<CatalogItemType> symbolicName(String symbolicName) {
+        dto.setSymbolicName(symbolicName);
         return this;
     }
 
     @Deprecated
     public CatalogItemBuilder<CatalogItemType> javaType(String javaType) {
-        dto.javaType = javaType;
+        dto.setJavaType(javaType);
         return this;
     }
 
@@ -64,40 +69,41 @@ public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?
     }
 
     public CatalogItemBuilder<CatalogItemType> displayName(String displayName) {
-        dto.name = displayName;
+        dto.setDisplayName(displayName);
         return this;
     }
 
     public CatalogItemBuilder<CatalogItemType> description(String description) {
-        dto.description = description;
+        dto.setDescription(description);
         return this;
     }
 
     public CatalogItemBuilder<CatalogItemType> iconUrl(String iconUrl) {
-        dto.iconUrl = iconUrl;
+        dto.setIconUrl(iconUrl);
         return this;
     }
 
     public CatalogItemBuilder<CatalogItemType> version(String version) {
-        dto.version = version;
+        dto.setVersion(version);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> libraries(CatalogLibrariesDto libraries) {
-        dto.libraries = libraries;
+    public CatalogItemBuilder<CatalogItemType> libraries(Collection<CatalogBundle> libraries) {
+        dto.setLibraries(libraries);
         return this;
     }
 
     public CatalogItemBuilder<CatalogItemType> plan(String yaml) {
-        dto.planYaml = yaml;
+        dto.setPlanYaml(yaml);
         return this;
     }
 
     public CatalogItemType build() {
-        Preconditions.checkNotNull(dto.registeredType);
+        Preconditions.checkNotNull(dto.getSymbolicName());
+        Preconditions.checkNotNull(dto.getVersion());
 
-        if (dto.libraries == null) {
-            dto.libraries = new CatalogLibrariesDto();
+        if (dto.getLibraries() == null) {
+            dto.setLibraries(Collections.<CatalogBundle>emptyList());
         }
 
         CatalogItemType ret = dto;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index b3ac88d..0b25785 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -18,6 +18,8 @@
  */
 package brooklyn.catalog.internal;
 
+import java.util.Collection;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -65,11 +67,6 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     @Override
-    public String getRegisteredTypeName() {
-        return itemDto.getRegisteredTypeName();
-    }
-    
-    @Override
     public String getJavaType() {
         return itemDto.getJavaType();
     }
@@ -105,6 +102,11 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     public String getIconUrl() {
         return itemDto.getIconUrl();
     }
+    
+    @Override
+    public String getSymbolicName() {
+        return itemDto.getSymbolicName();
+    }
 
     @Override
     public String getVersion() {
@@ -113,7 +115,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
 
     @Nonnull  // but it is still null sometimes, see in CatalogDo.loadJavaClass
     @Override
-    public CatalogItemLibraries getLibraries() {
+    public Collection<CatalogBundle> getLibraries() {
         return itemDto.getLibraries();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 3679373..f834f15 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -18,6 +18,8 @@
  */
 package brooklyn.catalog.internal;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 
@@ -32,55 +34,55 @@ import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.rebind.BasicCatalogItemRebindSupport;
 import brooklyn.entity.rebind.RebindSupport;
 import brooklyn.mementos.CatalogItemMemento;
+import brooklyn.util.collections.MutableList;
 import brooklyn.util.flags.FlagUtils;
 import brooklyn.util.flags.SetFromFlag;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
 public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
 
-    private static final Logger log = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
-    
-    // TODO are ID and registeredType the same?
-    @SetFromFlag Set<Object> tags = Sets.newLinkedHashSet();
-    @SetFromFlag String registeredType;
-    @SetFromFlag String javaType;
-    @SetFromFlag String description;
-    @SetFromFlag String iconUrl;
-    @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
-    @SetFromFlag CatalogLibrariesDto libraries;
-    @SetFromFlag String planYaml;
-
-    // Field left named `name' to maintain the name element in existing catalogues.
-    @SetFromFlag("displayName") String name;
-
-    /** @deprecated since 0.7.0.
-     * used for backwards compatibility when deserializing.
-     * when catalogs are converted to new yaml format, this can be removed. */
-    @Deprecated
-    @SetFromFlag
-    String type;
+    private static Logger LOG = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
+
+    private @SetFromFlag String symbolicName;
+    private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
+
+    /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
+    private @Deprecated @SetFromFlag String registeredTypeName;
+
+    private @SetFromFlag String displayName;
+    /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
+    private @Deprecated @SetFromFlag String name;
+    private @SetFromFlag String description;
+    private @SetFromFlag String iconUrl;
+
+    private @SetFromFlag String javaType;
+    /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
+    private @Deprecated @SetFromFlag String type;
+    private @SetFromFlag String planYaml;
+
+    private @SetFromFlag Collection<CatalogBundle> bundles;
+    /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
+    private @Deprecated @SetFromFlag CatalogLibrariesDto libraries;
+    private @SetFromFlag Set<Object> tags = Sets.newLinkedHashSet();
 
-    // TODO: Items with neither id nor java type should be rejected at construction.
-    // XStream auto-filling fields makes this a bit awkward.
     @Override
     public String getId() {
-        return super.getId() != null ? super.getId() : getJavaType();
+        return getCatalogItemId();
     }
 
     @Override
-    public String getRegisteredTypeName() {
-        if (registeredType!=null) return registeredType;
-        return getJavaType();
+    public String getCatalogItemId() {
+        return CatalogUtils.getVersionedId(getSymbolicName(), getVersion());
     }
 
     @Override
     public String getJavaType() {
-        if (javaType!=null) return javaType;
-        if (type!=null) return type;
-        return null;
+        if (javaType != null) return javaType;
+        return type;
     }
 
     @Deprecated
@@ -90,6 +92,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     @Override
     public String getDisplayName() {
+        if (displayName != null) return displayName;
         return name;
     }
 
@@ -104,9 +107,17 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
 
     @Override
+    public String getSymbolicName() {
+        if (symbolicName != null) return symbolicName;
+        if (registeredTypeName != null) return registeredTypeName;
+        return getJavaType();
+    }
+
+    @Override
     public String getVersion() {
-        //Deserializing doesn't call the constructor
-        //so the property may be null.
+        //xstream doesn't call constructors
+        //the object is used directly (instead of a memento) when
+        //deserializing directly from catalog.xml
         if (version != null) {
             return version;
         } else {
@@ -116,12 +127,15 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     @Nonnull
     @Override
-    public CatalogItemLibraries getLibraries() {
-        return getLibrariesDto();
-    }
-
-    public CatalogLibrariesDto getLibrariesDto() {
-        return libraries;
+    @SuppressWarnings("deprecation")
+    public Collection<CatalogBundle> getLibraries() {
+        if (bundles != null) {
+            return ImmutableList.copyOf(bundles);
+        } else if (libraries != null && libraries.getBundles() != null) {
+            return ImmutableList.copyOf(libraries.getBundles());
+        } else {
+            return Collections.emptyList();
+        }
     }
 
     @Nullable @Override
@@ -131,7 +145,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     @Override
     public String toString() {
-        return getClass().getSimpleName()+"["+getId()+":"+getVersion()+"/"+getName()+"]";
+        return getClass().getSimpleName()+"["+getId()+"/"+getDisplayName()+"]";
     }
 
     public abstract Class<SpecT> getSpecType();
@@ -157,7 +171,8 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     @Override
     public void setDisplayName(String newName) {
-        this.name = newName;
+        this.displayName = newName;
+        this.name = null;
     }
 
     @Override
@@ -240,12 +255,98 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         }
     }
 
-    /** Use of this method is discouraged unless it is assigning the same (final) ID that this object already has. */
     @Override
+    @Deprecated
     public void setCatalogItemId(String id) {
-        if (id!=null && !id.equals(getRegisteredTypeName())) {
-            log.warn("Setting 'catalog-item ID' of catalog item "+getId()+"/"+getRegisteredTypeName()+" to "+id+"; if set, catalog-item ID should match the registered type name.");
+        //no op, should be used by rebind code only
+    }
+
+    protected void setSymbolicName(String symbolicName) {
+        this.symbolicName = symbolicName;
+        this.registeredTypeName = null;
+    }
+
+    protected void setVersion(String version) {
+        this.version = version;
+    }
+
+    protected void setDescription(String description) {
+        this.description = description;
+    }
+
+    protected void setIconUrl(String iconUrl) {
+        this.iconUrl = iconUrl;
+    }
+
+    protected void setJavaType(String javaType) {
+        this.javaType = javaType;
+        this.type = null;
+    }
+
+    protected void setPlanYaml(String planYaml) {
+        this.planYaml = planYaml;
+    }
+
+    protected void setLibraries(Collection<CatalogBundle> libraries) {
+        this.bundles = libraries;
+    }
+
+    protected void setTags(Set<Object> tags) {
+        this.tags = tags;
+    }
+
+    protected void setSerializer(CatalogXmlSerializer serializer) {
+        this.serializer = serializer;
+    }
+
+    /**
+     * Parses an instance of CatalogLibrariesDto from the given List. Expects the list entries
+     * to be either Strings or Maps of String -> String. Will skip items that are not.
+     */
+    public static Collection<CatalogBundle> parseLibraries(Collection<?> possibleLibraries) {
+        Collection<CatalogBundle> dto = MutableList.of();
+        for (Object object : possibleLibraries) {
+            if (object instanceof Map) {
+                Map<?, ?> entry = (Map<?, ?>) object;
+                String name = stringValOrNull(entry, "name");
+                String version = stringValOrNull(entry, "version");
+                String url = stringValOrNull(entry, "url");
+                dto.add(new CatalogBundleDto(name, version, url));
+            } else if (object instanceof String) {
+                String inlineRef = (String) object;
+
+                final String name;
+                final String version;
+                final String url;
+
+                //Infer reference type (heuristically)
+                if (inlineRef.contains("/") || inlineRef.contains("\\")) {
+                    //looks like an url/file path
+                    name = null;
+                    version = null;
+                    url = inlineRef;
+                } else if (inlineRef.indexOf(CatalogUtils.VERSION_DELIMITER) != -1) {
+                    //looks like a name+version ref
+                    name = CatalogUtils.getIdFromVersionedId(inlineRef);
+                    version = CatalogUtils.getVersionFromVersionedId(inlineRef);
+                    url = null;
+                } else {
+                    //assume it to be relative url
+                    name = null;
+                    version = null;
+                    url = inlineRef;
+                }
+
+                dto.add(new CatalogBundleDto(name, version, url));
+            } else {
+                LOG.debug("Unexpected entry in libraries list neither string nor map: " + object);
+            }
         }
-        super.setCatalogItemId(id);
+        return dto;
+    }
+
+    private static String stringValOrNull(Map<?, ?> map, String key) {
+        Object val = map.get(key);
+        return val != null ? String.valueOf(val) : null;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
deleted file mode 100644
index 47f7b62..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemId.java
+++ /dev/null
@@ -1,67 +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.catalog.internal;
-
-import brooklyn.catalog.CatalogItem;
-
-class CatalogItemId {
-    private String id;
-    private String version;
-    
-    public CatalogItemId(String id, String version) {
-        this.id = id;
-        this.version = version;
-    }
-    
-    public CatalogItemId(CatalogItem<?, ?> item) {
-        this(item.getId(), item.getVersion());
-    }
-    
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((id == null) ? 0 : id.hashCode());
-        result = prime * result
-                + ((version == null) ? 0 : version.hashCode());
-        return result;
-    }
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        CatalogItemId other = (CatalogItemId) obj;
-        if (id == null) {
-            if (other.id != null)
-                return false;
-        } else if (!id.equals(other.id))
-            return false;
-        if (version == null) {
-            if (other.version != null)
-                return false;
-        } else if (!version.equals(other.version))
-            return false;
-        return true;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
index fa5f478..1fda2d7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
@@ -25,6 +25,7 @@ import brooklyn.catalog.CatalogItem.CatalogBundle;
 
 import com.google.common.base.Preconditions;
 
+@Deprecated
 public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
 
     private final CatalogLibrariesDto librariesDto;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
index 646d69c..8403876 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
@@ -20,36 +20,18 @@ package brooklyn.catalog.internal;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogItem.CatalogBundle;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
+@Deprecated
 public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
 
-    private static Logger LOG = LoggerFactory.getLogger(CatalogLibrariesDto.class);
-
     private Collection<CatalogBundle> bundles = new CopyOnWriteArrayList<CatalogBundle>();
 
-    public void addBundle(String name, String version, String url) {
-        Preconditions.checkNotNull(bundles, "Cannot add a bundle to a deserialized DTO");
-        if (name == null && version == null) {
-            Preconditions.checkNotNull(url, "url");
-        } else {
-            Preconditions.checkNotNull(name, "name");
-            Preconditions.checkNotNull(version, "version");
-        }
-        
-        bundles.add(new CatalogBundleDto(name, version, url));
-    }
-
     /**
      * @return An immutable copy of the bundle URLs referenced by this object
      */
@@ -62,54 +44,4 @@ public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
         return ImmutableList.copyOf(bundles);
     }
 
-    /**
-     * Parses an instance of CatalogLibrariesDto from the given List. Expects the list entries
-     * to be either Strings or Maps of String -> String. Will skip items that are not.
-     */
-    public static CatalogLibrariesDto from(Collection<?> possibleLibraries) {
-        CatalogLibrariesDto dto = new CatalogLibrariesDto();
-        for (Object object : possibleLibraries) {
-            if (object instanceof Map) {
-                Map<?, ?> entry = (Map<?, ?>) object;
-                String name = stringValOrNull(entry, "name");
-                String version = stringValOrNull(entry, "version");
-                String url = stringValOrNull(entry, "url");
-                dto.addBundle(name, version, url);
-            } else if (object instanceof String) {
-                String inlineRef = (String) object;
-
-                final String name;
-                final String version;
-                final String url;
-
-                //Infer reference type (heuristically)
-                if (inlineRef.contains("/") || inlineRef.contains("\\")) {
-                    //looks like an url/file path
-                    name = null;
-                    version = null;
-                    url = inlineRef;
-                } else if (inlineRef.indexOf(CatalogUtils.VERSION_DELIMITER) != -1) {
-                    //looks like a name+version ref
-                    name = CatalogUtils.getIdFromVersionedId(inlineRef);
-                    version = CatalogUtils.getVersionFromVersionedId(inlineRef);
-                    url = null;
-                } else {
-                    //assume it to be relative url
-                    name = null;
-                    version = null;
-                    url = inlineRef;
-                }
-
-                dto.addBundle(name, version, url);
-            } else {
-                LOG.debug("Unexpected entry in libraries list neither string nor map: " + object);
-            }
-        }
-        return dto;
-    }
-
-    private static String stringValOrNull(Map<?, ?> map, String key) {
-        Object val = map.get(key);
-        return val != null ? String.valueOf(val) : null;
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index 312351f..25c8d8d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -29,7 +29,6 @@ import brooklyn.basic.BrooklynObject;
 import brooklyn.basic.BrooklynObjectInternal;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogItem.CatalogBundle;
-import brooklyn.catalog.CatalogItem.CatalogItemLibraries;
 import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import brooklyn.config.BrooklynLogging;
 import brooklyn.entity.Entity;
@@ -54,23 +53,19 @@ public class CatalogUtils {
     public static final char VERSION_DELIMITER = ':';
 
     public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, CatalogItem<?, ?> item) {
-        CatalogItemLibraries libraries = item.getLibraries();
         // TODO getLibraries() should never be null but sometimes it is still
         // e.g. run CatalogResourceTest without the above check
-        if (libraries == null) {
+        if (item.getLibraries() == null) {
             log.debug("CatalogItemDtoAbstract.getLibraries() is null.", new Exception("Trace for null CatalogItemDtoAbstract.getLibraries()"));
         }
-        return newClassLoadingContext(mgmt, item.getId(), libraries, mgmt.getCatalog().getRootClassLoader());
+        return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), mgmt.getCatalog().getRootClassLoader());
     }
 
-    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, CatalogItemLibraries libraries, ClassLoader classLoader) {
+    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> libraries, ClassLoader classLoader) {
         BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
 
-        if (libraries!=null) {
-            Collection<CatalogBundle> bundles = libraries.getBundles();
-            if (bundles!=null && !bundles.isEmpty()) {
-                result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, bundles));
-            }
+        if (libraries!=null && !libraries.isEmpty()) {
+            result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
         }
 
         BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
@@ -85,28 +80,27 @@ public class CatalogUtils {
     /**
      * Registers all bundles with the management context's OSGi framework.
      */
-    public static void installLibraries(ManagementContext managementContext, @Nullable CatalogItemLibraries libraries) {
+    public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries) {
         if (libraries == null) return;
 
         ManagementContextInternal mgmt = (ManagementContextInternal) managementContext;
-        Collection<CatalogBundle> bundles = libraries.getBundles();
-        if (!bundles.isEmpty()) {
+        if (!libraries.isEmpty()) {
             Maybe<OsgiManager> osgi = mgmt.getOsgiManager();
             if (osgi.isAbsent()) {
-                throw new IllegalStateException("Unable to load bundles "+bundles+" because OSGi is not running.");
+                throw new IllegalStateException("Unable to load bundles "+libraries+" because OSGi is not running.");
             }
             if (log.isDebugEnabled()) 
                 logDebugOrTraceIfRebinding(log, 
                     "Loading bundles in {}: {}", 
-                    new Object[] {managementContext, Joiner.on(", ").join(bundles)});
+                    new Object[] {managementContext, Joiner.on(", ").join(libraries)});
             Stopwatch timer = Stopwatch.createStarted();
-            for (CatalogBundle bundleUrl : bundles) {
+            for (CatalogBundle bundleUrl : libraries) {
                 osgi.get().registerBundle(bundleUrl);
             }
             if (log.isDebugEnabled()) 
                 logDebugOrTraceIfRebinding(log, 
                     "Registered {} bundles in {}",
-                    new Object[]{bundles.size(), Time.makeTimeStringRounded(timer)});
+                    new Object[]{libraries.size(), Time.makeTimeStringRounded(timer)});
         }
     }
 
@@ -167,4 +161,8 @@ public class CatalogUtils {
         }
     }
 
+    public static String getVersionedId(String id, String version) {
+        return id + VERSION_DELIMITER + version;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
index 0948149..8871edf 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
@@ -30,6 +30,7 @@ import brooklyn.util.xstream.XmlSerializer;
 
 public class CatalogXmlSerializer extends XmlSerializer<Object> {
 
+    @SuppressWarnings("deprecation")
     public CatalogXmlSerializer() {
         xstream.addDefaultImplementation(ArrayList.class, Collection.class);
         
@@ -49,8 +50,8 @@ public class CatalogXmlSerializer extends XmlSerializer<Object> {
         xstream.aliasType("entity", CatalogEntityItemDto.class);
         xstream.aliasType("policy", CatalogPolicyItemDto.class);
 
-        xstream.useAttributeFor(CatalogItemDtoAbstract.class, "type");
-        xstream.useAttributeFor(CatalogItemDtoAbstract.class, "name");
+        xstream.aliasAttribute(CatalogItemDtoAbstract.class, "javaType", "type");
+        xstream.aliasAttribute(CatalogItemDtoAbstract.class, "displayName", "name");
         xstream.useAttributeFor(CatalogItemDtoAbstract.class, "version");
 
         xstream.useAttributeFor(CatalogClasspathDto.class, "scan");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
index 9ddd4ca..61b9511 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
@@ -42,14 +42,13 @@ public class BasicCatalogItemRebindSupport extends AbstractBrooklynObjectRebindS
     public void reconstruct(RebindContext rebindContext, CatalogItemMemento memento) {
         super.reconstruct(rebindContext, memento);
         FlagUtils.setFieldsFromFlags(MutableMap.builder()
-                .put("id", memento.getId())
-                .put("registeredType", memento.getRegisteredTypeName())
+                .put("symbolicName", memento.getSymbolicName())
                 .put("javaType", memento.getJavaType())
                 .put("displayName", memento.getDisplayName())
                 .put("description", memento.getDescription())
                 .put("iconUrl", memento.getIconUrl())
                 .put("version", memento.getVersion())
-                .put("libraries", memento.getLibraries())
+                .put("bundles", memento.getBundles())
                 .put("planYaml", memento.getPlanYaml())
                 .build(), instance);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
index 68d1212..b32e841 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
@@ -19,6 +19,7 @@
 package brooklyn.entity.rebind.dto;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
@@ -28,6 +29,8 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Objects;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogItem.CatalogBundle;
+import brooklyn.catalog.internal.BasicBrooklynCatalog;
 import brooklyn.mementos.CatalogItemMemento;
 
 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
@@ -41,12 +44,12 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
 
     public static class Builder extends AbstractMemento.Builder<Builder> {
         protected String description;
-        protected String registeredTypeName;
+        protected String symbolicName;
         protected String iconUrl;
         protected String javaType;
         protected String version;
         protected String planYaml;
-        protected CatalogItem.CatalogItemLibraries libraries;
+        protected Collection<CatalogItem.CatalogBundle> libraries;
         protected CatalogItem.CatalogItemType catalogItemType;
         protected Class<?> catalogItemJavaType;
         protected Class<?> specType;
@@ -56,8 +59,8 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
             return self();
         }
 
-        public Builder registeredTypeName(String registeredTypeName) {
-            this.registeredTypeName = registeredTypeName;
+        public Builder symbolicName(String symbolicName) {
+            this.symbolicName = symbolicName;
             return self();
         }
 
@@ -81,7 +84,7 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
             return self();
         }
 
-        public Builder libraries(CatalogItem.CatalogItemLibraries libraries) {
+        public Builder libraries(Collection<CatalogItem.CatalogBundle> libraries) {
             this.libraries = libraries;
             return self();
         }
@@ -104,12 +107,12 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
         public Builder from(CatalogItemMemento other) {
             super.from(other);
             description = other.getDescription();
-            registeredTypeName = other.getRegisteredTypeName();
+            symbolicName = other.getSymbolicName();
             iconUrl = other.getIconUrl();
             javaType = other.getJavaType();
             version = other.getVersion();
             planYaml = other.getPlanYaml();
-            libraries = other.getLibraries();
+            libraries = other.getBundles();
             catalogItemType = other.getCatalogItemType();
             catalogItemJavaType = other.getCatalogItemJavaType();
             specType = other.getSpecType();
@@ -122,11 +125,16 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
     }
 
     private String description;
-    private String registeredTypeName;
+    private String symbolicName;
     private String iconUrl;
     private String javaType;
     private String version;
     private String planYaml;
+    //Keep libraries for deserialization compatibility and
+    //introduce bundles to hold the new libraries type from
+    //catalog item
+    private Collection<CatalogItem.CatalogBundle> bundles;
+    @SuppressWarnings("deprecation")
     private CatalogItem.CatalogItemLibraries libraries;
     private CatalogItem.CatalogItemType catalogItemType;
     private Class<?> catalogItemJavaType;
@@ -138,11 +146,12 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
     protected BasicCatalogItemMemento(Builder builder) {
         super(builder);
         this.description = builder.description;
-        this.registeredTypeName = builder.registeredTypeName;
+        this.symbolicName = builder.symbolicName;
         this.iconUrl = builder.iconUrl;
         this.version = builder.version;
         this.planYaml = builder.planYaml;
-        this.libraries = builder.libraries;
+        this.bundles = builder.libraries;
+        this.libraries = null;
         this.catalogItemJavaType = builder.catalogItemJavaType;
         this.catalogItemType = builder.catalogItemType;
         this.specType = builder.specType;
@@ -155,8 +164,8 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
     }
 
     @Override
-    public String getRegisteredTypeName() {
-        return registeredTypeName;
+    public String getSymbolicName() {
+        return symbolicName;
     }
 
     @Override
@@ -166,7 +175,11 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
 
     @Override
     public String getVersion() {
-        return version;
+        if (version != null) {
+            return version;
+        } else {
+            return BasicBrooklynCatalog.NO_VERSION;
+        }
     }
 
     @Override
@@ -180,8 +193,16 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
     }
 
     @Override
-    public CatalogItem.CatalogItemLibraries getLibraries() {
-        return libraries;
+    public Collection<CatalogItem.CatalogBundle> getBundles() {
+        if (bundles != null) {
+            return bundles;
+        } else if (libraries != null) {
+            @SuppressWarnings("deprecation")
+            Collection<CatalogBundle> b = libraries.getBundles();
+            return b;
+        } else {
+            return null;
+        }
     }
 
     @Override
@@ -216,11 +237,11 @@ public class BasicCatalogItemMemento extends AbstractMemento implements CatalogI
     protected Objects.ToStringHelper newVerboseStringHelper() {
         return super.newVerboseStringHelper()
                 .add("description", getDescription())
-                .add("registeredTypeName", getRegisteredTypeName())
+                .add("symbolicName", getSymbolicName())
                 .add("iconUrl", getIconUrl())
                 .add("version", getVersion())
                 .add("planYaml", getPlanYaml())
-                .add("libraries", getLibraries())
+                .add("bundles", getBundles())
                 .add("catalogItemJavaType", getCatalogItemJavaType())
                 .add("catalogItemType", getCatalogItemType())
                 .add("javaType", getJavaType())

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index d5a5172..94c2b59 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -362,16 +362,15 @@ public class MementosGenerators {
         BasicCatalogItemMemento.Builder builder = BasicCatalogItemMemento.builder();
         populateBrooklynObjectMementoBuilder(catalogItem, builder);
         builder.catalogItemJavaType(catalogItem.getCatalogItemJavaType())
-        .catalogItemType(catalogItem.getCatalogItemType())
-        .description(catalogItem.getDescription())
-        .iconUrl(catalogItem.getIconUrl())
-        .javaType(catalogItem.getJavaType())
-        .libraries(catalogItem.getLibraries())
-        .registeredTypeName(catalogItem.getRegisteredTypeName())
-        .specType(catalogItem.getSpecType())
-        .version(catalogItem.getVersion())
-        .planYaml(catalogItem.getPlanYaml())
-        ;
+            .catalogItemType(catalogItem.getCatalogItemType())
+            .description(catalogItem.getDescription())
+            .iconUrl(catalogItem.getIconUrl())
+            .javaType(catalogItem.getJavaType())
+            .libraries(catalogItem.getLibraries())
+            .symbolicName(catalogItem.getSymbolicName())
+            .specType(catalogItem.getSpecType())
+            .version(catalogItem.getVersion())
+            .planYaml(catalogItem.getPlanYaml());
         return builder.build();
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index 392a496..ac49879 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -47,6 +47,7 @@ import brooklyn.mementos.EntityMemento;
 import brooklyn.mementos.LocationMemento;
 import brooklyn.mementos.PolicyMemento;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.io.FileUtil;
 import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
@@ -559,23 +560,27 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
     }
 
     private File getFileFor(EntityMemento entity) {
-        return new File(entitiesDir, entity.getId());
+        return getFileFor(entitiesDir, entity.getId());
     }
     
     private File getFileFor(LocationMemento location) {
-        return new File(locationsDir, location.getId());
+        return getFileFor(locationsDir, location.getId());
     }
     
     private File getFileFor(PolicyMemento policy) {
-        return new File(policiesDir, policy.getId());
+        return getFileFor(policiesDir, policy.getId());
     }
     
     private File getFileFor(EnricherMemento enricher) {
-        return new File(enrichersDir, enricher.getId());
+        return getFileFor(enrichersDir, enricher.getId());
     }
 
     private File getFileFor(CatalogItemMemento catalogItem) {
-        return new File(catalogItemsDir, catalogItem.getId());
+        return getFileFor(catalogItemsDir, catalogItem.getId());
+    }
+
+    private File getFileFor(File parent, String id) {
+        return new File(parent, FileUtil.getSafeFileName(id));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 0ee9a73..28a2810 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Pattern;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,6 +57,7 @@ import brooklyn.mementos.Memento;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.CompoundRuntimeException;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.io.FileUtil;
 import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
@@ -657,7 +659,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
     }
     
     private String getPath(String subPath, String id) {
-        return subPath+"/"+id;
+        return subPath+"/"+FileUtil.getSafeFileName(id);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 84e3fc5..6355c12 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -154,13 +154,13 @@ public class CampYamlLiteTest {
     public void testYamlServiceForCatalog() {
         CatalogItem<?, ?> realItem = mgmt.getCatalog().addItem(Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")));
         Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog()
-                .getCatalogItems(CatalogPredicates.registeredType(Predicates.equalTo("catalog-name")));
+                .getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo("catalog-name")));
         
         Assert.assertEquals(Iterables.size(retrievedItems), 1, "Wrong retrieved items: "+retrievedItems);
         CatalogItem<Object, Object> retrievedItem = Iterables.getOnlyElement(retrievedItems);
         Assert.assertEquals(retrievedItem, realItem);
 
-        Collection<CatalogBundle> bundles = retrievedItem.getLibraries().getBundles();
+        Collection<CatalogBundle> bundles = retrievedItem.getLibraries();
         Assert.assertEquals(bundles.size(), 1);
         CatalogBundle bundle = Iterables.getOnlyElement(bundles);
         Assert.assertEquals(bundle.getUrl(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL);
@@ -175,20 +175,20 @@ public class CampYamlLiteTest {
 
     @Test
     public void testRegisterCustomEntityWithBundleWhereEntityIsFromCoreAndIconFromBundle() throws IOException {
-        String registeredTypeName = "my.catalog.app.id";
+        String symbolicName = "my.catalog.app.id";
         String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-        String yaml = getSampleMyCatalogAppYaml(registeredTypeName, bundleUrl);
+        String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl);
 
         mgmt.getCatalog().addItem(yaml);
 
-        assertMgmtHasSampleMyCatalogApp(registeredTypeName, bundleUrl);
+        assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
     }
 
     @Test
     public void testResetXmlWithCustomEntity() throws IOException {
-        String registeredTypeName = "my.catalog.app.id";
+        String symbolicName = "my.catalog.app.id";
         String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-        String yaml = getSampleMyCatalogAppYaml(registeredTypeName, bundleUrl);
+        String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl);
 
         LocalManagementContext mgmt2 = LocalManagementContextForTests.newInstanceWithOsgi();
         try {
@@ -202,12 +202,12 @@ public class CampYamlLiteTest {
             mgmt2.terminate();
         }
 
-        assertMgmtHasSampleMyCatalogApp(registeredTypeName, bundleUrl);
+        assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
     }
 
-    private String getSampleMyCatalogAppYaml(String registeredTypeName, String bundleUrl) {
+    private String getSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) {
         return "brooklyn.catalog:\n" +
-                "  id: " + registeredTypeName + "\n" +
+                "  id: " + symbolicName + "\n" +
                 "  name: My Catalog App\n" +
                 "  description: My description\n" +
                 "  icon_url: classpath:/brooklyn/osgi/tests/icon.gif\n" +
@@ -219,20 +219,18 @@ public class CampYamlLiteTest {
                 "- type: io.camp.mock:AppServer\n";
     }
 
-    private void assertMgmtHasSampleMyCatalogApp(String registeredTypeName, String bundleUrl) {
-        CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(registeredTypeName, TEST_VERSION);
-        assertNotNull(item, "failed to load item with id=" + registeredTypeName + " from catalog. Entries were: " +
+    private void assertMgmtHasSampleMyCatalogApp(String symbolicName, String bundleUrl) {
+        CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(symbolicName, TEST_VERSION);
+        assertNotNull(item, "failed to load item with id=" + symbolicName + " from catalog. Entries were: " +
                 Joiner.on(",").join(mgmt.getCatalog().getCatalogItems()));
-        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+        assertEquals(item.getSymbolicName(), symbolicName);
 
         // stored as yaml, not java
         assertNotNull(item.getPlanYaml());
         Assert.assertTrue(item.getPlanYaml().contains("io.camp.mock:AppServer"));
 
-        assertEquals(item.getId(), registeredTypeName);
-
         // and let's check we have libraries
-        Collection<CatalogBundle> libs = item.getLibraries().getBundles();
+        Collection<CatalogBundle> libs = item.getLibraries();
         assertEquals(libs.size(), 1);
         CatalogBundle bundle = Iterables.getOnlyElement(libs);
         assertEquals(bundle.getUrl(), bundleUrl);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5661ac49/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index e232116..07585b2 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -21,6 +21,8 @@ package brooklyn.catalog.internal;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import java.util.Arrays;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -28,6 +30,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import brooklyn.catalog.CatalogItem.CatalogBundle;
 import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.management.internal.LocalManagementContext;
@@ -76,7 +79,7 @@ public class CatalogDtoTest {
         CatalogDo loader = new CatalogDo(managementContext, root).load();
         
         // test app comes from jar, by default
-        CatalogItemDo<?,?> worker = loader.getRegisteredTypeNameCache().get(new CatalogItemId(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION));
+        CatalogItemDo<?,?> worker = loader.getIdCache().get(CatalogUtils.getVersionedId(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION));
         assertNotNull(worker);
         assertEquals(worker.getDisplayName(), "Test App from JAR");
         
@@ -117,9 +120,10 @@ public class CatalogDtoTest {
                 CatalogDto.newNamedInstance("Test Entities from OSGi",
                         "A catalog whose entries define their libraries as a list of OSGi bundles", "test-osgi-defined"));
         osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
-        CatalogEntityItemDto osgiEntity = CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from OSGi").build();
-        // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
-        osgiEntity.libraries.addBundle(null, null, bundleUrl);
+        CatalogEntityItemDto osgiEntity = CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from OSGi")
+                // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
+                .libraries(Arrays.<CatalogBundle>asList(new CatalogBundleDto(null, null, bundleUrl)))
+                .build();
         testEntitiesJavaCatalog.addEntry(osgiEntity);
         root.addCatalog(osgiCatalog.dto);