KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > repo > content > transform > CompoundContentTransformer


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.repo.content.transform;
18
19 import java.io.File JavaDoc;
20 import java.util.LinkedList JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import org.alfresco.error.AlfrescoRuntimeException;
24 import org.alfresco.repo.content.filestore.FileContentWriter;
25 import org.alfresco.service.cmr.repository.ContentIOException;
26 import org.alfresco.service.cmr.repository.ContentReader;
27 import org.alfresco.service.cmr.repository.ContentWriter;
28 import org.alfresco.util.TempFileProvider;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 /**
33  * A chain of transformations that is able to produce non-zero reliability
34  * transformation from one mimetype to another.
35  * <p>
36  * The reliability of the chain is the product of all the individual
37  * transformations.
38  *
39  * @author Derek Hulley
40  */

41 public class CompoundContentTransformer implements ContentTransformer
42 {
43     private static final Log logger = LogFactory.getLog(CompoundContentTransformer.class);
44     
45     /** a sequence of transformers to apply */
46     private LinkedList JavaDoc<Transformation> chain;
47     /** the combined reliability of all the transformations in the chain */
48     private double reliability;
49     
50     public CompoundContentTransformer()
51     {
52         chain = new LinkedList JavaDoc<Transformation>();
53         reliability = 1.0;
54     }
55     
56     /**
57      * Adds a transformation to the chain. The reliability of each transformation
58      * added must be greater than 0.0.
59      *
60      * @param sourceMimetype
61      * @param targetMimetype
62      * @param transformer the transformer that will transform from the source to
63      * the target mimetype
64      */

65     public void addTransformation(String JavaDoc sourceMimetype, String JavaDoc targetMimetype, ContentTransformer transformer)
66     {
67         // create a transformation that aggregates the transform info
68
Transformation transformation = new Transformation(
69                 transformer,
70                 sourceMimetype,
71                 targetMimetype);
72         // add to the chain
73
chain.add(transformation);
74         // recalculate combined reliability
75
double transformerReliability = transformer.getReliability(sourceMimetype, targetMimetype);
76         if (transformerReliability <= 0.0 || transformerReliability > 1.0)
77         {
78             throw new AlfrescoRuntimeException(
79                     "Reliability of transformer must be between 0.0 and 1.0: \n" +
80                     " transformer: " + transformer + "\n" +
81                     " source: " + sourceMimetype + "\n" +
82                     " target: " + targetMimetype + "\n" +
83                     " reliability: " + transformerReliability);
84         }
85         this.reliability *= transformerReliability;
86     }
87     
88     /**
89      * In order to score anything, the source mimetype must match the source
90      * mimetype of the first transformer and the target mimetype must match
91      * the target mimetype of the last transformer in the chain.
92      *
93      * @return Returns the product of the individual reliability scores of the
94      * transformations in the chain
95      */

96     public double getReliability(String JavaDoc sourceMimetype, String JavaDoc targetMimetype)
97     {
98         if (chain.size() == 0)
99         {
100             // no transformers therefore no transformation possible
101
return 0.0;
102         }
103         Transformation first = chain.getFirst();
104         Transformation last = chain.getLast();
105         if (!first.getSourceMimetype().equals(sourceMimetype)
106                 && last.getTargetMimetype().equals(targetMimetype))
107         {
108             // the source type of the first transformation must match the source
109
// the target type of the last transformation must match the target
110
return 0.0;
111         }
112         return reliability;
113     }
114
115     /**
116      * @return Returns 0 if there are no transformers in the chain otherwise
117      * returns the sum of all the individual transformation times
118      */

119     public long getTransformationTime()
120     {
121         long transformationTime = 0L;
122         for (Transformation transformation : chain)
123         {
124             ContentTransformer transformer = transformation.transformer;
125             transformationTime += transformer.getTransformationTime();
126         }
127         return transformationTime;
128     }
129     
130     /**
131      *
132      */

133     public void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
134     {
135         transform(reader, writer, null);
136     }
137
138     /**
139      * Executes each transformer in the chain, passing the content between them
140      */

141     public void transform(ContentReader reader, ContentWriter writer, Map JavaDoc<String JavaDoc, Object JavaDoc> options)
142             throws ContentIOException
143     {
144         if (chain.size() == 0)
145         {
146             throw new AlfrescoRuntimeException("No transformations present in chain");
147         }
148         
149         // check that the mimetypes of the transformation are valid for the chain
150
String JavaDoc sourceMimetype = reader.getMimetype();
151         String JavaDoc targetMimetype = writer.getMimetype();
152         Transformation firstTransformation = chain.getFirst();
153         Transformation lastTransformation = chain.getLast();
154         if (!firstTransformation.getSourceMimetype().equals(sourceMimetype)
155                 && lastTransformation.getTargetMimetype().equals(targetMimetype))
156         {
157             throw new AlfrescoRuntimeException("Attempting to perform unreliable transformation: \n" +
158                     " reader: " + reader + "\n" +
159                     " writer: " + writer);
160         }
161         
162         ContentReader currentReader = reader;
163         ContentWriter currentWriter = null;
164         int currentIndex = 0;
165         for (Transformation transformation : chain)
166         {
167             boolean last = (currentIndex == chain.size() - 1);
168             if (last)
169             {
170                 // we are on the last transformation so use the final output writer
171
currentWriter = writer;
172             }
173             else
174             {
175                 // have to create an intermediate writer - just use a file writer
176
File JavaDoc tempFile = TempFileProvider.createTempFile("transform", ".tmp");
177                 currentWriter = new FileContentWriter(tempFile);
178                 // set the writer's mimetype to conform to the transformation we are using
179
currentWriter.setMimetype(transformation.getTargetMimetype());
180             }
181             // transform from the current reader to the current writer
182
transformation.execute(currentReader, currentWriter, options);
183             if (!currentWriter.isClosed())
184             {
185                 throw new AlfrescoRuntimeException("Writer not closed by transformation: \n" +
186                         " transformation: " + transformation + "\n" +
187                         " writer: " + currentWriter);
188             }
189             // if we have more transformations, then use the written content
190
// as the next source
191
if (!last)
192             {
193                 currentReader = currentWriter.getReader();
194             }
195         }
196         // done
197
if (logger.isDebugEnabled())
198         {
199             logger.debug("Executed complex transformation: \n" +
200                     " chain: " + chain + "\n" +
201                     " reader: " + reader + "\n" +
202                     " writer: " + writer);
203         }
204     }
205
206     /**
207      * A transformation that contains the transformer as well as the
208      * transformation mimetypes to be used
209      */

210     public static class Transformation extends ContentTransformerRegistry.TransformationKey
211     {
212         private ContentTransformer transformer;
213         public Transformation(ContentTransformer transformer, String JavaDoc sourceMimetype, String JavaDoc targetMimetype)
214         {
215             super(sourceMimetype, targetMimetype);
216             this.transformer = transformer;
217         }
218         
219         /**
220          * Executs the transformation
221          *
222          * @param reader the reader from which to read the content
223          * @param writer the writer to write content to
224          * @param options the options to execute with
225          * @throws ContentIOException if the transformation fails
226          */

227         public void execute(ContentReader reader, ContentWriter writer, Map JavaDoc<String JavaDoc, Object JavaDoc> options)
228                 throws ContentIOException
229         {
230             String JavaDoc sourceMimetype = getSourceMimetype();
231             String JavaDoc targetMimetype = getTargetMimetype();
232             // check that the source and target mimetypes of the reader and writer match
233
if (!sourceMimetype.equals(reader.getMimetype()))
234             {
235                 throw new AlfrescoRuntimeException("The source mimetype doesn't match the reader's mimetype: \n" +
236                         " source mimetype: " + sourceMimetype + "\n" +
237                         " reader: " + reader);
238             }
239             if (!targetMimetype.equals(writer.getMimetype()))
240             {
241                 throw new AlfrescoRuntimeException("The target mimetype doesn't match the writer's mimetype: \n" +
242                         " target mimetype: " + targetMimetype + "\n" +
243                         " writer: " + writer);
244             }
245             transformer.transform(reader, writer, options);
246         }
247     }
248 }
Popular Tags