KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nightlabs > editor2d > iofilter > XStreamFilter


1 /* *****************************************************************************
2  * NightLabs Editor2D - Graphical editor framework *
3  * Copyright (C) 2004-2005 NightLabs - http://NightLabs.org *
4  * *
5  * This library is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or (at your option) any later version. *
9  * *
10  * This library is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13  * Lesser General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Lesser General Public *
16  * License along with this library; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin St, Fifth Floor, *
19  * Boston, MA 02110-1301 USA *
20  * *
21  * Or get it online : *
22  * http://www.gnu.org/copyleft/lesser.html *
23  * *
24  * *
25  ******************************************************************************/

26
27 package org.nightlabs.editor2d.iofilter;
28
29 import java.awt.Rectangle JavaDoc;
30 import java.awt.geom.AffineTransform JavaDoc;
31 import java.awt.image.BufferedImage JavaDoc;
32 import java.io.BufferedInputStream JavaDoc;
33 import java.io.BufferedOutputStream JavaDoc;
34 import java.io.FileNotFoundException JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.InputStreamReader JavaDoc;
38 import java.io.OutputStream JavaDoc;
39 import java.io.OutputStreamWriter JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Collection JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.Iterator JavaDoc;
44 import java.util.List JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.zip.ZipEntry JavaDoc;
47 import java.util.zip.ZipInputStream JavaDoc;
48 import java.util.zip.ZipOutputStream JavaDoc;
49
50 import org.apache.log4j.Logger;
51 import org.nightlabs.editor2d.DrawComponent;
52 import org.nightlabs.editor2d.DrawComponentContainer;
53 import org.nightlabs.editor2d.ImageDrawComponent;
54 import org.nightlabs.editor2d.MultiLayerDrawComponent;
55 import org.nightlabs.editor2d.impl.ImageDrawComponentImpl;
56 import org.nightlabs.editor2d.iofilter.xstream.AffineTransformConverter;
57 import org.nightlabs.editor2d.iofilter.xstream.GeneralShapeConverter;
58 import org.nightlabs.editor2d.iofilter.xstream.ImageDrawComponentConverter;
59 import org.nightlabs.editor2d.j2d.GeneralShape;
60 import org.nightlabs.io.AbstractIOFilterWithProgress;
61 import org.nightlabs.io.ReadException;
62 import org.nightlabs.io.WriteException;
63
64 import com.sun.image.codec.jpeg.ImageFormatException;
65 import com.sun.image.codec.jpeg.JPEGCodec;
66 import com.sun.image.codec.jpeg.JPEGEncodeParam;
67 import com.sun.image.codec.jpeg.JPEGImageEncoder;
68 import com.thoughtworks.xstream.XStream;
69 import com.thoughtworks.xstream.io.xml.XppDriver;
70
71 public class XStreamFilter
72 extends AbstractIOFilterWithProgress
73 {
74     public static final String JavaDoc FILE_EXTENSION = "e2d";
75     public static final Logger LOGGER = Logger.getLogger(XStreamFilter.class.getName());
76             
77     public static final String JavaDoc SUBTASK_DECOMPRESS = "Decompress";
78     public static final String JavaDoc SUBTASK_PARSING = "Parsing";
79     public static final String JavaDoc SUBTASK_REBUILD = "Rebuilding";
80     
81     public static final String JavaDoc SUBTASK_COMPRESS = "Compress";
82     public static final String JavaDoc SUBTASK_WRITING = "Writing";
83     
84     public static final String JavaDoc MANIFEST_NAME = "manifest.xml";
85     public static final String JavaDoc META_INF_DIR = "meta-inf/";
86     public static final String JavaDoc IMAGES_DIR = "images/";
87     public static final String JavaDoc CHARSET_NAME = "UTF-8";
88     
89     public static final String JavaDoc EDITOR2D_CONTENT_TYPE = "vnd.nightlabs.editor2d";
90     
91     public XStreamFilter()
92     {
93         super();
94     }
95     
96     protected void initReadSubTasks()
97     {
98         flushSubTasks();
99         addSubTask(SUBTASK_DECOMPRESS, 10);
100         addSubTask(SUBTASK_PARSING, 80);
101         addSubTask(SUBTASK_REBUILD, 10);
102     }
103     
104     protected void initWriteSubTasks()
105     {
106         flushSubTasks();
107         addSubTask(SUBTASK_COMPRESS, 10);
108         addSubTask(SUBTASK_WRITING, 90);
109     }
110     
111     protected MultiLayerDrawComponent mldc = null;
112     
113     protected Map JavaDoc imageName2BufferedImage;
114     protected Map JavaDoc getImageName2BufferedImage()
115     {
116         if (imageName2BufferedImage == null)
117             imageName2BufferedImage = new HashMap JavaDoc();
118         
119         return imageName2BufferedImage;
120     }
121     
122     /**
123      * Reads the XStream-File-Format and returns the SunDrawComponent
124      * First the File is unzipped and then redundant informtion is rebuild
125      * @return the SunDrawComponent to read
126      */

127     public Object JavaDoc read(InputStream JavaDoc in)
128     throws ReadException
129     {
130         LOGGER.debug("XStream READ BEGIN!");
131         long startTime = System.currentTimeMillis();
132         initReadSubTasks();
133         XStream xstream = new XStream(new XppDriver());
134
135         ZipInputStream JavaDoc zipStream = new ZipInputStream JavaDoc(in);
136         try
137         {
138             // META-INF-Directory
139
ZipEntry JavaDoc metaInfEntry = zipStream.getNextEntry();
140             if (metaInfEntry.isDirectory()) {
141                 String JavaDoc metaInfDir = metaInfEntry.getName();
142             }
143             zipStream.closeEntry();
144
145             // Manifest.xml
146
ZipEntry JavaDoc manifestEntry = zipStream.getNextEntry();
147             InputStream JavaDoc zipIn = new BufferedInputStream JavaDoc(zipStream);
148             ManifestReader manifestReader = new ManifestReader(zipIn);
149             manifestReader.read();
150             List JavaDoc imageInfo = manifestReader.getImageInfo();
151             zipStream.closeEntry();
152             
153             // Content.xml
154
ZipEntry JavaDoc contentEntry = zipStream.getNextEntry();
155             InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(new BufferedInputStream JavaDoc(zipStream));
156             registerConverter(xstream);
157             processSubTask(SUBTASK_DECOMPRESS);
158             long newTime = System.currentTimeMillis() - startTime;
159             LOGGER.debug("XStream PARSING BEGINS after "+newTime+" ms");
160             Object JavaDoc o = xstream.fromXML(reader);
161             processSubTask(SUBTASK_PARSING);
162             newTime = System.currentTimeMillis() - startTime;
163             LOGGER.debug("XStream PARSING took = "+newTime+" ms");
164             zipStream.closeEntry();
165             
166             // Images
167
if (!imageInfo.isEmpty())
168             {
169                 ZipEntry JavaDoc imageDirEntry = zipStream.getNextEntry();
170                 zipStream.closeEntry();
171                 
172                 for (Iterator JavaDoc it = imageInfo.iterator(); it.hasNext(); ) {
173                     String JavaDoc[] info = (String JavaDoc[]) it.next();
174                     String JavaDoc imageType = info[0];
175                     String JavaDoc imageName = info[1];
176                     BufferedImage JavaDoc image = readImage(zipStream, imageType);
177                     if (image != null)
178                         getImageName2BufferedImage().put(imageName, image);
179                 }
180             }
181             
182             zipIn.close();
183             manifestReader.close();
184             reader.close();
185             zipStream.close();
186             
187             if (o instanceof MultiLayerDrawComponent) {
188                 mldc = (MultiLayerDrawComponent) o;
189                 rebuild(mldc);
190                 processSubTask(SUBTASK_REBUILD);
191                 newTime = System.currentTimeMillis() - startTime;
192                 LOGGER.debug("XStream TOTAL READ took "+newTime+" ms");
193                 return mldc;
194             }
195             return o;
196         } catch (IOException JavaDoc e) {
197             throw new RuntimeException JavaDoc(e);
198         }
199     }
200         
201     protected ManifestWriter manifestWriter = null;
202     /**
203      * Writes the given Object (SunDrawComponent) zipped to the OutputStream
204      */

205     public void write(Object JavaDoc o, OutputStream JavaDoc out)
206     throws WriteException
207     {
208         XStream xstream = new XStream(new XppDriver());
209         initWriteSubTasks();
210         try {
211             ZipOutputStream JavaDoc zipStream = new ZipOutputStream JavaDoc(out);
212             zipStream.setLevel(9);
213             
214             MultiLayerDrawComponent mldc = (MultiLayerDrawComponent) o;
215                         
216             // META-INF-Directory
217
ZipEntry JavaDoc metaInfEntry = new ZipEntry JavaDoc(META_INF_DIR);
218             zipStream.putNextEntry(metaInfEntry);
219             zipStream.closeEntry();
220                         
221             // Manifest.xml
222
ZipEntry JavaDoc manifestEntry = new ZipEntry JavaDoc(META_INF_DIR + MANIFEST_NAME);
223             zipStream.putNextEntry(manifestEntry);
224             OutputStreamWriter JavaDoc manifestOut = new OutputStreamWriter JavaDoc(new BufferedOutputStream JavaDoc(zipStream), CHARSET_NAME);
225             manifestWriter = new ManifestWriter(EDITOR2D_CONTENT_TYPE);
226             manifestWriter.setEncoding(CHARSET_NAME);
227             StringBuffer JavaDoc sb = manifestWriter.writeManifest(mldc);
228             String JavaDoc manifest = sb.toString();
229             manifestOut.write(manifest);
230             LOGGER.debug("Manifest.xml");
231             LOGGER.debug("\n" + manifest);
232             manifestOut.flush();
233             zipStream.closeEntry();
234                         
235             // Content.xml
236
ZipEntry JavaDoc contentEntry = new ZipEntry JavaDoc(ManifestWriter.DEFAULT_CONTENT_NAME);
237             zipStream.putNextEntry(contentEntry);
238             OutputStreamWriter JavaDoc writer = new OutputStreamWriter JavaDoc(new BufferedOutputStream JavaDoc(zipStream), CHARSET_NAME);
239             registerConverter(xstream);
240             processSubTask(SUBTASK_COMPRESS);
241             xstream.toXML(o, writer);
242             processSubTask(SUBTASK_WRITING);
243             zipStream.closeEntry();
244              
245             if (manifestWriter.containsImages(mldc))
246             {
247                 // Images-Directory
248
ZipEntry JavaDoc imagesEntry = new ZipEntry JavaDoc(IMAGES_DIR);
249                 zipStream.putNextEntry(imagesEntry);
250                 zipStream.closeEntry();
251                 
252                 // Images
253
writeImages(mldc, zipStream);
254             }
255             
256             zipStream.finish();
257             zipStream.close();
258             
259             manifestOut.close();
260             writer.close();
261             
262         } catch (IOException JavaDoc e) {
263             throw new RuntimeException JavaDoc(e);
264         }
265     }
266     
267 // protected int jpgQuality = 50;
268
protected void writeImages(MultiLayerDrawComponent mldc, ZipOutputStream JavaDoc out)
269     {
270         Collection JavaDoc imageDCs = mldc.getDrawComponents(ImageDrawComponentImpl.class);
271         if (imageDCs != null)
272         {
273             for (Iterator JavaDoc it = imageDCs.iterator(); it.hasNext(); )
274             {
275                 ImageDrawComponent image = (ImageDrawComponent) it.next();
276                 try {
277                     ZipEntry JavaDoc imageEntry = new ZipEntry JavaDoc(IMAGES_DIR + image.getName());
278                     out.putNextEntry(imageEntry);
279                 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
280                 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image.getOriginalImage());
281 // int quality = Math.max(0, Math.min(jpgQuality, 100));
282
// param.setQuality((float)quality / 100.0f, false);
283
encoder.setJPEGEncodeParam(param);
284                 encoder.encode(image.getOriginalImage());
285                 out.closeEntry();
286                 }
287                 catch (FileNotFoundException JavaDoc e) {
288                     throw new RuntimeException JavaDoc(e);
289                 } catch (ImageFormatException e) {
290                     throw new RuntimeException JavaDoc(e);
291                 } catch (IOException JavaDoc e) {
292                     throw new RuntimeException JavaDoc(e);
293                 }
294             }
295         }
296     }
297     
298     /**
299      *
300      * @param in the ZipInputStream to read
301      * @param imageType the type of the Image as read from the Manifest.xml (e.g. jpg)
302      * at the moment only JPG is supported
303      * @return the decoded BufferedImage
304      */

305     protected BufferedImage JavaDoc readImage(ZipInputStream JavaDoc in, String JavaDoc imageType)
306     {
307         try {
308             ZipEntry JavaDoc imageEntry = in.getNextEntry();
309             LOGGER.debug("imageEntry = "+imageEntry.getName());
310             BufferedImage JavaDoc image = null;
311             if (imageType.equals("jpg")) {
312                 image = JPEGCodec.createJPEGDecoder(in).decodeAsBufferedImage();
313             }
314             return image;
315         }
316         catch (IOException JavaDoc e) {
317             throw new RuntimeException JavaDoc(e);
318         }
319     }
320     
321     /**
322      * rebuilds all necessary redundant information which is not saved in the file-format
323      *
324      * @param mldc the MultiLayerDrawComponent to rebuild
325      */

326     public void rebuild(MultiLayerDrawComponent mldc)
327     {
328         LOGGER.debug("Rebuild BEGIN!");
329         long startTime = System.currentTimeMillis();
330         rebuildIDAndTypeMap(mldc.getDrawComponents(), mldc);
331         long newTime = System.currentTimeMillis() - startTime;
332         LOGGER.debug("Rebuild FILL MAPS took "+newTime+" ms");
333         rebuildImages(mldc);
334         newTime = System.currentTimeMillis() - startTime;
335         LOGGER.debug("Rebuild Images took "+newTime+" ms");
336     }
337                     
338     protected AffineTransform JavaDoc at = new AffineTransform JavaDoc();
339         
340     /**
341      * Rebuilds both Maps (id2DrawComponent and class2DrawComponents) of a
342      * MultiLayerDrawComponent based on the entries in the drawComponents-Lists of
343      * all DrawComponentContainers.
344      *
345      * This is done by recursivly going through all drawComponents-Lists of
346      * all DrawComponentContainers.
347      *
348      * @param drawComponents a List of drawComponents
349      * (the drawComponents-List of a DrawComponentContainer)
350      * @param mldc The MultiLayerDrawComponent to rebuild
351      */

352     protected void rebuildIDAndTypeMap(List JavaDoc drawComponents, MultiLayerDrawComponent mldc)
353     {
354         for (Iterator JavaDoc it = drawComponents.iterator(); it.hasNext(); )
355         {
356             DrawComponent dc = (DrawComponent) it.next();
357             long id = dc.getId();
358             mldc.getId2DrawComponent().put(new Long JavaDoc(id), dc);
359             rebuildTypeMap(dc, mldc);
360             if (dc instanceof DrawComponentContainer) {
361                 DrawComponentContainer container = (DrawComponentContainer) dc;
362                 List JavaDoc children = container.getDrawComponents();
363                 rebuildIDAndTypeMap(children, mldc);
364             }
365         }
366     }
367     
368     /**
369      * rebuilds the class2DrawComponents-Map for the MultiLayerDrawComponent
370      * this Method is called recursivly by rebuildIDAndTypeMap(List, MultiLayerDrawComponent)
371      *
372      * @param drawComponent the drawComponent to add to the typeMap
373      * @param mldc the Root-Object for the given drawComponent
374      */

375     protected void rebuildTypeMap(DrawComponent drawComponent, MultiLayerDrawComponent mldc)
376     {
377     Class JavaDoc dcClass = drawComponent.getClass();
378     Collection JavaDoc typeCollection = null;
379     if (!mldc.getClass2DrawComponents().containsKey(dcClass))
380     {
381       typeCollection = new ArrayList JavaDoc();
382       typeCollection.add(drawComponent);
383       mldc.getClass2DrawComponents().put(dcClass, typeCollection);
384     }
385     else if (mldc.getClass2DrawComponents().containsKey(dcClass))
386     {
387       typeCollection = (Collection JavaDoc) mldc.getClass2DrawComponents().get(dcClass);
388       typeCollection.add(drawComponent);
389     }
390     }
391     
392     protected void rebuildImages(MultiLayerDrawComponent mldc)
393     {
394         Collection JavaDoc images = mldc.getDrawComponents(ImageDrawComponentImpl.class);
395         if (images != null) {
396             for (Iterator JavaDoc it = images.iterator(); it.hasNext(); )
397             {
398                 ImageDrawComponent img = (ImageDrawComponent) it.next();
399                 // TODO: avoid this dirty workaround, by adding parentID to DrawComponent
400
img.setParent(mldc.getCurrentLayer());
401                 if (getImageName2BufferedImage().containsKey(img.getName()))
402                 {
403                     GeneralShape oldImageShape = img.getImageShape();
404                     AffineTransform JavaDoc oldAT = img.getAffineTransform();
405                     Rectangle JavaDoc oldBounds = oldImageShape.getBounds();
406                     
407                     BufferedImage JavaDoc bufferedImage = (BufferedImage JavaDoc) getImageName2BufferedImage().get(img.getName());
408                     img.setImage(bufferedImage);
409                     
410                     img.setAffineTransform(new AffineTransform JavaDoc());
411                     img.transform(oldAT);
412                     img.setBounds(new Rectangle JavaDoc(img.getX(), img.getY(), oldBounds.width, oldBounds.height));
413                     img.setImageShape(oldImageShape);
414                     img.setRotationX(DrawComponent.ROTATION_X_DEFAULT);
415                     img.setRotationY(DrawComponent.ROTATION_Y_DEFAULT);
416                     img.setAffineTransform(oldAT);
417                     
418                     if (oldAT.equals(img.getAffineTransform()))
419                         LOGGER.debug("oldAT = newAT");
420                 }
421             }
422         }
423     }
424         
425     /**
426      * registers Converters to the given XStream
427      *
428      * @param xstream the Xstream to which Converters should be added
429      */

430     protected void registerConverter(XStream xstream)
431     {
432         xstream.registerConverter(new GeneralShapeConverter());
433         xstream.registerConverter(new ImageDrawComponentConverter());
434         xstream.registerConverter(new AffineTransformConverter());
435         
436 // xstream.registerConverter(new TextDrawComponentConverter());
437
// xstream.registerConverter(new LineDrawComponentConverter());
438
// xstream.registerConverter(new EllipseDrawComponentConverter());
439
// xstream.registerConverter(new RectangleDrawComponentConverter());
440
}
441     
442     public String JavaDoc getFileExtension() {
443         return FILE_EXTENSION;
444     }
445
446     public String JavaDoc getDescription() {
447         return "Editor2D Description";
448     }
449
450 }
451
Popular Tags