+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<String, String> defsMap = (Map<String, String>)owner.getUserData("defs-map");
+ if (defsMap == null) {
+ defsMap = new HashMap<String, String>();
+ 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);
+ }
+
+ }
+
+}