1 26 27 package org.nightlabs.editor2d.iofilter; 28 29 import java.awt.Rectangle ; 30 import java.awt.geom.AffineTransform ; 31 import java.awt.image.BufferedImage ; 32 import java.io.BufferedInputStream ; 33 import java.io.BufferedOutputStream ; 34 import java.io.FileNotFoundException ; 35 import java.io.IOException ; 36 import java.io.InputStream ; 37 import java.io.InputStreamReader ; 38 import java.io.OutputStream ; 39 import java.io.OutputStreamWriter ; 40 import java.util.ArrayList ; 41 import java.util.Collection ; 42 import java.util.HashMap ; 43 import java.util.Iterator ; 44 import java.util.List ; 45 import java.util.Map ; 46 import java.util.zip.ZipEntry ; 47 import java.util.zip.ZipInputStream ; 48 import java.util.zip.ZipOutputStream ; 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 FILE_EXTENSION = "e2d"; 75 public static final Logger LOGGER = Logger.getLogger(XStreamFilter.class.getName()); 76 77 public static final String SUBTASK_DECOMPRESS = "Decompress"; 78 public static final String SUBTASK_PARSING = "Parsing"; 79 public static final String SUBTASK_REBUILD = "Rebuilding"; 80 81 public static final String SUBTASK_COMPRESS = "Compress"; 82 public static final String SUBTASK_WRITING = "Writing"; 83 84 public static final String MANIFEST_NAME = "manifest.xml"; 85 public static final String META_INF_DIR = "meta-inf/"; 86 public static final String IMAGES_DIR = "images/"; 87 public static final String CHARSET_NAME = "UTF-8"; 88 89 public static final String 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 imageName2BufferedImage; 114 protected Map getImageName2BufferedImage() 115 { 116 if (imageName2BufferedImage == null) 117 imageName2BufferedImage = new HashMap (); 118 119 return imageName2BufferedImage; 120 } 121 122 127 public Object read(InputStream 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 zipStream = new ZipInputStream (in); 136 try 137 { 138 ZipEntry metaInfEntry = zipStream.getNextEntry(); 140 if (metaInfEntry.isDirectory()) { 141 String metaInfDir = metaInfEntry.getName(); 142 } 143 zipStream.closeEntry(); 144 145 ZipEntry manifestEntry = zipStream.getNextEntry(); 147 InputStream zipIn = new BufferedInputStream (zipStream); 148 ManifestReader manifestReader = new ManifestReader(zipIn); 149 manifestReader.read(); 150 List imageInfo = manifestReader.getImageInfo(); 151 zipStream.closeEntry(); 152 153 ZipEntry contentEntry = zipStream.getNextEntry(); 155 InputStreamReader reader = new InputStreamReader (new BufferedInputStream (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 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 if (!imageInfo.isEmpty()) 168 { 169 ZipEntry imageDirEntry = zipStream.getNextEntry(); 170 zipStream.closeEntry(); 171 172 for (Iterator it = imageInfo.iterator(); it.hasNext(); ) { 173 String [] info = (String []) it.next(); 174 String imageType = info[0]; 175 String imageName = info[1]; 176 BufferedImage 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 e) { 197 throw new RuntimeException (e); 198 } 199 } 200 201 protected ManifestWriter manifestWriter = null; 202 205 public void write(Object o, OutputStream out) 206 throws WriteException 207 { 208 XStream xstream = new XStream(new XppDriver()); 209 initWriteSubTasks(); 210 try { 211 ZipOutputStream zipStream = new ZipOutputStream (out); 212 zipStream.setLevel(9); 213 214 MultiLayerDrawComponent mldc = (MultiLayerDrawComponent) o; 215 216 ZipEntry metaInfEntry = new ZipEntry (META_INF_DIR); 218 zipStream.putNextEntry(metaInfEntry); 219 zipStream.closeEntry(); 220 221 ZipEntry manifestEntry = new ZipEntry (META_INF_DIR + MANIFEST_NAME); 223 zipStream.putNextEntry(manifestEntry); 224 OutputStreamWriter manifestOut = new OutputStreamWriter (new BufferedOutputStream (zipStream), CHARSET_NAME); 225 manifestWriter = new ManifestWriter(EDITOR2D_CONTENT_TYPE); 226 manifestWriter.setEncoding(CHARSET_NAME); 227 StringBuffer sb = manifestWriter.writeManifest(mldc); 228 String 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 ZipEntry contentEntry = new ZipEntry (ManifestWriter.DEFAULT_CONTENT_NAME); 237 zipStream.putNextEntry(contentEntry); 238 OutputStreamWriter writer = new OutputStreamWriter (new BufferedOutputStream (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 ZipEntry imagesEntry = new ZipEntry (IMAGES_DIR); 249 zipStream.putNextEntry(imagesEntry); 250 zipStream.closeEntry(); 251 252 writeImages(mldc, zipStream); 254 } 255 256 zipStream.finish(); 257 zipStream.close(); 258 259 manifestOut.close(); 260 writer.close(); 261 262 } catch (IOException e) { 263 throw new RuntimeException (e); 264 } 265 } 266 267 protected void writeImages(MultiLayerDrawComponent mldc, ZipOutputStream out) 269 { 270 Collection imageDCs = mldc.getDrawComponents(ImageDrawComponentImpl.class); 271 if (imageDCs != null) 272 { 273 for (Iterator it = imageDCs.iterator(); it.hasNext(); ) 274 { 275 ImageDrawComponent image = (ImageDrawComponent) it.next(); 276 try { 277 ZipEntry imageEntry = new ZipEntry (IMAGES_DIR + image.getName()); 278 out.putNextEntry(imageEntry); 279 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 280 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image.getOriginalImage()); 281 encoder.setJPEGEncodeParam(param); 284 encoder.encode(image.getOriginalImage()); 285 out.closeEntry(); 286 } 287 catch (FileNotFoundException e) { 288 throw new RuntimeException (e); 289 } catch (ImageFormatException e) { 290 throw new RuntimeException (e); 291 } catch (IOException e) { 292 throw new RuntimeException (e); 293 } 294 } 295 } 296 } 297 298 305 protected BufferedImage readImage(ZipInputStream in, String imageType) 306 { 307 try { 308 ZipEntry imageEntry = in.getNextEntry(); 309 LOGGER.debug("imageEntry = "+imageEntry.getName()); 310 BufferedImage image = null; 311 if (imageType.equals("jpg")) { 312 image = JPEGCodec.createJPEGDecoder(in).decodeAsBufferedImage(); 313 } 314 return image; 315 } 316 catch (IOException e) { 317 throw new RuntimeException (e); 318 } 319 } 320 321 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 at = new AffineTransform (); 339 340 352 protected void rebuildIDAndTypeMap(List drawComponents, MultiLayerDrawComponent mldc) 353 { 354 for (Iterator it = drawComponents.iterator(); it.hasNext(); ) 355 { 356 DrawComponent dc = (DrawComponent) it.next(); 357 long id = dc.getId(); 358 mldc.getId2DrawComponent().put(new Long (id), dc); 359 rebuildTypeMap(dc, mldc); 360 if (dc instanceof DrawComponentContainer) { 361 DrawComponentContainer container = (DrawComponentContainer) dc; 362 List children = container.getDrawComponents(); 363 rebuildIDAndTypeMap(children, mldc); 364 } 365 } 366 } 367 368 375 protected void rebuildTypeMap(DrawComponent drawComponent, MultiLayerDrawComponent mldc) 376 { 377 Class dcClass = drawComponent.getClass(); 378 Collection typeCollection = null; 379 if (!mldc.getClass2DrawComponents().containsKey(dcClass)) 380 { 381 typeCollection = new ArrayList (); 382 typeCollection.add(drawComponent); 383 mldc.getClass2DrawComponents().put(dcClass, typeCollection); 384 } 385 else if (mldc.getClass2DrawComponents().containsKey(dcClass)) 386 { 387 typeCollection = (Collection ) mldc.getClass2DrawComponents().get(dcClass); 388 typeCollection.add(drawComponent); 389 } 390 } 391 392 protected void rebuildImages(MultiLayerDrawComponent mldc) 393 { 394 Collection images = mldc.getDrawComponents(ImageDrawComponentImpl.class); 395 if (images != null) { 396 for (Iterator it = images.iterator(); it.hasNext(); ) 397 { 398 ImageDrawComponent img = (ImageDrawComponent) it.next(); 399 img.setParent(mldc.getCurrentLayer()); 401 if (getImageName2BufferedImage().containsKey(img.getName())) 402 { 403 GeneralShape oldImageShape = img.getImageShape(); 404 AffineTransform oldAT = img.getAffineTransform(); 405 Rectangle oldBounds = oldImageShape.getBounds(); 406 407 BufferedImage bufferedImage = (BufferedImage ) getImageName2BufferedImage().get(img.getName()); 408 img.setImage(bufferedImage); 409 410 img.setAffineTransform(new AffineTransform ()); 411 img.transform(oldAT); 412 img.setBounds(new Rectangle (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 430 protected void registerConverter(XStream xstream) 431 { 432 xstream.registerConverter(new GeneralShapeConverter()); 433 xstream.registerConverter(new ImageDrawComponentConverter()); 434 xstream.registerConverter(new AffineTransformConverter()); 435 436 } 441 442 public String getFileExtension() { 443 return FILE_EXTENSION; 444 } 445 446 public String getDescription() { 447 return "Editor2D Description"; 448 } 449 450 } 451 | Popular Tags |