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

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

commit b86c57e062c8a393d1ea2840a47d4e2f06e67a12
Author: Alex Heneveld <[email protected]>
AuthorDate: Fri Oct 9 10:50:32 2020 +0100

    rest api for bundle/catalog add now accepts format
    
    and includes more details for legacy compatibility
---
 .../org/apache/brooklyn/rest/api/BundleApi.java    |  52 ++++++----
 .../org/apache/brooklyn/rest/api/CatalogApi.java   | 109 ++++++++++-----------
 .../brooklyn/rest/resources/BundleResource.java    |  32 +++---
 .../brooklyn/rest/resources/CatalogResource.java   |  70 +++----------
 .../brooklyn/rest/transform/TypeTransformer.java   |  43 +++++---
 5 files changed, 143 insertions(+), 163 deletions(-)

diff --git 
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java 
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
index 2296fe3..33fa6f5 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
@@ -151,18 +151,11 @@ public interface BundleApi {
         @QueryParam("force") @DefaultValue("false")
         Boolean force);
 
+    /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} 
instead */
+    @Deprecated
     @POST
-    @Consumes({MediaType.APPLICATION_JSON, "application/x-yaml",
-        // see http://stackoverflow.com/questions/332129/yaml-mime-type
-        "text/yaml", "text/x-yaml", "application/yaml"})
-    @ApiOperation(
-            value = "Adds types to the registry from a given BOM YAML/JSON 
descriptor (creating a bundle with just this file in it)",
-            response = BundleInstallationRestResult.class
-    )
-    @ApiResponses(value = {
-            @ApiResponse(code = 400, message = "Error processing the given 
YAML"),
-            @ApiResponse(code = 201, message = "Items added successfully")
-    })
+    @Consumes("application/deprecated-yaml")
+    @ApiOperation(value = "(deprecated)", hidden = true)
     public Response createFromYaml(
             @ApiParam(name = "yaml", value = "BOM YAML declaring the types to 
be installed", required = true)
             @Valid String yaml,
@@ -170,25 +163,46 @@ public interface BundleApi {
             @QueryParam("force") @DefaultValue("false")
             Boolean forceUpdate);
 
+    /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} 
instead */
+    @Deprecated
+    @POST
+    @Consumes({"application/deprecated-zip"})
+    @ApiOperation(value = "(deprecated)", hidden = true)
+    public Response createFromArchive(
+            @ApiParam(
+                    name = "archive",
+                    value = "Bundle to install, in ZIP or JAR format, 
requiring catalog.bom containing bundle name and version",
+                    required = true)
+            byte[] archive,
+            @ApiParam(name = "force", value = "Whether to forcibly remove it, 
even if in use and/or errors", required = false, defaultValue = "false")
+            @QueryParam("force") @DefaultValue("false")
+            Boolean force);
+
+    /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} 
instead */
+    @Deprecated
     @POST
-    @Consumes({"application/x-zip", "application/x-jar"})
+    @Consumes // anything - now autodetect is done for everything unless 
'format' is specified
+    // (mime type is ignored; though it could be useful in the "score" 
function, and probably is available on the thread)
     @ApiOperation(
-            value = "Adds types to the registry from a given JAR or ZIP",
-            notes = "Accepts either an OSGi bundle JAR, or ZIP which will be 
turned into bundle JAR. Either format must "
-                    + "contain a catalog.bom at the root of the archive, which 
must contain the bundle and version key.",
+            value = "Add a bundle of types (entities, etc) to the type 
registry",
+            notes = "This will auto-detect the format, with the 
'brooklyn-bom-bundle' being common and consisting of "
+                    + "a ZIP/JAR containing a catalog.bom",
             response = BundleInstallationRestResult.class)
     @ApiResponses(value = {
             @ApiResponse(code = 400, message = "Error processing the given 
archive, or the catalog.bom is invalid"),
             @ApiResponse(code = 201, message = "Catalog items added 
successfully")
     })
-    public Response createFromArchive(
+    public Response create(
             @ApiParam(
                     name = "archive",
-                    value = "Bundle to install, in ZIP or JAR format, 
requiring catalog.bom containing bundle name and version",
+                    value = "Bundle contents to install, eg for 
brooklyn-catalog-bundle a ZIP or JAR containing a catalog.bom file",
                     required = true)
-            byte[] archive,
+                    byte[] archive,
+            @ApiParam(name = "format", value="Specify the format to indicate a 
specific resolver for handling this", required=false)
+            @QueryParam("format") @DefaultValue("")
+                    String format,
             @ApiParam(name = "force", value = "Whether to forcibly remove it, 
even if in use and/or errors", required = false, defaultValue = "false")
             @QueryParam("force") @DefaultValue("false")
-            Boolean force);
+                    Boolean force);
 
 }
diff --git 
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java 
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
index 94de80e..3d7a908 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
@@ -53,38 +53,20 @@ import io.swagger.annotations.ApiResponses;
 @Produces(MediaType.APPLICATION_JSON)
 public interface CatalogApi {
 
-    /** @deprecated since 0.11.0 use {@link #createFromYaml(String)} instead */
+    /** @deprecated since 0.11.0 use {@link #createFromYaml(String, boolean)} 
instead */
     @Deprecated
-    @Consumes("application/json-deprecated")  // prevent this from taking 
things
+    @Consumes("application/deprecated-yaml-old")  // prevent this from taking 
things
     @POST
-    @ApiOperation(
-            value = "Add a catalog items (e.g. new type of entity, policy or 
location) by uploading YAML descriptor (deprecated, use POST of yaml or ZIP/JAR 
instead)",
-            notes = "Return value is map of ID to CatalogItemSummary.",
-            response = String.class,
-            hidden = true
-    )
-    @ApiResponses(value = {
-            @ApiResponse(code = 400, message = "Error processing the given 
YAML"),
-            @ApiResponse(code = 201, message = "Catalog items added 
successfully")
-    })
+    @ApiOperation(value = "(deprecated)", hidden = true)
     public Response create(String yaml,
             @ApiParam(name="forceUpdate", value="Force update of catalog item 
(overwriting existing catalog items with same name and version)")
             @QueryParam("forceUpdate") @DefaultValue("false") boolean 
forceUpdate);
 
+    /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, 
boolean, boolean)} instead */
+    @Deprecated
     @POST
-    @Consumes({MediaType.APPLICATION_JSON, "application/x-yaml",
-        // see http://stackoverflow.com/questions/332129/yaml-mime-type
-        "text/yaml", "text/x-yaml", "application/yaml"})
-    @ApiOperation(
-            value = "Add a catalog items (e.g. new type of entity, policy or 
location) by uploading YAML descriptor.",
-            notes = "Return value is map of ID to CatalogItemSummary.",
-            response = String.class,
-            hidden = true
-    )
-    @ApiResponses(value = {
-            @ApiResponse(code = 400, message = "Error processing the given 
YAML"),
-            @ApiResponse(code = 201, message = "Catalog items added 
successfully")
-    })
+    @Consumes("application/deprecated-yaml")
+    @ApiOperation(value = "(deprecated)", hidden = true)
     public Response createFromYaml(
             @ApiParam(name = "yaml", value = "YAML descriptor of catalog 
item", required = true)
             @Valid String yaml,
@@ -92,29 +74,11 @@ public interface CatalogApi {
             @QueryParam("forceUpdate") @DefaultValue("false")
             boolean forceUpdate);
 
-    @Beta
-    /* TODO the polymorphic return type dependent on 'detail' is ugly, 
-     * but we're stuck in this API because backwards compatibility expects the 
types map
-     * whereas typical usage wants more feedback. we should introduce a 
-     * /registry and/or /types and/or /bundles endpoint that always provides 
details
-     * (and an approach to handling types more aligned with 
BrooklynTypeRegistry and OSGi bundling).
-     * Not too concerned here as this method is beta and the above switch will 
probably naturally happen soon. 
-     * The main client who cares about this is the Go CLI. */
+    /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, 
boolean, boolean)} instead */
+    @Deprecated
     @POST
-    @Consumes({"application/x-zip", "application/x-jar"})
-    @ApiOperation(
-            value = "Add a catalog items (e.g. new type of entity, policy or 
location) by uploading a ZIP/JAR archive.",
-            notes = "Accepts either an OSGi bundle JAR, or ZIP which will be 
turned into bundle JAR. Bother format must "
-                    + "contain a catalog.bom at the root of the archive, which 
must contain the bundle and version key."
-                    + "Return value is map of ID to CatalogItemSummary unless 
detail=true is passed as a parameter in which "
-                    + "case the return value is a BundleInstallationRestResult 
map containing the types map in types along "
-                    + "with a message, bundle, and code.",
-            response = String.class,
-            hidden = true)
-    @ApiResponses(value = {
-            @ApiResponse(code = 400, message = "Error processing the given 
archive, or the catalog.bom is invalid"),
-            @ApiResponse(code = 201, message = "Catalog items added 
successfully")
-    })
+    @Consumes("application/deprecated-x-zip")
+    @ApiOperation(value = "(deprecated)", hidden = true)
     public Response createFromArchive(
             @ApiParam(
                     name = "archive",
@@ -129,26 +93,53 @@ public interface CatalogApi {
             boolean forceUpdate);
 
     @Beta
+    /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, 
boolean, boolean)} instead */
+    @Deprecated
     @POST
-    @Consumes // anything (if doesn't match other methods with specific 
content types
+    @Consumes("application/deprecated-autodetect")
+    @ApiOperation(value = "(deprecated)", hidden = true)
+    public Response createFromUpload(
+            @ApiParam(
+                    name = "item",
+                    value = "Item to install, as JAR/ZIP or Catalog YAML 
(autodetected)",
+                    required = true)
+                    byte[] item,
+            @ApiParam(name="forceUpdate", value="Force update of catalog item 
(overwriting existing catalog items with same name and version)")
+            @QueryParam("forceUpdate") @DefaultValue("false")
+                    boolean forceUpdate);
+
+    // the /bundles endpoint is preferred and things (Go client and UI) should 
be switched to use it exclusively
+    @Beta
+    @POST
+    @Consumes // anything - now autodetect is done for everything unless 
'format' is specified
+    // (mime type is ignored; though it could be useful in the "score" 
function, and probably is available on the thread)
     @ApiOperation(
-            value = "Add a catalog items (e.g. new type of entity, policy or 
location) by uploading either YAML or ZIP/JAR archive (format autodetected)",
-            notes = "Specify a content-type header to skip auto-detection and 
invoke one of the more specific methods. "
-                    + "Accepts either an OSGi bundle JAR, or ZIP which will be 
turned into bundle JAR. Bother format must "
-                    + "contain a catalog.bom at the root of the archive, which 
must contain the bundle and version key."
-                    + "Return value is map of ID to CatalogItemSummary.",
-            response = String.class
-    )
+            value = "Add a bundle of types (entities, etc) to the type 
registry (catalog)",
+            notes = "This will auto-detect the format, with the 
'brooklyn-bom-bundle' being common and consisting of "
+                    + "a ZIP/JAR containing a catalog.bom. "
+                    + "Return value is map of ID to CatalogItemSummary unless 
detail=true is passed as a parameter in which "
+                    + "case the return value is a BundleInstallationRestResult 
map containing the types map in types along "
+                    + "with a message, bundle, and code.",
+            response = String.class)
     @ApiResponses(value = {
             @ApiResponse(code = 400, message = "Error processing the given 
archive, or the catalog.bom is invalid"),
             @ApiResponse(code = 201, message = "Catalog items added 
successfully")
     })
-    public Response createFromUpload(
+    public Response create(
             @ApiParam(
-                    name = "item",
-                    value = "Item to install, as JAR/ZIP or Catalog YAML 
(autodetected)",
+                    name = "bundle",
+                    value = "Bundle contents to install, eg for 
brooklyn-catalog-bundle a ZIP or JAR containing a catalog.bom file",
                     required = true)
-                    byte[] item,
+                    byte[] archive,
+            @ApiParam(name="format", value="Specify the format to indicate a 
specific resolver for handling this", required=false)
+            @QueryParam("format") @DefaultValue("")
+                    String format,
+            @ApiParam(name="detail", value="Provide a wrapping details map 
(false for backwards compatibility, but true is recommended for migration to 
bundle API)", required=false)
+            @QueryParam("detail") @DefaultValue("false")
+                    boolean detail,
+            @ApiParam(name="itemDetails", value="Include legacy item details 
in the map of types (true for backwards compatibility, but false is recommended 
for migration to bundle API)", required=false)
+            @QueryParam("itemDetails") @DefaultValue("true")
+                    boolean itemDetails,
             @ApiParam(name="forceUpdate", value="Force update of catalog item 
(overwriting existing catalog items with same name and version)")
             @QueryParam("forceUpdate") @DefaultValue("false")
                     boolean forceUpdate);
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
index 33bc162..b2dd7d8 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
@@ -32,6 +32,8 @@ import 
org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.typereg.BrooklynBomBundleCatalogBundleResolver;
+import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.rest.api.BundleApi;
@@ -167,34 +169,26 @@ public class BundleResource extends 
AbstractBrooklynRestResource implements Bund
     }
 
 
-    @Override
+    @Override @Deprecated
     public Response createFromYaml(String yaml, Boolean force) {
-        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.ADD_CATALOG_ITEM, yaml)) {
-            throw WebResourceUtils.forbidden("User '%s' is not authorized to 
add catalog items",
-                Entitlements.getEntitlementContext().user());
-        }
-        if (force==null) force = false;
-
-        try {
-            return Response.status(Status.CREATED).entity(
-                    TypeTransformer.bundleInstallationResult(
-                        
((BasicBrooklynCatalog)brooklyn().getCatalog()).addItemsBundleResult(yaml, 
force), mgmt(), brooklyn(), ui)).build();
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            return badRequest(e);
-        }
+        return create(yaml.getBytes(), 
BrooklynBomYamlCatalogBundleResolver.FORMAT, force);
     }
     
-    @Override
+    @Override @Deprecated
     public Response createFromArchive(byte[] zipInput, Boolean force) {
+        return create(zipInput, BrooklynBomBundleCatalogBundleResolver.FORMAT, 
force);
+    }
+
+    @Override @Deprecated
+    public Response create(byte[] contents, String format, Boolean force) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.ROOT, null)) {
             throw WebResourceUtils.forbidden("User '%s' is not authorized to 
add catalog items",
-                Entitlements.getEntitlementContext().user());
+                    Entitlements.getEntitlementContext().user());
         }
         if (force==null) force = false;
 
         ReferenceWithError<OsgiBundleInstallationResult> result = 
((ManagementContextInternal)mgmt()).getOsgiManager().get()
-            .install(InputStreamSource.of("REST bundle upload", zipInput), 
null, force);
+                .install(InputStreamSource.of("REST bundle upload", contents), 
format, force);
 
         if (result.hasError()) {
             // (rollback already done as part of install, if necessary)
@@ -206,7 +200,7 @@ public class BundleResource extends 
AbstractBrooklynRestResource implements Bund
                 error = error.message(result.getWithoutError().getMessage())
                         
.data(TypeTransformer.bundleInstallationResult(result.getWithoutError(), 
mgmt(), brooklyn(), ui));
             } else {
-                error.message(result.getError().getMessage());
+                
error.message(Strings.isNonBlank(result.getError().getMessage()) ? 
result.getError().getMessage() : result.getError().toString());
             }
             return error.build().asJsonResponse();
         }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 43d0c18..0afbc6f 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -24,7 +24,6 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Nullable;
@@ -34,13 +33,13 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
-import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import 
org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.rest.api.CatalogApi;
@@ -57,7 +56,6 @@ import org.apache.brooklyn.rest.transform.CatalogTransformer;
 import org.apache.brooklyn.rest.transform.TypeTransformer;
 import org.apache.brooklyn.rest.util.WebResourceUtils;
 import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -105,8 +103,7 @@ public class CatalogResource extends 
AbstractBrooklynRestResource implements Cat
 
     static Set<String> missingIcons = MutableSet.of();
 
-    @Override
-    @Beta
+    @Override @Deprecated @Beta
     public Response createFromUpload(byte[] item, boolean forceUpdate) {
         Throwable yamlException = null;
         try {
@@ -124,61 +121,48 @@ public class CatalogResource extends 
AbstractBrooklynRestResource implements Cat
         return createFromArchive(item, false, forceUpdate);
     }
     
-    @Override
-    @Deprecated
+    @Override @Deprecated
     public Response create(String yaml, boolean forceUpdate) {
         return createFromYaml(yaml, forceUpdate);
     }
     
-    @SuppressWarnings("deprecation")
-    @Override
+    @Override @Deprecated
     public Response createFromYaml(String yaml, boolean forceUpdate) {
-        if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.ADD_CATALOG_ITEM, yaml)) {
-            throw WebResourceUtils.forbidden("User '%s' is not authorized to 
add catalog item",
-                Entitlements.getEntitlementContext().user());
-        }
+        return create(yaml.getBytes(), 
BrooklynBomYamlCatalogBundleResolver.FORMAT, false, true, forceUpdate);
+    }
 
-        try {
-            final Iterable<? extends CatalogItem<?, ?>> items = 
brooklyn().getCatalog().addItems(yaml, true, forceUpdate);
-            List<RegisteredType> itemsRT = MutableList.of();
-            for (CatalogItem<?, ?> ci: items) {
-                RegisteredType rt = 
brooklyn().getTypeRegistry().get(ci.getId());
-                itemsRT.add(rt!=null ? rt : RegisteredTypes.of(ci));
-            }
-            return buildCreateResponse(itemsRT);
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            return badRequest(e);
-        }
+    @Override @Deprecated @Beta
+    public Response createFromArchive(byte[] zipInput, boolean detail, boolean 
forceUpdate) {
+        return create(zipInput, "", detail, false, forceUpdate);
     }
 
     @Override
-    @Beta
-    public Response createFromArchive(byte[] zipInput, boolean detail, boolean 
forceUpdate) {
+    public Response create(byte[] archive, String format, boolean detail, 
boolean itemDetails, boolean forceUpdate) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.ROOT, null)) {
             throw WebResourceUtils.forbidden("User '%s' is not authorized to 
add catalog item",
-                Entitlements.getEntitlementContext().user());
+                    Entitlements.getEntitlementContext().user());
         }
 
         ReferenceWithError<OsgiBundleInstallationResult> result = 
((ManagementContextInternal)mgmt()).getOsgiManager().get()
-            .install(InputStreamSource.of("REST bundle upload", zipInput), 
null, forceUpdate);
+                .install(InputStreamSource.of("REST bundle upload", archive), 
format, forceUpdate);
 
         if (result.hasError()) {
             // (rollback already done as part of install, if necessary)
             if (log.isTraceEnabled()) {
-                log.trace("Unable to create from archive, returning 400: 
"+result.getError().getMessage(), result.getError());
+                log.trace("Unable to create, format '"+format+"', returning 
400: "+result.getError().getMessage(), result.getError());
             }
             Builder error = ApiError.builder().errorCode(Status.BAD_REQUEST);
             if (result.getWithoutError()!=null) {
                 error = error.message(result.getWithoutError().getMessage())
                         
.data(TypeTransformer.bundleInstallationResult(result.getWithoutError(), 
mgmt(), brooklyn(), ui));
             } else {
-                error.message(result.getError().getMessage());
+                
error.message(Strings.isNonBlank(result.getError().getMessage()) ? 
result.getError().getMessage() : result.getError().toString());
             }
             return error.build().asJsonResponse();
         }
 
-        BundleInstallationRestResult resultR = 
TypeTransformer.bundleInstallationResult(result.get(), mgmt(), brooklyn(), ui);
+        BundleInstallationRestResult resultR = itemDetails ? 
TypeTransformer.bundleInstallationResultLegacyItemDetails(result.get(), mgmt(), 
brooklyn(), ui)
+                : TypeTransformer.bundleInstallationResult(result.get(), 
mgmt(), brooklyn(), ui);
         Status status;
         switch (result.get().getCode()) {
             case IGNORING_BUNDLE_AREADY_INSTALLED:
@@ -193,28 +177,6 @@ public class CatalogResource extends 
AbstractBrooklynRestResource implements Cat
         return Response.status(status).entity( detail ? resultR : 
resultR.getTypes() ).build();
     }
 
-    private Response buildCreateResponse(Iterable<RegisteredType> 
catalogItems) {
-        log.info("REST created catalog items: "+catalogItems);
-
-        Map<String,Object> result = MutableMap.of();
-
-        for (RegisteredType catalogItem: catalogItems) {
-            try {
-                result.put(
-                        catalogItem.getId(),
-                        CatalogTransformer.catalogItemSummary(brooklyn(), 
catalogItem, ui.getBaseUriBuilder()));
-            } catch (Throwable t) {
-                log.warn("Error loading catalog item '"+catalogItem+"' 
(rethrowing): "+t);
-                // unfortunately items are already added to the catalog and 
hard to remove,
-                // but at least let the user know;
-                // happens eg if a class refers to a missing class, like
-                // loading nosql items including mongo without the mongo bson 
class on the classpath
-                throw Exceptions.propagateAnnotated("At least one unusable 
item was added ("+catalogItem.getId()+")", t);
-            }
-        }
-        return Response.status(Status.CREATED).entity(result).build();
-    }
-
     @Override
     @Deprecated
     public void deleteApplication(String symbolicName, String version) throws 
Exception {
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
index 0efcbe8..294745f 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
@@ -74,14 +74,18 @@ public class TypeTransformer {
     private static final org.slf4j.Logger log = 
LoggerFactory.getLogger(TypeTransformer.class);
     
     public static <T extends Entity> TypeSummary 
summary(BrooklynRestResourceUtils b, RegisteredType item, UriBuilder ub) {
-        return embellish(new TypeSummary(item), item, false, b, ub);
+        return embellish(new TypeSummary(item), item, false, false, b, ub);
     }
 
     public static TypeDetail detail(BrooklynRestResourceUtils b, 
RegisteredType item, UriBuilder ub) {
-        return embellish(new TypeDetail(item), item, true, b, ub);
+        return embellish(new TypeDetail(item), item, true, false, b, ub);
     }
 
-    private static <T extends TypeSummary> T embellish(T result, 
RegisteredType item, boolean detail, BrooklynRestResourceUtils b, UriBuilder 
ub) {
+    public static TypeDetail 
detailIncludingLegacyItemFields(BrooklynRestResourceUtils b, RegisteredType 
item, UriBuilder ub) {
+        return embellish(new TypeDetail(item), item, true, true, b, ub);
+    }
+
+    private static <T extends TypeSummary> T embellish(T result, 
RegisteredType item, boolean detail, boolean legacyDetailFields, 
BrooklynRestResourceUtils b, UriBuilder ub) {
         result.setExtraField("links", makeLinks(item, ub));
         
         if (RegisteredTypes.isTemplate(item)) {
@@ -101,27 +105,32 @@ public class TypeTransformer {
             } else if (RegisteredTypes.isSubtypeOf(item, EntityAdjunct.class) 
||
                     // when implied supertypes are used we won't need the code 
below
                     RegisteredTypes.isSubtypeOf(item, Policy.class) || 
RegisteredTypes.isSubtypeOf(item, Enricher.class) || 
RegisteredTypes.isSubtypeOf(item, Feed.class)
-                    ) {
+            ) {
                 try {
                     Set<ConfigSummary> config = Sets.newLinkedHashSet();
-                    
-                    AbstractBrooklynObjectSpec<?,?> spec = 
b.getTypeRegistry().createSpec(item, null, null);
+
+                    AbstractBrooklynObjectSpec<?, ?> spec = 
b.getTypeRegistry().createSpec(item, null, null);
                     AtomicInteger priority = new AtomicInteger(0);
-                    for (final SpecParameter<?> input : spec.getParameters()){
+                    for (final SpecParameter<?> input : spec.getParameters()) {
                         
config.add(ConfigTransformer.of(input).uiIncrementAndSetPriorityIfPinned(priority).transform());
                     }
-                    
+
                     result.setExtraField("config", config);
                 } catch (Exception e) {
                     Exceptions.propagateIfFatal(e);
-                    log.trace("Unable to create spec for "+item+": "+e, e);
+                    log.trace("Unable to create spec for " + item + ": " + e, 
e);
                 }
-                
+
             } else if (RegisteredTypes.isSubtypeOf(item, Location.class)) {
                 // TODO include config on location specs?  (wasn't done 
previously so not needed, but good for completeness)
-                result.setExtraField("config", Collections.emptyMap());
+                result.setExtraField("config", Collections.emptySet());
             }
         }
+        if (legacyDetailFields) {
+            // for legacy compatibility
+            result.setExtraField("planYaml", item.getPlan()==null ? null : 
item.getPlan().getPlanData());
+            result.setExtraField("name", item.getDisplayName());
+        }
         return result;
     }
 
@@ -183,7 +192,7 @@ public class TypeTransformer {
 
     public static BundleInstallationRestResult 
bundleInstallationResult(OsgiBundleInstallationResult in, ManagementContext 
mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) {
         BundleInstallationRestResult result = new BundleInstallationRestResult(
-            in.getMessage(), in.getVersionedName() != null ? 
in.getVersionedName().toString() : "", in.getCode());
+                in.getMessage(), in.getVersionedName() != null ? 
in.getVersionedName().toString() : "", in.getCode());
         for (RegisteredType t: in.getTypesInstalled()) {
             TypeSummary summary = TypeTransformer.summary(brooklynU, t, 
ui.getBaseUriBuilder());
             result.getTypes().put(t.getId(), summary);
@@ -191,6 +200,16 @@ public class TypeTransformer {
         return result;
     }
 
+    public static BundleInstallationRestResult 
bundleInstallationResultLegacyItemDetails(OsgiBundleInstallationResult in, 
ManagementContext mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) {
+        BundleInstallationRestResult result = new BundleInstallationRestResult(
+            in.getMessage(), in.getVersionedName() != null ? 
in.getVersionedName().toString() : "", in.getCode());
+        for (RegisteredType t: in.getTypesInstalled()) {
+            TypeSummary summary = 
TypeTransformer.detailIncludingLegacyItemFields(brooklynU, t, 
ui.getBaseUriBuilder());
+            result.getTypes().put(t.getId(), summary);
+        }
+        return result;
+    }
+
     protected static Map<String, URI> makeLinks(RegisteredType item, 
UriBuilder ub) {
         return MutableMap.<String, URI>of().addIfNotNull("self", 
getSelfLink(item, ub));
     }

Reply via email to