JavaScript API enhancements - Document and Image transformation services

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3465 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2006-08-08 12:05:41 +00:00
parent df7f1062df
commit 499367c4e9
7 changed files with 246 additions and 7 deletions

View File

@@ -66,6 +66,9 @@
<property name="policyComponent">
<ref bean="policyComponent" />
</property>
<property name="imageMagickContentTransformer">
<ref bean="transformer.ImageMagick" />
</property>
</bean>
<bean id="mimetypeConfigService" class="org.alfresco.config.xml.XMLConfigService" init-method="init">

View File

@@ -7,7 +7,7 @@
<mime-type>application/pdf</mime-type>
<file-extension>pdf</file-extension>
<export-filters>
<entry><family>Presentation</family><string>impress_pdf_Export</string></entry>
<entry><family>Presentation</family><string>impress_pdf_Export</string></entry>
<entry><family>Spreadsheet</family><string>calc_pdf_Export</string></entry>
<entry><family>Text</family><string>writer_pdf_Export</string></entry>
</export-filters>
@@ -30,7 +30,7 @@
<mime-type>text/html</mime-type>
<file-extension>html</file-extension>
<export-filters>
<entry><family>Presentation</family><string>impress_html_Export</string></entry>
<entry><family>Presentation</family><string>impress_html_Export</string></entry>
<entry><family>Spreadsheet</family><string>HTML (StarCalc)</string></entry>
<entry><family>Text</family><string>HTML (StarWriter)</string></entry>
</export-filters>

View File

@@ -405,6 +405,7 @@
org.alfresco.service.cmr.repository.ContentService.getWriter=ACL_NODE.0.sys:base.WriteContent
org.alfresco.service.cmr.repository.ContentService.isTransformable=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.getTransformer=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.getImageTransformer=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.transform=ACL_ALLOW
org.alfresco.service.cmr.repository.ContentService.getTempWriter=ACL_ALLOW
</value>

View File

@@ -169,7 +169,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
// Calculate the destination name
String originalName = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME);
String newName = transformName(originalName, mimeType);
String newName = transformName(this.mimetypeService, originalName, mimeType);
// Since we are overwriting we need to figure out whether the destination node exists
NodeRef copyNodeRef = null;
@@ -225,7 +225,7 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
String originalTitle = (String)nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_TITLE);
if (originalTitle != null && originalTitle.length() > 0)
{
String newTitle = transformName(originalTitle, mimeType);
String newTitle = transformName(this.mimetypeService, originalTitle, mimeType);
nodeService.setProperty(copyNodeRef, ContentModel.PROP_TITLE, newTitle);
}
}
@@ -267,11 +267,11 @@ public class TransformActionExecuter extends ActionExecuterAbstractBase
* Transform name from original extension to new extension
*
* @param original
* @param originalMimetype
* @param newMimetype
* @return
*
* @return name with new extension as appropriate for the mimetype
*/
private String transformName(String original, String newMimetype)
public static String transformName(MimetypeService mimetypeService, String original, String newMimetype)
{
// get the current extension
int dotIndex = original.lastIndexOf('.');

View File

@@ -28,6 +28,7 @@ import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
import org.alfresco.repo.content.filestore.FileContentStore;
import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.repo.content.transform.ContentTransformerRegistry;
import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer;
import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
@@ -72,6 +73,7 @@ public class RoutingContentService implements ContentService
private ContentStore store;
/** the store for all temporarily created content */
private ContentStore tempStore;
private ImageMagickContentTransformer imageMagickContentTransformer;
/**
* The policy component
@@ -122,6 +124,11 @@ public class RoutingContentService implements ContentService
this.policyComponent = policyComponent;
}
public void setImageMagickContentTransformer(ImageMagickContentTransformer imageMagickContentTransformer)
{
this.imageMagickContentTransformer = imageMagickContentTransformer;
}
/**
* Service initialise
*/
@@ -385,6 +392,14 @@ public class RoutingContentService implements ContentService
return transformer;
}
/**
* @see org.alfresco.service.cmr.repository.ContentService#getImageTransformer()
*/
public ContentTransformer getImageTransformer()
{
return imageMagickContentTransformer;
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformerRegistry
* @see org.alfresco.repo.content.transform.ContentTransformer

View File

@@ -30,6 +30,8 @@ import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.TransformActionExecuter;
import org.alfresco.repo.content.transform.magick.ImageMagickContentTransformer;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.ServiceRegistry;
@@ -45,6 +47,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
@@ -1420,6 +1423,196 @@ public final class Node implements Serializable, Scopeable
}
// ------------------------------------------------------------------------------
// Transformation and Rendering API
/**
* Transform a document to a new document mimetype format. A copy of the document is made and
* the extension changed to match the new mimetype, then the transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
*
* @return Node representing the newly transformed document.
*/
public Node transformDocument(String mimetype)
{
return transformDocument(mimetype, getPrimaryParentAssoc().getParentRef());
}
/**
* Transform a document to a new document mimetype format. A copy of the document is made in the
* specified destination folder and the extension changed to match the new mimetype, then then
* transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
* @param destination Destination folder location
*
* @return Node representing the newly transformed document.
*/
public Node transformDocument(String mimetype, Node destination)
{
return transformDocument(mimetype, destination.getNodeRef());
}
private Node transformDocument(String mimetype, NodeRef destination)
{
// the delegate definition for transforming a document
Transformer transformer = new Transformer()
{
public Node transform(ContentService contentService, NodeRef nodeRef, ContentReader reader, ContentWriter writer)
{
Node transformedNode = null;
if (contentService.isTransformable(reader, writer))
{
try
{
contentService.transform(reader, writer);
transformedNode = new Node(nodeRef, services, imageResolver, scope);
}
catch (NoTransformerException err)
{
// failed to find a useful transformer - do not return a node instance
}
}
return transformedNode;
}
};
return transformNode(transformer, mimetype, destination);
}
/**
* Generic method to transform Node content from one mimetype to another.
*
* @param transformer The Transformer delegate supplying the transformation logic
* @param mimetype Mimetype of the destination content
* @param destination Destination folder location for the resulting document
*
* @return Node representing the transformed content - or null if the transform failed
*/
private Node transformNode(Transformer transformer, String mimetype, NodeRef destination)
{
Node transformedNode = null;
// get the content reader
ContentService contentService = this.services.getContentService();
ContentReader reader = contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
// only perform the transformation if some content is available
if (reader != null)
{
// Copy the content node to a new node
NodeRef copyNodeRef = this.services.getCopyService().copy(
this.nodeRef,
destination,
ContentModel.ASSOC_CONTAINS,
getPrimaryParentAssoc().getQName(),
false);
// modify the name of the copy to reflect the new mimetype
this.nodeService.setProperty(
copyNodeRef,
ContentModel.PROP_NAME,
TransformActionExecuter.transformName(
this.services.getMimetypeService(), getName(), mimetype));
// get the writer and set it up
ContentWriter writer = contentService.getWriter(copyNodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(mimetype); // new mimetype
writer.setEncoding(reader.getEncoding()); // original encoding
// Try and transform the content using the supplied delegate
transformedNode = transformer.transform(contentService, copyNodeRef, reader, writer);
}
return transformedNode;
}
/**
* Transform an image to a new image format. A copy of the image document is made and
* the extension changed to match the new mimetype, then the transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
*
* @return Node representing the newly transformed image.
*/
public Node transformImage(String mimetype)
{
return transformImage(mimetype, null, getPrimaryParentAssoc().getParentRef());
}
/**
* Transform an image to a new image format. A copy of the image document is made and
* the extension changed to match the new mimetype, then the transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
* @param options Image convert command options
*
* @return Node representing the newly transformed image.
*/
public Node transformImage(String mimetype, String options)
{
return transformImage(mimetype, options, getPrimaryParentAssoc().getParentRef());
}
/**
* Transform an image to a new image mimetype format. A copy of the image document is made in the
* specified destination folder and the extension changed to match the new mimetype, then then
* transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
* @param destination Destination folder location
*
* @return Node representing the newly transformed image.
*/
public Node transformImage(String mimetype, Node destination)
{
return transformImage(mimetype, null, destination.getNodeRef());
}
/**
* Transform an image to a new image mimetype format. A copy of the image document is made in the
* specified destination folder and the extension changed to match the new mimetype, then then
* transformation is applied.
*
* @param mimetype Mimetype destination for the transformation
* @param options Image convert command options
* @param destination Destination folder location
*
* @return Node representing the newly transformed image.
*/
public Node transformImage(String mimetype, String options, Node destination)
{
return transformImage(mimetype, options, destination.getNodeRef());
}
private Node transformImage(String mimetype, final String options, NodeRef destination)
{
// the delegate definition for transforming an image
Transformer transformer = new Transformer()
{
public Node transform(ContentService contentService, NodeRef nodeRef, ContentReader reader, ContentWriter writer)
{
Node transformedNode = null;
try
{
Map<String, Object> opts = new HashMap<String, Object>(1);
opts.put(ImageMagickContentTransformer.KEY_OPTIONS, options != null ? options : "");
contentService.getImageTransformer().transform(reader, writer, opts);
transformedNode = new Node(nodeRef, services, imageResolver, scope);
}
catch (NoTransformerException err)
{
// failed to find a useful transformer - do not return a node instance
}
return transformedNode;
}
};
return transformNode(transformer, mimetype, destination);
}
// ------------------------------------------------------------------------------
// Helper methods
@@ -1647,4 +1840,23 @@ public final class Node implements Serializable, Scopeable
private ContentData contentData;
private QName property;
}
/**
* Interface contract for simple anonymous classes that implement document transformations
*/
private interface Transformer
{
/**
* Transform the reader to the specified writer
*
* @param contentService ContentService
* @param noderef NodeRef of the destination for the transform
* @param reader Source reader
* @param writer Destination writer
*
* @return Node representing the transformed entity
*/
Node transform(ContentService contentService, NodeRef noderef, ContentReader reader, ContentWriter writer);
}
}

View File

@@ -126,6 +126,14 @@ public interface ContentService
@Auditable(parameters = {"sourceMimetype", "targetMimetype"})
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype);
/**
* Fetch the transformer that is capable of transforming image content.
*
* @return Returns a transformer that can be used, or null if one was not available
*/
@Auditable
public ContentTransformer getImageTransformer();
/**
* Returns whether a transformer exists that can read the content from
* the reader and write the content back out to the writer.