package org.simantics.diagram.svg.export; import java.awt.Shape; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.batik.svggen.SVGGeneratorContext; import org.apache.batik.svggen.SVGShape; import org.simantics.db.common.utils.Logger; import org.simantics.scenegraph.utils.SVGPassthruShape; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; public class SVGShapeWithPassthruSupport extends SVGShape { private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); public SVGShapeWithPassthruSupport(SVGGeneratorContext generatorCtx) { super(generatorCtx); dbf.setValidating(false); dbf.setExpandEntityReferences(false); try { dbf.setFeature("http://xml.org/sax/features/namespaces", false); dbf.setFeature("http://xml.org/sax/features/validation", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } catch (ParserConfigurationException e) { Logger.defaultLogError(e); } } public Element toSVG(Shape shape) { if (shape instanceof SVGPassthruShape) { String source = ((SVGPassthruShape) shape).getSource(); try { Document owner = generatorContext.getDOMFactory(); @SuppressWarnings("unchecked") Map defsMap = (Map)owner.getUserData("defs-map"); if (defsMap == null) { defsMap = new HashMap(); owner.setUserData("defs-map", defsMap, null); } synchronized (defsMap) { String symbolId = defsMap.get(source); if (symbolId == null) { symbolId = "S" + defsMap.size(); defsMap.put(source, symbolId); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new ByteArrayInputStream(source.getBytes("UTF-8"))); Node node = doc.getDocumentElement(); Node localNode = owner.importNode(node, true); if (localNode instanceof Element) { Element g = generatorContext.getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_G_TAG); Element e = (Element)localNode; e.setAttribute("id", symbolId); g.appendChild(localNode); return g; } else { return null; } } else { Element element = owner.createElement("use"); element.setAttribute("xlink:href", "#" + symbolId); return element; } } } catch (UnsupportedEncodingException e) { Logger.defaultLogError(e); return null; } catch (IOException e) { Logger.defaultLogError(e); return null; } catch (ParserConfigurationException e) { Logger.defaultLogError(e); return null; } catch (SAXException e) { Logger.defaultLogError(e); return null; } } else { return super.toSVG(shape); } } }