Merged BRANCHES/DEV/RGAUSS/HEAD-SOURCE-TARGET-TRANS-OPTIONS to HEAD:

45449: ALF-13254: TransformationOptions Should Have Separate Source and Target Options
        - Added SerializedTransformationOptionsAccessor interface which defines the methods used in the protected AbstractRenderingEngine.RenderContext class in a public manner
        - Changed AbstractRenderingEngine.RenderContext to implement SerializedTransformationOptionsAccessor
        - Added TransformationSourceOptions interface which also contains TransformationSourceOptionsSerializer interface which uses SerializedTransformationOptionsAccessor for deserialization
        - Added base AbstractTransformationSourceOptions class
        - Added PagedSourceOptions class which extends TransformationSourceOptions for start and end page options
        - Added TemporalSourceOptions class which extends TransformationSourceOptions for time-based offset and duration options
        - Changed TransformationOptions to contain TransformationSourceOptions held as a map with class as key
        - Changed ImageTransformationOptions to extend copyFrom
        - Changed ImageMagickContentTransformerWorker.getSourcePageRange to check for paged source options in the TransformationOptions passed in
        - Added ImageMagickContentTransformerTest.testPageSourceOptions to test null, default, page 2, and invalid options
        - Changed ThumbnailRenditionConvertor to iterate the transformationOptions.sourceOptionsList and use each serializer to add to the parameters
        - Changed AbstractTransformationRenderingEngine to iterate a list of TransformationSourceOptionsSerializers and use each to deserialize the RenderContext parameters and construct a TransformationSourceOptions object
        - Changed rendition-services-context.xml to set imageRenderingEngine's list of known sourceOptionsSerializers
        - Changed ThumbnailServiceImplParameterTest to test paged and temporal options
        - Added ThumbanailServiceImplTest.testCreateRenditionThumbnailFromPdfPage2 which tests grabbing the second page of a PDF


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@46062 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Ray Gauss
2013-01-30 20:32:55 +00:00
parent 259ceebf47
commit 1c928e4c9f
15 changed files with 1005 additions and 27 deletions

View File

@@ -138,6 +138,12 @@
<bean id="imageRenderingEngine" <bean id="imageRenderingEngine"
class="org.alfresco.repo.rendition.executer.ImageRenderingEngine" class="org.alfresco.repo.rendition.executer.ImageRenderingEngine"
parent="baseRenderingAction"> parent="baseRenderingAction">
<property name="sourceOptionsSerializers">
<list>
<bean class="org.alfresco.service.cmr.repository.PagedSourceOptions" factory-method="createSerializerInstance" />
<bean class="org.alfresco.service.cmr.repository.TemporalSourceOptions" factory-method="createSerializerInstance" />
</list>
</property>
</bean> </bean>
<bean id="freemarkerRenderingEngine" <bean id="freemarkerRenderingEngine"

View File

@@ -18,14 +18,23 @@
*/ */
package org.alfresco.repo.content.transform.magick; package org.alfresco.repo.content.transform.magick;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.content.transform.AbstractContentTransformerTest; import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.repo.content.transform.ProxyContentTransformer; import org.alfresco.repo.content.transform.ProxyContentTransformer;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.PagedSourceOptions;
import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.repository.TransformationSourceOptions;
import org.alfresco.util.TempFileProvider;
/** /**
* @see org.alfresco.repo.content.transform.magick.JMagickContentTransformer * @see org.alfresco.repo.content.transform.magick.JMagickContentTransformer
@@ -73,6 +82,95 @@ public class ImageMagickContentTransformerTest extends AbstractContentTransforme
assertEquals("Mimetype should be supported", true, reliability); assertEquals("Mimetype should be supported", true, reliability);
} }
protected void transform(String sourceMimetype, String targetMimetype, TransformationOptions options) throws IOException
{
String[] quickFiles = getQuickFilenames(sourceMimetype);
for (String quickFile : quickFiles)
{
String sourceExtension = quickFile.substring(quickFile.lastIndexOf('.')+1);
String targetExtension = mimetypeService.getExtension(targetMimetype);
// is there a test file for this conversion?
File sourceFile = AbstractContentTransformerTest.loadNamedQuickTestFile(quickFile);
if (sourceFile == null)
{
continue; // no test file available for that extension
}
ContentReader sourceReader = new FileContentReader(sourceFile);
// make a writer for the target file
File targetFile = TempFileProvider.createTempFile(
getClass().getSimpleName() + "_" + getName() + "_" + sourceExtension + "_",
"." + targetExtension);
ContentWriter targetWriter = new FileContentWriter(targetFile);
// do the transformation
sourceReader.setMimetype(sourceMimetype);
targetWriter.setMimetype(targetMimetype);
transformer.transform(sourceReader.getReader(), targetWriter, options);
ContentReader targetReader = targetWriter.getReader();
assertTrue(targetReader.getSize() > 0);
}
}
public void testPageSourceOptions() throws Exception
{
// Test empty source options
ImageTransformationOptions options = new ImageTransformationOptions();
this.transform(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, options);
// Test first page
options = new ImageTransformationOptions();
List<TransformationSourceOptions> sourceOptionsList = new ArrayList<TransformationSourceOptions>();
sourceOptionsList.add(PagedSourceOptions.getPage1Instance());
options.setSourceOptionsList(sourceOptionsList);
this.transform(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, options);
// Test second page
options = new ImageTransformationOptions();
sourceOptionsList = new ArrayList<TransformationSourceOptions>();
PagedSourceOptions sourceOptions = new PagedSourceOptions();
sourceOptions.setStartPageNumber(2);
sourceOptions.setEndPageNumber(2);
sourceOptionsList.add(sourceOptions);
options.setSourceOptionsList(sourceOptionsList);
this.transform(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, options);
// Test page range invalid for target type
options = new ImageTransformationOptions();
sourceOptionsList = new ArrayList<TransformationSourceOptions>();
sourceOptions = new PagedSourceOptions();
sourceOptions.setStartPageNumber(1);
sourceOptions.setEndPageNumber(2);
sourceOptionsList.add(sourceOptions);
options.setSourceOptionsList(sourceOptionsList);
try {
this.transform(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, options);
fail("An exception regarding an invalid page range should have been thrown");
}
catch (Exception e)
{
// failure expected
}
// Test page out of range
options = new ImageTransformationOptions();
sourceOptionsList = new ArrayList<TransformationSourceOptions>();
sourceOptions = new PagedSourceOptions();
sourceOptions.setStartPageNumber(3);
sourceOptions.setEndPageNumber(3);
sourceOptionsList.add(sourceOptions);
options.setSourceOptionsList(sourceOptionsList);
try {
this.transform(MimetypeMap.MIMETYPE_PDF, MimetypeMap.MIMETYPE_IMAGE_PNG, options);
fail("An exception regarding an invalid page range should have been thrown");
}
catch (Exception e)
{
// failure expected
}
}
/** /**
* Mock mimetype service which returns a limited set of mimetypes * Mock mimetype service which returns a limited set of mimetypes
* as {@link AbstractContentTransformerTest#testAllConversions()} will * as {@link AbstractContentTransformerTest#testAllConversions()} will

View File

@@ -25,6 +25,7 @@ import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.PagedSourceOptions;
import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.exec.RuntimeExec; import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult; import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
@@ -295,13 +296,13 @@ public class ImageMagickContentTransformerWorker extends AbstractImageMagickCont
} }
/** /**
* Determines whether or not page range is required for the given source and target mimetypes. * Determines whether or not a single page range is required for the given source and target mimetypes.
* *
* @param sourceMimetype * @param sourceMimetype
* @param targetMimetype * @param targetMimetype
* @return whether or not a page range must be specified for the transformer to read the target files * @return whether or not a page range must be specified for the transformer to read the target files
*/ */
private boolean isSourcePageRangeRequired(String sourceMimetype, String targetMimetype) private boolean isSingleSourcePageRangeRequired(String sourceMimetype, String targetMimetype)
{ {
// Need a page source if we're transforming from PDF or TIFF to an image other than TIFF // Need a page source if we're transforming from PDF or TIFF to an image other than TIFF
return ((sourceMimetype.equals(MimetypeMap.MIMETYPE_PDF) || return ((sourceMimetype.equals(MimetypeMap.MIMETYPE_PDF) ||
@@ -322,7 +323,43 @@ public class ImageMagickContentTransformerWorker extends AbstractImageMagickCont
*/ */
private String getSourcePageRange(TransformationOptions options, String sourceMimetype, String targetMimetype) private String getSourcePageRange(TransformationOptions options, String sourceMimetype, String targetMimetype)
{ {
if (options.getPageLimit() == 1 || isSourcePageRangeRequired(sourceMimetype, targetMimetype)) // Check for PagedContentSourceOptions in the options
if (options instanceof ImageTransformationOptions)
{
ImageTransformationOptions imageOptions = (ImageTransformationOptions) options;
PagedSourceOptions pagedSourceOptions = imageOptions.getSourceOptions(PagedSourceOptions.class);
if (pagedSourceOptions != null)
{
if (pagedSourceOptions.getStartPageNumber() != null &&
pagedSourceOptions.getEndPageNumber() != null)
{
if (pagedSourceOptions.getStartPageNumber().equals(pagedSourceOptions.getEndPageNumber()))
{
return "[" + (pagedSourceOptions.getStartPageNumber() - 1) + "]";
}
else
{
if (isSingleSourcePageRangeRequired(sourceMimetype, targetMimetype))
{
throw new AlfrescoRuntimeException(
"A single page is required for targets of type " + targetMimetype);
}
return "[" + (pagedSourceOptions.getStartPageNumber() - 1) +
"-" + (pagedSourceOptions.getEndPageNumber() - 1) + "]";
}
}
else
{
// TODO specified start to end of doc and start of doc to specified end not yet supported
// Just grab a single page specified by either start or end
if (pagedSourceOptions.getStartPageNumber() != null)
return "[" + (pagedSourceOptions.getStartPageNumber() - 1) + "]";
if (pagedSourceOptions.getEndPageNumber() != null)
return "[" + (pagedSourceOptions.getEndPageNumber() - 1) + "]";
}
}
}
if (options.getPageLimit() == 1 || isSingleSourcePageRangeRequired(sourceMimetype, targetMimetype))
{ {
return "[0]"; return "[0]";
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2010 Alfresco Software Limited. * Copyright (C) 2005-2013 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -143,4 +143,20 @@ public class ImageTransformationOptions extends TransformationOptions
{ {
this.autoOrient = autoOrient; this.autoOrient = autoOrient;
} }
@Override
public void copyFrom(TransformationOptions origOptions) {
super.copyFrom(origOptions);
if (origOptions != null)
{
if (origOptions instanceof ImageTransformationOptions)
{
// Clone ImageTransformationOptions
this.setCommandOptions(((ImageTransformationOptions) origOptions).getCommandOptions());
this.setResizeOptions(((ImageTransformationOptions) origOptions).getResizeOptions());
this.setCropOptions(((ImageTransformationOptions) origOptions).getCropOptions());
this.setAutoOrient(((ImageTransformationOptions) origOptions).isAutoOrient());
}
}
}
} }

View File

@@ -59,6 +59,7 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.SerializedTransformationOptionsAccessor;
import org.alfresco.service.namespace.NamespaceException; import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
@@ -732,7 +733,7 @@ public abstract class AbstractRenderingEngine extends ActionExecuterAbstractBase
return result; return result;
} }
protected class RenderingContext protected class RenderingContext implements SerializedTransformationOptionsAccessor
{ {
private final NodeRef sourceNode; private final NodeRef sourceNode;
private final RenditionDefinition definition; private final RenditionDefinition definition;
@@ -792,31 +793,11 @@ public abstract class AbstractRenderingEngine extends ActionExecuterAbstractBase
return this.definition; return this.definition;
} }
/**
* Gets the value for the named parameter from the . Checks the type of
* the parameter is correct and throws and Exception if it isn't.
* Returns <code>null</code> if the parameter value is <code>null</code>
*
* @param paramName the name of the parameter being checked.
* @param clazz the expected {@link Class} of the parameter value.
* @return the parameter value or <code>null</code>.
*/
public <T> T getCheckedParam(String paramName, Class<T> clazz) public <T> T getCheckedParam(String paramName, Class<T> clazz)
{ {
return AbstractRenderingEngine.getCheckedParam(paramName, clazz, definition); return AbstractRenderingEngine.getCheckedParam(paramName, clazz, definition);
} }
/**
* Gets the value for the named parameter. Checks the type of the
* parameter is the same as the type of <code>defaultValue</code> and
* throws a {@link RenditionServiceException} if it isn't. Returns
* <code>defaultValue</code> if the parameter value is <code>null</code>
*
* @param <T>
* @param paramName
* @param defaultValue
* @return
*/
public <T> T getParamWithDefault(String paramName, T defaultValue) public <T> T getParamWithDefault(String paramName, T defaultValue)
{ {
return AbstractRenderingEngine.getParamWithDefault(paramName, defaultValue, definition); return AbstractRenderingEngine.getParamWithDefault(paramName, defaultValue, definition);

View File

@@ -32,6 +32,8 @@ import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.TransformationOptionLimits; import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.repository.TransformationSourceOptions;
import org.alfresco.service.cmr.repository.TransformationSourceOptions.TransformationSourceOptionsSerializer;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -82,6 +84,18 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend
private static final String TRANSFORMER_NOT_EXISTS_MESSAGE_PATTERN = "Transformer for '%s' source mime type and '%s' target mime type was not found. Operation can't be performed"; private static final String TRANSFORMER_NOT_EXISTS_MESSAGE_PATTERN = "Transformer for '%s' source mime type and '%s' target mime type was not found. Operation can't be performed";
private static final String NOT_TRANSFORMABLE_MESSAGE_PATTERN = "Content not transformable for '%s' source mime type and '%s' target mime type. Operation can't be performed"; private static final String NOT_TRANSFORMABLE_MESSAGE_PATTERN = "Content not transformable for '%s' source mime type and '%s' target mime type. Operation can't be performed";
private static final String TRANSFORMING_ERROR_MESSAGE = "Some error occurred during document transforming. Error message: "; private static final String TRANSFORMING_ERROR_MESSAGE = "Some error occurred during document transforming. Error message: ";
private Collection<TransformationSourceOptionsSerializer> sourceOptionsSerializers;
public Collection<TransformationSourceOptionsSerializer> getSourceOptionsSerializers()
{
return sourceOptionsSerializers;
}
public void setSourceOptionsSerializers(Collection<TransformationSourceOptionsSerializer> sourceOptionsSerializers)
{
this.sourceOptionsSerializers = sourceOptionsSerializers;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
@@ -184,6 +198,18 @@ public abstract class AbstractTransformationRenderingEngine extends AbstractRend
{ {
options.setPageLimit(pageLimit); options.setPageLimit(pageLimit);
} }
if (getSourceOptionsSerializers() != null)
{
for (TransformationSourceOptionsSerializer sourceSerializer : getSourceOptionsSerializers())
{
TransformationSourceOptions sourceOptions = sourceSerializer.deserialize(context);
if (sourceOptions != null)
{
options.addSourceOptions(sourceOptions);
}
}
}
return options; return options;
} }

View File

@@ -33,6 +33,7 @@ import org.alfresco.repo.rendition.executer.ReformatRenderingEngine;
import org.alfresco.service.cmr.rendition.RenditionDefinition; import org.alfresco.service.cmr.rendition.RenditionDefinition;
import org.alfresco.service.cmr.rendition.RenditionService; import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.repository.TransformationSourceOptions;
import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails; import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails;
import org.alfresco.service.cmr.thumbnail.ThumbnailService; import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
@@ -185,6 +186,14 @@ public class ThumbnailRenditionConvertor
parameters.put(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT, allowEnlargement); parameters.put(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT, allowEnlargement);
} }
} }
if (transformationOptions.getSourceOptionsList() != null)
{
for (TransformationSourceOptions sourceOptions : transformationOptions.getSourceOptionsList())
{
sourceOptions.getSerializer().serialize(sourceOptions, parameters);
}
}
// TODO Handle RuntimeExecutableTransformationOptions // TODO Handle RuntimeExecutableTransformationOptions
return parameters; return parameters;
} }

View File

@@ -45,6 +45,10 @@ import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.PagedSourceOptions;
import org.alfresco.service.cmr.repository.PagedSourceOptions.PagedSourceOptionsSerializer;
import org.alfresco.service.cmr.repository.TemporalSourceOptions;
import org.alfresco.service.cmr.repository.TemporalSourceOptions.TemporalSourceOptionsSerializer;
import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails; import org.alfresco.service.cmr.thumbnail.ThumbnailParentAssociationDetails;
import org.alfresco.service.cmr.thumbnail.ThumbnailService; import org.alfresco.service.cmr.thumbnail.ThumbnailService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
@@ -135,6 +139,9 @@ public class ThumbnailServiceImplParameterTest
parametersUnderTest.put(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT, Boolean.TRUE); parametersUnderTest.put(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT, Boolean.TRUE);
parametersUnderTest.put(AbstractRenderingEngine.PARAM_TARGET_CONTENT_PROPERTY, ContentModel.PROP_CONTENT); parametersUnderTest.put(AbstractRenderingEngine.PARAM_TARGET_CONTENT_PROPERTY, ContentModel.PROP_CONTENT);
parametersUnderTest.put(RenditionService.PARAM_DESTINATION_NODE, dummyNodeRef2); parametersUnderTest.put(RenditionService.PARAM_DESTINATION_NODE, dummyNodeRef2);
parametersUnderTest.put(PagedSourceOptionsSerializer.PARAM_SOURCE_START_PAGE, new Integer(2));
parametersUnderTest.put(PagedSourceOptionsSerializer.PARAM_SOURCE_END_PAGE, new Integer(2));
parametersUnderTest.put(TemporalSourceOptionsSerializer.PARAM_SOURCE_TIME_OFFSET, "00:00:00.5");
ImageTransformationOptions imageTransOpts = new ImageTransformationOptions(); ImageTransformationOptions imageTransOpts = new ImageTransformationOptions();
@@ -151,6 +158,15 @@ public class ThumbnailServiceImplParameterTest
resizeOptions.setAllowEnlargement((Boolean) parametersUnderTest.get(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT)); resizeOptions.setAllowEnlargement((Boolean) parametersUnderTest.get(ImageRenderingEngine.PARAM_ALLOW_ENLARGEMENT));
imageTransOpts.setResizeOptions(resizeOptions); imageTransOpts.setResizeOptions(resizeOptions);
PagedSourceOptions pagedSourceOptions = new PagedSourceOptions();
pagedSourceOptions.setStartPageNumber((Integer) parametersUnderTest.get(PagedSourceOptionsSerializer.PARAM_SOURCE_START_PAGE));
pagedSourceOptions.setEndPageNumber((Integer) parametersUnderTest.get(PagedSourceOptionsSerializer.PARAM_SOURCE_END_PAGE));
imageTransOpts.addSourceOptions(pagedSourceOptions);
TemporalSourceOptions temporalSourceOptions = new TemporalSourceOptions();
temporalSourceOptions.setOffset((String) parametersUnderTest.get(TemporalSourceOptionsSerializer.PARAM_SOURCE_TIME_OFFSET));
imageTransOpts.addSourceOptions(temporalSourceOptions);
ThumbnailParentAssociationDetails assocDetails = new ThumbnailParentAssociationDetails(dummyNodeRef3, ThumbnailParentAssociationDetails assocDetails = new ThumbnailParentAssociationDetails(dummyNodeRef3,
ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
"homerSimpson")); "homerSimpson"));

View File

@@ -49,6 +49,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentServiceTransientException; import org.alfresco.service.cmr.repository.ContentServiceTransientException;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.PagedSourceOptions;
import org.alfresco.service.cmr.repository.ScriptLocation; import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService; import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.service.cmr.repository.TransformationOptions;
@@ -175,6 +176,39 @@ public class ThumbnailServiceImplTest extends BaseAlfrescoSpringTest
checkRendition("doclib", thumbnail0); checkRendition("doclib", thumbnail0);
outputThumbnailTempContentLocation(thumbnail0, "jpg", "doclib test"); outputThumbnailTempContentLocation(thumbnail0, "jpg", "doclib test");
} }
public void testCreateRenditionThumbnailFromPdfPage2() throws Exception
{
ImageTransformationOptions options = new ImageTransformationOptions();
PagedSourceOptions pagedSourceOptions = new PagedSourceOptions();
pagedSourceOptions.setStartPageNumber(new Integer(2));
pagedSourceOptions.setEndPageNumber(new Integer(2));
options.addSourceOptions(pagedSourceOptions);
ThumbnailDefinition thumbnailDefinition = new ThumbnailDefinition(MimetypeMap.MIMETYPE_PDF, options, "doclib_2");
thumbnailService.getThumbnailRegistry().addThumbnailDefinition(thumbnailDefinition);
checkTransformer();
NodeRef pdfOrig = createOriginalContent(this.folder, MimetypeMap.MIMETYPE_PDF);
NodeRef thumbnail0 = this.thumbnailService.createThumbnail(pdfOrig, ContentModel.PROP_CONTENT,
MimetypeMap.MIMETYPE_IMAGE_JPEG, thumbnailDefinition.getTransformationOptions(), "doclib_2");
assertNotNull(thumbnail0);
checkRenditioned(pdfOrig, "doclib_2");
checkRendition("doclib_2", thumbnail0);
// Check the length
File tempFile = TempFileProvider.createTempFile("thumbnailServiceImplTest", ".jpg");
ContentReader reader = this.contentService.getReader(thumbnail0, ContentModel.PROP_CONTENT);
long size = reader.getSize();
System.out.println("size=" + size);
assertTrue("Page 2 should be blank and less than 4500 bytes", size < 4500);
reader.getContent(tempFile);
System.out.println("doclib_2 test: " + tempFile.getPath());
}
public void testCreateThumbnailFromImage() throws Exception public void testCreateThumbnailFromImage() throws Exception
{ {

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* Base implementation of TransformationSourceOptions which holds applicable mimetypes
* and handles merge of options.
*
* @author Ray Gauss II
*/
public abstract class AbstractTransformationSourceOptions implements TransformationSourceOptions, Cloneable
{
protected static final String MIMETYPE_VIDEO_PREFIX = "video/";
protected static final String MIMETYPE_AUDIO_PREFIX = "audio/";
/** The list of applicable mimetypes */
private List<String> applicabledMimetypes;
/**
* Gets the list of applicable mimetypes
*
* @return the applicable mimetypes
*/
public List<String> getApplicabledMimetypes()
{
return applicabledMimetypes;
}
/**
* Sets the list of applicable mimetypes
*
* @param applicableMimetypes the applicable mimetypes
*/
public void setApplicableMimetypes(List<String> applicabledMimetypes)
{
this.applicabledMimetypes = applicabledMimetypes;
}
/**
* Gets whether or not these transformation source options apply for the
* given mimetype
*
* @param mimetype the mimetype of the source
* @return if these transformation source options apply
*/
public boolean isApplicableForMimetype(String mimetype)
{
if (mimetype != null && applicabledMimetypes != null) { return applicabledMimetypes.contains(mimetype); }
return false;
}
@Override
protected AbstractTransformationSourceOptions clone() throws CloneNotSupportedException
{
return (AbstractTransformationSourceOptions) super.clone();
}
/**
* Creates a new <code>TransformationSourceOptions</code> object from this
* one, merging any non-null overriding fields in the given
* <code>overridingOptions</code>
*
* @param overridingOptions
* @return a merged <code>TransformationSourceOptions</code> object
*/
public TransformationSourceOptions mergedOptions(TransformationSourceOptions overridingOptions)
{
try
{
AbstractTransformationSourceOptions mergedOptions = this.clone();
mergedOptions.setApplicableMimetypes(this.getApplicabledMimetypes());
return mergedOptions;
}
catch (CloneNotSupportedException e)
{
// Not thrown
}
return null;
}
/**
* Adds the given paramValue to the given params if it's not null.
*
* @param paramName
* @param paramValue
* @param params
*/
protected void putParameterIfNotNull(String paramName, Serializable paramValue, Map<String, Serializable> params)
{
if (paramValue != null)
{
params.put(paramName, paramValue);
}
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.AbstractTransformationSourceOptions;
/**
* Paged content conversion options to specify a page number range.
* <p>
* The page numbering index starts with 1.
* <p>
* If only the start page number is specified transformers should attempt
* a page range from that page number to the end if possible.
* <p>
* If only an end page number is specified transformers should attempt
* a page range from the start to that page if possible.
*
* @author Ray Gauss II
*/
public class PagedSourceOptions extends AbstractTransformationSourceOptions
{
public static final Integer PAGE_1 = new Integer(1);
/** The start of the page range in the source document */
private Integer startPageNumber;
/** The end of the page range in the source document */
private Integer endPageNumber;
protected static List<String> getDefaultApplicableMimetypes()
{
List<String> defaults = new ArrayList<String>(17);
defaults.add(MimetypeMap.MIMETYPE_PDF);
defaults.add(MimetypeMap.MIMETYPE_WORD);
defaults.add(MimetypeMap.MIMETYPE_PPT);
defaults.add(MimetypeMap.MIMETYPE_IMAGE_TIFF);
defaults.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION);
defaults.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE);
defaults.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE);
defaults.add(MimetypeMap.MIMETYPE_OPENOFFICE1_WRITER);
defaults.add(MimetypeMap.MIMETYPE_OPENOFFICE1_IMPRESS);
defaults.add(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION);
defaults.add(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING);
defaults.add(MimetypeMap.MIMETYPE_STAROFFICE5_IMPRESS);
defaults.add(MimetypeMap.MIMETYPE_STAROFFICE5_IMPRESS_PACKED);
defaults.add(MimetypeMap.MIMETYPE_STAROFFICE5_WRITER);
defaults.add(MimetypeMap.MIMETYPE_STAROFFICE5_WRITER_GLOBAL);
defaults.add(MimetypeMap.MIMETYPE_IWORK_KEYNOTE);
defaults.add(MimetypeMap.MIMETYPE_IWORK_PAGES);
defaults.add(MimetypeMap.MIMETYPE_WORDPERFECT);
return defaults;
}
public PagedSourceOptions()
{
super();
setApplicableMimetypes(PagedSourceOptions.getDefaultApplicableMimetypes());
}
/**
* Gets the page number to start from in the source document
*
* @return the start page number
*/
public Integer getStartPageNumber()
{
return startPageNumber;
}
/**
* Sets the page number to start from in the source document
*
* @param startPageNumber the start page number
*/
public void setStartPageNumber(Integer startPageNumber)
{
this.startPageNumber = startPageNumber;
}
/**
* Gets the page number to end at in the source document
*
* @return the start page number
*/
public Integer getEndPageNumber()
{
return endPageNumber;
}
/**
* Sets the page number to end at in the source document
*
* @param endPageNumber the end page number
*/
public void setEndPageNumber(Integer endPageNumber)
{
this.endPageNumber = endPageNumber;
}
@Override
public TransformationSourceOptions mergedOptions(TransformationSourceOptions overridingOptions)
{
if (overridingOptions instanceof PagedSourceOptions)
{
PagedSourceOptions mergedOptions = (PagedSourceOptions) super.mergedOptions(overridingOptions);
if (((PagedSourceOptions) overridingOptions).getStartPageNumber() != null)
{
mergedOptions.setStartPageNumber(((PagedSourceOptions) overridingOptions).getStartPageNumber());
}
if (((PagedSourceOptions) overridingOptions).getEndPageNumber() != null)
{
mergedOptions.setEndPageNumber(((PagedSourceOptions) overridingOptions).getEndPageNumber());
}
return mergedOptions;
}
return null;
}
/**
* Gets paged source options which specify just the first page.
*
* @return the page one source options
*/
public static PagedSourceOptions getPage1Instance() {
PagedSourceOptions sourceOptions = new PagedSourceOptions();
sourceOptions.setStartPageNumber(PAGE_1);
sourceOptions.setEndPageNumber(PAGE_1);
return sourceOptions;
}
@Override
public TransformationSourceOptionsSerializer getSerializer()
{
return PagedSourceOptions.createSerializerInstance();
}
/**
* Creates an instance of the options serializer
*
* @return the options serializer
*/
public static TransformationSourceOptionsSerializer createSerializerInstance()
{
return (new PagedSourceOptions()).new PagedSourceOptionsSerializer();
}
/**
* Serializer for paged source options
*/
public class PagedSourceOptionsSerializer implements TransformationSourceOptionsSerializer
{
public static final String PARAM_SOURCE_START_PAGE = "source_start_page";
public static final String PARAM_SOURCE_END_PAGE = "source_end_page";
@Override
public TransformationSourceOptions deserialize(SerializedTransformationOptionsAccessor serializedOptions)
{
int startPageNumber = serializedOptions.getIntegerParam(PARAM_SOURCE_START_PAGE, 1);
int endPageNumber = serializedOptions.getIntegerParam(PARAM_SOURCE_END_PAGE, 1);
PagedSourceOptions sourceOptions = new PagedSourceOptions();
sourceOptions.setStartPageNumber(startPageNumber);
sourceOptions.setEndPageNumber(endPageNumber);
return sourceOptions;
}
@Override
public void serialize(TransformationSourceOptions sourceOptions,
Map<String, Serializable> parameters)
{
if (parameters == null || sourceOptions == null)
{
return;
}
PagedSourceOptions pagedSourceOptions = (PagedSourceOptions) sourceOptions;
parameters.put(PARAM_SOURCE_START_PAGE, pagedSourceOptions.getStartPageNumber());
parameters.put(PARAM_SOURCE_END_PAGE, pagedSourceOptions.getEndPageNumber());
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.repository;
import org.alfresco.service.cmr.rendition.RenditionServiceException;
/**
* Defines methods for retrieving parameter values for use in building
* transformation options.
*
* @author Ray Gauss II
*/
public interface SerializedTransformationOptionsAccessor
{
/**
* Gets the value for the named parameter. Checks the type of
* the parameter is correct and throws and Exception if it isn't.
* Returns <code>null</code> if the parameter value is <code>null</code>
*
* @param paramName the name of the parameter being checked.
* @param clazz the expected {@link Class} of the parameter value.
* @return the parameter value or <code>null</code>.
*/
public <T> T getCheckedParam(String paramName, Class<T> clazz);
/**
* Gets the value for the named parameter. Checks the type of the
* parameter is the same as the type of <code>defaultValue</code> and
* throws a {@link RenditionServiceException} if it isn't. Returns
* <code>defaultValue</code> if the parameter value is <code>null</code>
*
* @param <T>
* @param paramName
* @param defaultValue
* @return
*/
public <T> T getParamWithDefault(String paramName, T defaultValue);
/**
* Gets the int value for the named parameter. Returns
* <code>defaultValue</code> if the parameter value is <code>null</code>.
*
* @param key
* @param defaultValue
* @return
*/
public int getIntegerParam(String key, int defaultValue);
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.service.cmr.repository.AbstractTransformationSourceOptions;
/**
* Time-based content conversion options to specify an offset and duration.
* Useful for audio and video.
* <p>
* If only the offset is specified transformers should attempt
* a transform from that offset to the end if possible.
* <p>
* If only a duration is specified transformers should attempt
* a transform from the start until that duration is reached if possible.
*
* @author Ray Gauss II
*/
public class TemporalSourceOptions extends AbstractTransformationSourceOptions
{
/** The offset time code from which to start the transformation */
private String offset;
/** The duration of the target video after the transformation */
private String duration;
public boolean isApplicableForMimetype(String sourceMimetype)
{
return ((sourceMimetype != null &&
sourceMimetype.startsWith(MIMETYPE_VIDEO_PREFIX) ||
sourceMimetype.startsWith(MIMETYPE_AUDIO_PREFIX)) ||
super.isApplicableForMimetype(sourceMimetype));
}
/**
* Gets the offset time code from which to start the transformation
* with a format of hh:mm:ss[.xxx]
*
* @return the offset
*/
public String getOffset()
{
return offset;
}
/**
* Sets the offset time code from which to start the transformation
* with a format of hh:mm:ss[.xxx]
*
* @param offset
*/
public void setOffset(String offset)
{
this.offset = offset;
}
/**
* Gets the duration of the source to read
* with a format of hh:mm:ss[.xxx]
*
* @return
*/
public String getDuration()
{
return duration;
}
/**
* Sets the duration of the source to read
* with a format of hh:mm:ss[.xxx]
*
* @param duration
*/
public void setDuration(String duration)
{
this.duration = duration;
}
@Override
public TransformationSourceOptions mergedOptions(TransformationSourceOptions overridingOptions)
{
if (overridingOptions instanceof TemporalSourceOptions)
{
TemporalSourceOptions mergedOptions = (TemporalSourceOptions) super.mergedOptions(overridingOptions);
if (((TemporalSourceOptions) overridingOptions).getOffset() != null)
{
mergedOptions.setOffset(((TemporalSourceOptions) overridingOptions).getOffset());
}
if (((TemporalSourceOptions) overridingOptions).getDuration() != null)
{
mergedOptions.setDuration(((TemporalSourceOptions) overridingOptions).getDuration());
}
return mergedOptions;
}
return null;
}
@Override
public TransformationSourceOptionsSerializer getSerializer()
{
return TemporalSourceOptions.createSerializerInstance();
}
/**
* Creates an instance of the options serializer
*
* @return the options serializer
*/
public static TransformationSourceOptionsSerializer createSerializerInstance()
{
return (new TemporalSourceOptions()).new TemporalSourceOptionsSerializer();
}
/**
* Serializer for temporal source options
*/
public class TemporalSourceOptionsSerializer implements TransformationSourceOptionsSerializer
{
public static final String PARAM_SOURCE_TIME_OFFSET = "source_time_offset";
public static final String PARAM_SOURCE_TIME_DURATION = "source_time_duration";
@Override
public TransformationSourceOptions deserialize(SerializedTransformationOptionsAccessor serializedOptions)
{
String offset = serializedOptions.getCheckedParam(PARAM_SOURCE_TIME_OFFSET, String.class);
String duration = serializedOptions.getCheckedParam(PARAM_SOURCE_TIME_DURATION, String.class);
if (offset == null && duration == null)
{
return null;
}
TemporalSourceOptions sourceOptions = new TemporalSourceOptions();
sourceOptions.setOffset(offset);
sourceOptions.setDuration(duration);
return sourceOptions;
}
@Override
public void serialize(TransformationSourceOptions sourceOptions,
Map<String, Serializable> parameters)
{
if (parameters == null || sourceOptions == null)
return;
TemporalSourceOptions temporalSourceOptions = (TemporalSourceOptions) sourceOptions;
parameters.put(PARAM_SOURCE_TIME_OFFSET, temporalSourceOptions.getOffset());
parameters.put(PARAM_SOURCE_TIME_DURATION, temporalSourceOptions.getDuration());
}
}
}

View File

@@ -18,11 +18,16 @@
*/ */
package org.alfresco.service.cmr.repository; package org.alfresco.service.cmr.repository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.service.cmr.repository.datatype.TypeConverter; import org.alfresco.service.cmr.repository.datatype.TypeConverter;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** /**
* Class containing values of options that are passed to content transformers. These options * Class containing values of options that are passed to content transformers. These options
@@ -37,6 +42,8 @@ import org.alfresco.service.namespace.QName;
*/ */
public class TransformationOptions implements Cloneable public class TransformationOptions implements Cloneable
{ {
private static final Log logger = LogFactory.getLog(TransformationOptions.class);
/** Option map names to preserve backward compatibility */ /** Option map names to preserve backward compatibility */
public static final String OPT_SOURCE_NODEREF = "contentReaderNodeRef"; public static final String OPT_SOURCE_NODEREF = "contentReaderNodeRef";
public static final String OPT_SOURCE_CONTENT_PROPERTY = "sourceContentProperty"; public static final String OPT_SOURCE_CONTENT_PROPERTY = "sourceContentProperty";
@@ -61,6 +68,9 @@ public class TransformationOptions implements Cloneable
/** Time, KBytes and page limits */ /** Time, KBytes and page limits */
private TransformationOptionLimits limits = new TransformationOptionLimits(); private TransformationOptionLimits limits = new TransformationOptionLimits();
/** Source options based on its mimetype */
private Map<Class<? extends TransformationSourceOptions>, TransformationSourceOptions> sourceOptionsMap;
/** /**
* Default constructor * Default constructor
@@ -124,6 +134,7 @@ public class TransformationOptions implements Cloneable
public void copyFrom(TransformationOptions otherOptions) public void copyFrom(TransformationOptions otherOptions)
{ {
this.set(otherOptions.toMap()); this.set(otherOptions.toMap());
this.setSourceOptionsList(otherOptions.getSourceOptionsList());
} }
/** /**
@@ -419,7 +430,87 @@ public class TransformationOptions implements Cloneable
{ {
this.limits = limits; this.limits = limits;
} }
/**
* Gets the map of source options further describing how the source should
* be transformed based on its mimetype
*
* @return the source mimetype to source options map
*/
protected Map<Class<? extends TransformationSourceOptions>, TransformationSourceOptions> getSourceOptionsMap()
{
return sourceOptionsMap;
}
/**
* Gets the immutable list of source options further describing how the source should
* be transformed based on its mimetype.
* Use {@link TransformationOptions#addSourceOptions(TransformationSourceOptions)}
* to add source options.
*
* @return the source options list
*/
public Collection<TransformationSourceOptions> getSourceOptionsList()
{
if (sourceOptionsMap == null)
return null;
return sourceOptionsMap.values();
}
/**
* Sets the list of source options further describing how the source should
* be transformed based on its mimetype.
*
* @param sourceOptionsList the source options list
*/
public void setSourceOptionsList(Collection<TransformationSourceOptions> sourceOptionsList)
{
if (sourceOptionsList != null)
{
for (TransformationSourceOptions sourceOptions : sourceOptionsList)
{
addSourceOptions(sourceOptions);
}
}
}
/**
* Adds the given sourceOptions to the sourceOptionsMap.
* <p>
* Note that if source options of the same class already exists a new
* merged source options object is added.
*
* @param sourceOptions
*/
public void addSourceOptions(TransformationSourceOptions sourceOptions)
{
if (sourceOptionsMap == null)
{
sourceOptionsMap = new HashMap<Class<? extends TransformationSourceOptions>, TransformationSourceOptions>(1);
}
TransformationSourceOptions newOptions = sourceOptions;
TransformationSourceOptions existingOptions = sourceOptionsMap.get(sourceOptions.getClass());
if (existingOptions != null)
{
newOptions = existingOptions.mergedOptions(sourceOptions);
}
sourceOptionsMap.put(sourceOptions.getClass(), newOptions);
}
/**
* Gets the appropriate source options for the given mimetype if available.
*
* @param sourceMimetype
* @return the source options for the mimetype
*/
@SuppressWarnings("unchecked")
public <T extends TransformationSourceOptions> T getSourceOptions(Class<T> clazz)
{
if (sourceOptionsMap == null)
return null;
return (T) sourceOptionsMap.get(clazz);
}
/** /**
* Convert the transformation options into a map. * Convert the transformation options into a map.
* <p> * <p>

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.service.cmr.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.rendition.executer.AbstractRenderingEngine;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.PagedSourceOptions;
/**
* Defines options and demarcations needed to describe the details of how
* the source should be transformed, independent of the target requirements.
* <p>
* See {@link PagedSourceOptions} for an example implementation that
* describes the page number that should be used from the source content.
*
* @author Ray Gauss II
*/
public interface TransformationSourceOptions
{
/**
* Gets the list of applicable mimetypes
*
* @return the applicable mimetypes
*/
public List<String> getApplicabledMimetypes();
/**
* Gets whether or not these transformation source options apply for the
* given mimetype
*
* @param mimetype the mimetype of the source
* @return if these transformation source options apply
*/
public boolean isApplicableForMimetype(String mimetype);
/**
* Creates a new <code>TransformationSourceOptions</code> object from this
* one, merging any non-null overriding fields in the given
* <code>overridingOptions</code>
*
* @param overridingOptions
* @return a merged <code>TransformationSourceOptions</code> object
*/
public TransformationSourceOptions mergedOptions(TransformationSourceOptions overridingOptions);
/**
* Gets the serializer for the source options.
*
* @return the serializer
*/
public TransformationSourceOptionsSerializer getSerializer();
/**
* Defines methods for serializing the source options into a parameter map and
* deserializing from a serialized options accessor.
* <p>
* This is primarily used when interacting with the {@link RenditionService}
* with {@link AbstractRenderingEngine}'s RenderContext being an implementer
* of this interface.
*/
public interface TransformationSourceOptionsSerializer
{
/**
* Serializes the given transformation source options into the given parameter map.
*
* @param transformationSourceOptions
* @param parameters
*/
public void serialize(TransformationSourceOptions transformationSourceOptions, Map<String, Serializable> parameters);
/**
* Gets the parameters from the serialized options accessor and builds a source options object.
*
* @param serializedOptions
* @return the deserialized source options
*/
public TransformationSourceOptions deserialize(SerializedTransformationOptionsAccessor serializedOptions);
}
}