All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.dam.core.process.CreateThumbnailProcess Maven / Gradle / Ivy

/*
 * Copyright 1997-2008 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.dam.core.process;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.api.renditions.RenditionMaker;
import com.day.cq.dam.api.renditions.RenditionTemplate;
import com.day.cq.dam.api.thumbnail.ThumbnailConfig;
import com.day.cq.dam.commons.process.AbstractAssetWorkflowProcess;
import com.day.cq.dam.commons.thumbnail.ThumbnailConfigImpl;
import com.day.cq.dam.commons.util.DamUtil;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * The CreateThumbnailProcess is called in a Workflow process step. This process will create one or more Thumbnails for the
 * Asset to be procesed. The Thumbnail generation is delegated to the appropriate {@link com.day.cq.dam.api.handler.AssetHandler
 * AssetHandler}. The thumbails Dimensions are given as the Workflow
 * {@link com.day.cq.workflow.exec.WorkflowProcess#execute(WorkItem, WorkflowSession, MetaDataMap) Process arguments}
* Each argument is considered as one thumbnail configuration. The configuration has to be enclosed in squared brackets ([]) The * configuration consists of a number for the width, the height in pixel and an optional flag that indicates if the image should be * centered.
* These values are seperated by a colon character (:).
* Dimension:
* The thumbnail from an image will be created by resizeing according the thumbnail configuration. The ascpect ratio is respected and the * image will have at most the dimension given by the configuration.
* Centering:
* If the center flag is set to true, the thumbnail image will have exactly the size given by the configuraiton. If the resized image * is smaller it will be centered within the thumbnail. *

* Example with the following Workflow step arguments: * *

 *    [70:70],
 *    [80:100:true]
 * 
*

* The Process creates two PNG images one of the size of 70x70 pixel and one 80x100 where the result is centred */ @Component @Service @Property(name = "process.label", value = "Create Thumbnail") public class CreateThumbnailProcess extends AbstractAssetWorkflowProcess { /** * Logger instance for this class. */ private static final Logger log = LoggerFactory.getLogger(CreateThumbnailProcess.class); /** * The available arguments to this process implementation. */ public enum Arguments { PROCESS_ARGS, CONFIGS, SKIP_MIME_TYPES } /** The parsed configuration for this wf process */ public static class Config { public String[] skipMimeTypes; public ThumbnailConfig[] thumbnails; public Config() { } public Config(String[] skipMimeTypes, ThumbnailConfig[] thumbnails) { this.skipMimeTypes = skipMimeTypes; this.thumbnails = thumbnails; } } @Reference private RenditionMaker renditionMaker; public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaData) throws WorkflowException { final Asset asset = getAssetFromPayload(workItem, workflowSession.getSession()); if (asset == null) { String wfPayload = workItem.getWorkflowData().getPayload().toString(); String message = "execute: cannot create thumbnails, asset [{" + wfPayload + "}] in payload doesn't exist for workflow [{" + workItem.getId() + "}]."; throw new WorkflowException(message); } final Config config = parseConfig(metaData); createThumbnails(asset, config, renditionMaker); } public void createThumbnails(Asset asset, Config config, RenditionMaker renditionMaker) { if (handleAsset(asset, config)) { asset.setBatchMode(true); // for each thumbnail config, create a rendition template RenditionTemplate[] templates = createRenditionTemplates(asset, config.thumbnails, renditionMaker); // create thumbnail renditions renditionMaker.generateRenditions(asset, templates); } } public static RenditionTemplate[] createRenditionTemplates(Asset asset, ThumbnailConfig[] thumbnails, RenditionMaker renditionMaker) { ArrayList list = new ArrayList(); for (int i = 0; i < thumbnails.length; i++) { ThumbnailConfig thumb = thumbnails[i]; // filter thumbnails that have been updated String thName = DamUtil.getThumbnailName(thumb.getWidth(), thumb.getHeight(), thumb.doCenter() ? new String[]{"margin"} : null); if(isThumbnailStale(asset, thName)) { list.add(renditionMaker.createThumbnailTemplate(asset, thumb.getWidth(), thumb.getHeight(), thumb.doCenter())); } } return list.toArray(new RenditionTemplate[list.size()]); } /** * Check if the rendition present has been updated. If yes then return true, false if it needs to be updated */ static boolean isThumbnailStale(Asset asset, String thumb) { // 1. check against all renditions Rendition rendition = asset.getRendition(thumb); Rendition original = asset.getOriginal(); // 2. new rendition is not needed if(isNotNull(rendition, original) && rendition.getResourceMetadata().getModificationTime() > original.getResourceMetadata().getModificationTime()) { return false ; } // 3. template generates a new rendition return true; } private static boolean isNotNull(Rendition rendition, Rendition rendition2) { return (rendition != null && rendition.getResourceMetadata() != null && rendition2 != null && rendition2.getResourceMetadata() != null); } public Config parseConfig(MetaDataMap metaData) { Config cfg = new Config(); String[] args; String[] skipMimeTypeArgs; // the 'old' way, ensures backward compatibility String processArgs = metaData.get(Arguments.PROCESS_ARGS.name(), String.class); if (processArgs != null && !processArgs.equals("")) { String[] argTypes = processArgs.split(";"); if (argTypes.length > 1) { skipMimeTypeArgs = argTypes[1].split(","); args = argTypes[0].split(","); } else { skipMimeTypeArgs = null; args = processArgs.split(","); } if (skipMimeTypeArgs != null) { // must be prefixed with "skip:" List values = getValuesFromArgs("skip", skipMimeTypeArgs); cfg.skipMimeTypes = values.toArray(new String[values.size()]); } } // the 'new' way else { // String[] configs = metaData.get(Arguments.CONFIGS.name(), String[].class); skipMimeTypeArgs = metaData.get(Arguments.SKIP_MIME_TYPES.name(), String[].class); if (configs != null) { args = configs; } else { args = new String[0]; } if (skipMimeTypeArgs != null) { // can be prefixed with "skip:", but it's redundant and it's easier without List values = new ArrayList(); for (String arg : skipMimeTypeArgs) { values.add(StringUtils.removeStart(arg, "skip:")); } cfg.skipMimeTypes = values.toArray(new String[values.size()]); } } cfg.thumbnails = parseThumbnailArguments(args); return cfg; } public static ThumbnailConfig[] parseThumbnailArguments(String[] args) { List list = new ArrayList(); for (String arg : args) { ThumbnailConfig config = parseThumbnailArguments(arg); if (config != null) { list.add(config); } } return list.toArray(new ThumbnailConfig[list.size()]); } public static ThumbnailConfig parseThumbnailArguments(final String arg) { // remove any whitespace String str = arg.trim(); // if square brackets are present, just use the inside if (str.contains("[")) { str = StringUtils.substringBetween(str, "[", "]"); // if no closing bracket if (str == null) { log.warn("parseConfig: cannot parse width/height, missing closing bracket '{}'.", arg); return null; } } final String fragments[] = str.split(":"); // ensure sufficient arguments are present (at least width:height) if (fragments.length >= 2) { try { final Integer width = Integer.valueOf(fragments[0]); final Integer height = Integer.valueOf(fragments[1]); boolean doCenter = false; if (fragments.length > 2) { doCenter = Boolean.valueOf(fragments[2]); } return new ThumbnailConfigImpl(width, height, doCenter); } catch (NumberFormatException e) { log.warn("parseConfig: cannot parse, invalid width/height specified in config '{}': ", str, e); return null; } } else { log.warn("parseConfig: cannot parse, insufficient arguments in config '{}'.", str); return null; } } protected boolean handleAsset(Asset asset, Config config) { if (asset == null || config.skipMimeTypes == null) { return true; } final String mimeType = asset.getMimeType(); if (mimeType == null) { // absence of mimetype is handled at later stage in process return true; } for (String val : config.skipMimeTypes) { if (mimeType.matches(val)) { log.debug(this.getClass().getName() + " skipped for MIME type: " + mimeType); return false; } } return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy