package at.bestsolution.efxclipse.formats.svg.handler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.zip.GZIPInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import at.bestsolution.efxclipse.formats.svg.converter.FXMLConverter;
import at.bestsolution.efxclipse.formats.svg.svg.ContentElement;
import at.bestsolution.efxclipse.formats.svg.svg.CoreAttributes;
import at.bestsolution.efxclipse.formats.svg.svg.SvgElement;
import at.bestsolution.efxclipse.formats.svg.svg.SvgPackage;
import at.bestsolution.efxclipse.formats.svg.svg.SvgSvgElement;
public class XMLLoader {
public static void main(String[] args) {
XMLLoader l = new XMLLoader();
try {
File f = new File("/Users/tomschindl/git/e-fx-clipse/at.bestsolution.efxclipse.formats.svg/samples/oxygen/test2.svg");
InputStream in;
if( f.getName().endsWith("svgz") ) {
in = new GZIPInputStream(f.toURL().openStream());
} else {
in = f.toURL().openStream();
}
SvgSvgElement g = l.loadDocument(in);
// SvgSvgElement g = l.loadDocument(new File("/Users/tomschindl/git/e-fx-clipse/at.bestsolution.efxclipse.formats.svg/samples/w3/images/shapes/rect01.svg").toURL().openStream());
// SvgSvgElement g = l.loadDocument(new File("/Users/tomschindl/git/e-fx-clipse/at.bestsolution.efxclipse.formats.svg/samples/w3/images/filters/filters01.svg").toURL().openStream());
FXMLConverter c = new FXMLConverter(g);
String fxmlData = c.generate().toString();
System.err.println("data: " + fxmlData);
File outFile = new File("/Users/tomschindl/git/e-fx-clipse/at.bestsolution.efxclipse.formats.svg/samples/test.fxml");
FileOutputStream out = new FileOutputStream(outFile);
out.write(fxmlData.getBytes());
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public SvgSvgElement loadDocument(InputStream in) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();
Handler handler = new Handler();
parser.parse(in, handler);
postProcess(handler.root);
return handler.root;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private void postProcess(SvgSvgElement root) {
TreeIterator<EObject> it = EcoreUtil.getAllContents(root, true);
while( it.hasNext() ) {
EObject o = it.next();
EStructuralFeature f = o.eClass().getEStructuralFeature("style");
if( f != null ) {
String s = (String) o.eGet(f);
if( s != null && s.trim().length() > 0 ) {
for( Entry<String, String> e : valueMap(s).entrySet() ) {
String name = e.getKey().replaceAll("-", "_");
EStructuralFeature styleFeature = o.eClass().getEStructuralFeature(name.trim());
if( styleFeature != null ) {
Object value = EcoreUtil.createFromString((EDataType) styleFeature.getEType(), e.getValue());
o.eSet(styleFeature, value);
} else {
System.err.println("Could not find style attribute: " + name + " on " + o.eClass());
}
}
}
}
f = o.eClass().getEStructuralFeature("xlink__href");
if( f != null ) {
EStructuralFeature instanceFeature = o.eClass().getEStructuralFeature("resolvedInstance");
String link = (String) o.eGet(f);
if( link != null && link.trim().length() > 0 ) {
link = link.substring(1);
TreeIterator<EObject> internalIt = EcoreUtil.getAllContents(root, true);
while( internalIt.hasNext() ) {
EObject internalO = internalIt.next();
if( internalO instanceof CoreAttributes ) {
if( link.equals(internalO.eGet(SvgPackage.Literals.CORE_ATTRIBUTES__ID))) {
o.eSet(instanceFeature, internalO);
break;
}
}
}
}
}
}
}
private Map<String, String> valueMap(String styleString) {
//TODO This is a very very poor algorithm
Map<String,String> map = new HashMap<String, String>();
for( String o : styleString.split(";") ) {
String k = o.substring(0,o.indexOf(":"));
String v = o.substring(o.indexOf(":")+1,o.length());
map.put(k, v);
}
return map;
}
static class Handler extends DefaultHandler {
private SvgSvgElement root;
private Stack<SvgElement> elementStack = new Stack<SvgElement>();
private static final String SVG_NS = "http://www.w3.org/2000/svg";
private static final String XLINK_NS = "http://www.w3.org/1999/xlink";
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if( SVG_NS.equals(uri) ) {
EClass ec = (EClass) SvgPackage.eINSTANCE.getEClassifier("Svg"+Character.toUpperCase(localName.charAt(0))+ localName.substring(1) + "Element");
if( ec != null ) {
SvgElement e = (SvgElement) EcoreUtil.create(ec);
for (int i = 0; i < attributes.getLength(); i++) {
if (SVG_NS.equals(attributes.getURI(i)) || "".equals(attributes.getURI(i))) {
String name = attributes.getLocalName(i).replaceAll("-", "_");
EStructuralFeature f = e.eClass().getEStructuralFeature(name);
if (f != null) {
Object o = EcoreUtil.createFromString((EDataType) f.getEType(), attributes.getValue(i));
e.eSet(f, o);
} else {
System.err.println("Could not find feature '" + name + "' in " + e.eClass().getName());
}
} else if( XLINK_NS.equals(attributes.getURI(i)) ) {
String name = "xlink__" + attributes.getLocalName(i).replaceAll("-", "_");
EStructuralFeature f = e.eClass().getEStructuralFeature(name);
if( f != null ) {
Object o = EcoreUtil.createFromString((EDataType) f.getEType(), attributes.getValue(i));
e.eSet(f, o);
} else {
System.err.println("Could not find feature '" + name + "' in " + e.eClass().getName());
}
}
}
if( elementStack.isEmpty() ) {
root = (SvgSvgElement) e;
} else {
((ContentElement<SvgElement>)elementStack.peek()).getChildren().add(e);
}
elementStack.push(e);
} else {
throw new IllegalStateException("Unable to find element '"+localName+"'");
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if( SVG_NS.equals(uri) && ! localName.equals("svg") ) {
elementStack.pop();
}
}
}
}