From f8c74956707b1fb741adad070bb4f8625ca8cb6d Mon Sep 17 00:00:00 2001 From: jensp Date: Wed, 5 Sep 2018 07:01:04 +0000 Subject: [PATCH] CcmNG: REST API endpoint for assets now provides more data about images git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5686 8810af33-2d31-482b-a856-94f89814c4df --- .../librecms/contentsection/rs/Assets.java | 278 +++++++++++------- 1 file changed, 173 insertions(+), 105 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java index a6a289c0b..66c01f318 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Assets.java @@ -21,6 +21,7 @@ package org.librecms.contentsection.rs; import com.arsdigita.cms.ui.assets.AssetSearchWidget; import com.arsdigita.kernel.KernelConfig; +import org.libreccm.configuration.ConfigurationManager; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.assets.AssetTypeInfo; import org.librecms.assets.AssetTypesManager; @@ -34,16 +35,23 @@ import org.librecms.contentsection.FolderManager; import org.librecms.contentsection.FolderRepository; import org.librecms.contentsection.FolderType; -import java.util.ArrayList; -import java.util.HashMap; +import java.io.StringWriter; import java.util.List; -import java.util.Map; +import java.util.Locale; import java.util.Optional; import java.util.ResourceBundle; -import java.util.stream.Collectors; +import javax.annotation.PostConstruct; import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Any; +import javax.enterprise.inject.Instance; +import javax.enterprise.util.AnnotationLiteral; import javax.inject.Inject; +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.json.JsonWriter; import javax.transaction.Transactional; import javax.ws.rs.GET; import javax.ws.rs.NotFoundException; @@ -51,6 +59,7 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; /** * Provides a Web Service (build using JAX-RS). Used for example by the @@ -63,103 +72,48 @@ import javax.ws.rs.QueryParam; public class Assets { @Inject - private ContentSectionRepository sectionRepo; - - @Inject - private FolderRepository folderRepo; - - @Inject - private FolderManager folderManager; + private AssetManager assetManager; @Inject private AssetRepository assetRepo; @Inject - private AssetManager assetManager; + private AssetTypesManager assetTypesManager; @Inject - private AssetTypesManager assetTypesManager; + private ConfigurationManager confManager; + + @Inject + private ContentSectionRepository sectionRepo; + + @Inject + private FolderManager folderManager; + + @Inject + private FolderRepository folderRepo; @Inject private GlobalizationHelper globalizationHelper; - private Class toAssetTypeClass(final String type) { - final Class clazz; - try { - clazz = Class.forName(type); - } catch (ClassNotFoundException ex) { - throw new IllegalArgumentException(String.format( - "Type '%s' is not a valid class.", - type)); - } + @Inject + @Any + private Instance assetPropertiesProviders; - if (Asset.class.isAssignableFrom(clazz)) { - @SuppressWarnings("unchecked") - final Class typeClass - = (Class) clazz; - return typeClass; - } else { - throw new IllegalArgumentException(String.format( - "Type '%s is not a subclass of '%s'.", - type, - Asset.class.getName())); - } - } + private Locale defaultLocale; - private Map createAssetMapEntry(final Folder folder) { - final Map result = new HashMap<>(); + @PostConstruct + private void init() { - result.put("title", - folder - .getTitle() - .getValue(KernelConfig.getConfig().getDefaultLocale())); - result.put("type", - Folder.class.getName()); - result.put("place", ""); - - return result; - } - - private Map createAssetMapEntry(final Asset asset) { - final Map result = new HashMap<>(); - - result.put("assetId", - Long.toString(asset.getObjectId())); - - result.put("uuid", asset.getUuid()); - - result.put("name", asset.getDisplayName()); - - result.put("title", - globalizationHelper - .getValueFromLocalizedString(asset.getTitle())); - - result.put("type", - asset.getClass().getName()); - - final AssetTypeInfo typeInfo = assetTypesManager - .getAssetTypeInfo(asset.getClass()); - final ResourceBundle bundle = ResourceBundle - .getBundle(typeInfo.getLabelBundle(), - globalizationHelper.getNegotiatedLocale()); - result.put("typeLabel", bundle.getString(typeInfo.getLabelKey())); - - final Optional assetFolder = assetManager.getAssetFolder(asset); - if (assetFolder.isPresent()) { - result.put("place", - folderManager.getFolderPath(assetFolder.get())); - } else { - result.put("place", ""); - } - - return result; + final KernelConfig kernelConfig = confManager + .findConfiguration(KernelConfig.class); + defaultLocale = kernelConfig.getDefaultLocale(); } @GET @Path("/") - @Produces("application/json; charset=utf-8") + @Produces(MediaType.APPLICATION_JSON) @Transactional(Transactional.TxType.REQUIRED) - public List> findAssets( + public String findAssets( @PathParam("content-section") final String section, @QueryParam("query") final String query, @QueryParam("type") final String type) { @@ -190,17 +144,25 @@ public class Assets { contentSection); } - return assets + final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + + assets .stream() - .map(asset -> createAssetMapEntry(asset)) - .collect(Collectors.toList()); + .map(this::assetToJson) + .forEach(arrayBuilder::add); + + final StringWriter writer = new StringWriter(); + final JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(arrayBuilder.build()); + + return writer.toString(); } @GET @Path("/folders/") - @Produces("application/json; charset=utf-8") + @Produces(MediaType.APPLICATION_JSON) @Transactional(Transactional.TxType.REQUIRED) - public List> findAssetsInRootFolder( + public String findAssetsInRootFolder( @PathParam("content-section") final String section, @QueryParam("query") final String query, @QueryParam("type") final String type) { @@ -217,9 +179,9 @@ public class Assets { @GET @Path("/folders/{folder}/") - @Produces("application/json; charset=utf-8") + @Produces(MediaType.APPLICATION_JSON) @Transactional(Transactional.TxType.REQUIRED) - public List> findAssetsInFolder( + public String findAssetsInFolder( @PathParam("content-section") final String section, @PathParam("folder") final String folderPath, @QueryParam("query") final String query, @@ -241,15 +203,9 @@ public class Assets { return findAssetsInFolder(folder, query, type); } - private List> findAssetsInFolder(final Folder folder, - final String query, - final String type) { - - final List> subFolderEntries = folder - .getSubFolders() - .stream() - .map(subFolder -> createAssetMapEntry(subFolder)) - .collect(Collectors.toList()); + private String findAssetsInFolder(final Folder folder, + final String query, + final String type) { final List assets; if ((query == null || query.trim().isEmpty()) @@ -270,16 +226,128 @@ public class Assets { query); } - final List> assetEntries = assets + final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder(); + folder + .getSubFolders() .stream() - .map(asset -> createAssetMapEntry(asset)) - .collect(Collectors.toList()); + .map(this::assetToJson) + .forEach(arrayBuilder::add); - final List> result = new ArrayList<>(); - result.addAll(subFolderEntries); - result.addAll(assetEntries); + assets + .stream() + .map(this::assetToJson) + .forEach(arrayBuilder::add); + + final StringWriter writer = new StringWriter(); + final JsonWriter jsonWriter = Json.createWriter(writer); + jsonWriter.writeArray(arrayBuilder.build()); + + return writer.toString(); + } + + private Class toAssetTypeClass(final String type) { + final Class clazz; + try { + clazz = Class.forName(type); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException(String.format( + "Type '%s' is not a valid class.", + type)); + } + + if (Asset.class.isAssignableFrom(clazz)) { + @SuppressWarnings("unchecked") + final Class typeClass + = (Class) clazz; + return typeClass; + } else { + throw new IllegalArgumentException(String.format( + "Type '%s is not a subclass of '%s'.", + type, + Asset.class.getName())); + } + } + + private JsonObject assetToJson(final Folder folder) { + + return Json + .createObjectBuilder() + .add("title", + folder.getTitle().getValue(defaultLocale)) + .add("type", Folder.class.getName()) + .add("place", "") + .build(); + } + + private JsonObject assetToJson(final Asset asset) { + + final AssetTypeInfo typeInfo = assetTypesManager + .getAssetTypeInfo(asset.getClass()); + final ResourceBundle bundle = ResourceBundle + .getBundle(typeInfo.getLabelBundle(), + globalizationHelper.getNegotiatedLocale()); + final String place; + final Optional assetFolder = assetManager.getAssetFolder(asset); + if (assetFolder.isPresent()) { + place = folderManager.getFolderPath(assetFolder.get()); + } else { + place = ""; + } + + return Json + .createObjectBuilder() + .add("assetId", asset.getObjectId()) + .add("uuid", asset.getUuid()) + .add("name", asset.getDisplayName()) + .add("title", globalizationHelper.getValueFromLocalizedString( + asset.getTitle())) + .add("type", asset.getClass().getName()) + .add("typeLabel", bundle.getString(typeInfo.getLabelKey())) + .add("place", place) + .add("properties", getAssetProperties(asset)) + .build(); + } + + private JsonObject getAssetProperties(final Asset asset) { + + final ProvidesPropertiesForAssetTypeLiteral literal + = new ProvidesPropertiesForAssetTypeLiteral( + asset.getClass()); + + final Instance instance + = assetPropertiesProviders + .select(literal); + + final JsonObjectBuilder objBuilder = Json.createObjectBuilder(); + if (!instance.isUnsatisfied()) { + + instance + .forEach(provider -> provider.addProperties(asset, objBuilder)); + } + + return objBuilder.build(); + } + + private static class ProvidesPropertiesForAssetTypeLiteral + extends AnnotationLiteral + implements ProvidesPropertiesForAssetType { + + private static final long serialVersionUID = 1L; + + private final Class forAssetType; + + public ProvidesPropertiesForAssetTypeLiteral( + final Class forAssetType) { + + this.forAssetType = forAssetType; + } + + @Override + public Class value() { + + return forAssetType; + } - return result; } }