Package com.cburch.logisim.file

Source Code of com.cburch.logisim.file.XmlWriter

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.file;

import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.cburch.draw.model.AbstractCanvasObject;
import com.cburch.logisim.LogisimVersion;
import com.cburch.logisim.Main;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeDefaultProvider;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.tools.Library;
import com.cburch.logisim.tools.Tool;
import com.cburch.logisim.util.InputEventUtil;

class XmlWriter {
    static void write(LogisimFile file, OutputStream out, LibraryLoader loader)
            throws ParserConfigurationException,
                TransformerConfigurationException, TransformerException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        Document doc = docBuilder.newDocument();
        XmlWriter context = new XmlWriter(file, doc, loader);
        context.fromLogisimFile();

        TransformerFactory tfFactory = TransformerFactory.newInstance();
        try {
            tfFactory.setAttribute("indent-number", Integer.valueOf(2));
        } catch (IllegalArgumentException e) { }
        Transformer tf = tfFactory.newTransformer();
        tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        tf.setOutputProperty(OutputKeys.INDENT, "yes");
        try {
            tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
                    "2");
        } catch (IllegalArgumentException e) { }

        Source src = new DOMSource(doc);
        Result dest = new StreamResult(out);
        tf.transform(src, dest);
    }

    private LogisimFile file;
    private Document doc;
    private LibraryLoader loader;
    private HashMap<Library,String> libs = new HashMap<Library,String>();

    private XmlWriter(LogisimFile file, Document doc, LibraryLoader loader) {
        this.file = file;
        this.doc = doc;
        this.loader = loader;
    }

    Element fromLogisimFile() {
        Element ret = doc.createElement("project");
        doc.appendChild(ret);
        ret.appendChild(doc.createTextNode("\nThis file is intended to be "
                + "loaded by Logisim (http://www.cburch.com/logisim/).\n"));
        ret.setAttribute("version", "1.0");
        ret.setAttribute("source", Main.VERSION_NAME);

        for (Library lib : file.getLibraries()) {
            Element elt = fromLibrary(lib);
            if (elt != null) {
                ret.appendChild(elt);
            }

        }

        if (file.getMainCircuit() != null) {
            Element mainElt = doc.createElement("main");
            mainElt.setAttribute("name", file.getMainCircuit().getName());
            ret.appendChild(mainElt);
        }

        ret.appendChild(fromOptions());
        ret.appendChild(fromMouseMappings());
        ret.appendChild(fromToolbarData());

        for (Circuit circ : file.getCircuits()) {
            ret.appendChild(fromCircuit(circ));
        }
        return ret;
    }

    Element fromLibrary(Library lib) {
        Element ret = doc.createElement("lib");
        if (libs.containsKey(lib)) {
            return null;
        }

        String name = "" + libs.size();
        String desc = loader.getDescriptor(lib);
        if (desc == null) {
            loader.showError("library location unknown: "
                + lib.getName());
            return null;
        }
        libs.put(lib, name);
        ret.setAttribute("name", name);
        ret.setAttribute("desc", desc);
        for (Tool t : lib.getTools()) {
            AttributeSet attrs = t.getAttributeSet();
            if (attrs != null) {
                Element toAdd = doc.createElement("tool");
                toAdd.setAttribute("name", t.getName());
                addAttributeSetContent(toAdd, attrs, t);
                if (toAdd.getChildNodes().getLength() > 0) {
                    ret.appendChild(toAdd);
                }
            }
        }
        return ret;
    }

    Element fromOptions() {
        Element elt = doc.createElement("options");
        addAttributeSetContent(elt, file.getOptions().getAttributeSet(), null);
        return elt;
    }

    Element fromMouseMappings() {
        Element elt = doc.createElement("mappings");
        MouseMappings map = file.getOptions().getMouseMappings();
        for (Map.Entry<Integer,Tool> entry : map.getMappings().entrySet()) {
            Integer mods = entry.getKey();
            Tool tool = entry.getValue();
            Element toolElt = fromTool(tool);
            String mapValue = InputEventUtil.toString(mods.intValue());
            toolElt.setAttribute("map", mapValue);
            elt.appendChild(toolElt);
        }
        return elt;
    }

    Element fromToolbarData() {
        Element elt = doc.createElement("toolbar");
        ToolbarData toolbar = file.getOptions().getToolbarData();
        for (Tool tool : toolbar.getContents()) {
            if (tool == null) {
                elt.appendChild(doc.createElement("sep"));
            } else {
                elt.appendChild(fromTool(tool));
            }
        }
        return elt;
    }

    Element fromTool(Tool tool) {
        Library lib = findLibrary(tool);
        String lib_name;
        if (lib == null) {
            loader.showError(String.format("tool `%s' not found",
                tool.getDisplayName()));
            return null;
        } else if (lib == file) {
            lib_name = null;
        } else {
            lib_name = libs.get(lib);
            if (lib_name == null) {
                loader.showError("unknown library within file");
                return null;
            }
        }

        Element elt = doc.createElement("tool");
        if (lib_name != null) {
            elt.setAttribute("lib", lib_name);
        }

        elt.setAttribute("name", tool.getName());
        addAttributeSetContent(elt, tool.getAttributeSet(), tool);
        return elt;
    }

    Element fromCircuit(Circuit circuit) {
        Element ret = doc.createElement("circuit");
        ret.setAttribute("name", circuit.getName());
        addAttributeSetContent(ret, circuit.getStaticAttributes(), null);
        if (!circuit.getAppearance().isDefaultAppearance()) {
            Element appear = doc.createElement("appear");
            for (Object o : circuit.getAppearance().getObjectsFromBottom()) {
                if (o instanceof AbstractCanvasObject) {
                    /*Element elt = ((AbstractCanvasObject) o).toSvgElement(doc);
                    if (elt != null) {
                        appear.appendChild(elt);
                    }*/
                }
            }
            ret.appendChild(appear);
        }
        for (Wire w : circuit.getWires()) {
            ret.appendChild(fromWire(w));
        }
        for (Component comp : circuit.getNonWires()) {
            Element elt = fromComponent(comp);
            if (elt != null) {
                ret.appendChild(elt);
            }

        }
        return ret;
    }

    Element fromComponent(Component comp) {
        ComponentFactory source = comp.getFactory();
        Library lib = findLibrary(source);
        String lib_name;
        if (lib == null) {
            loader.showError(source.getName() + " component not found");
            return null;
        } else if (lib == file) {
            lib_name = null;
        } else {
            lib_name = libs.get(lib);
            if (lib_name == null) {
                loader.showError("unknown library within file");
                return null;
            }
        }

        Element ret = doc.createElement("comp");
        if (lib_name != null) {
            ret.setAttribute("lib", lib_name);
        }

        ret.setAttribute("name", source.getName());
        ret.setAttribute("loc", comp.getLocation().toString());
        addAttributeSetContent(ret, comp.getAttributeSet(), comp.getFactory());
        return ret;
    }

    Element fromWire(Wire w) {
        Element ret = doc.createElement("wire");
        ret.setAttribute("from", w.getEnd0().toString());
        ret.setAttribute("to", w.getEnd1().toString());
        return ret;
    }

    void addAttributeSetContent(Element elt, AttributeSet attrs,
            AttributeDefaultProvider source) {
        if (attrs == null) {
            return;
        }

        LogisimVersion ver = Main.VERSION;
        if (source != null && source.isAllDefaultValues(attrs, ver)) {
            return;
        }

        for (Attribute<?> attrBase : attrs.getAttributes()) {
            @SuppressWarnings("unchecked")
            Attribute<Object> attr = (Attribute<Object>) attrBase;
            Object val = attrs.getValue(attr);
            if (attrs.isToSave(attr) && val != null) {
                Object dflt = source == null ? null : source.getDefaultAttributeValue(attr, ver);
                if (dflt == null || !dflt.equals(val)) {
                    Element a = doc.createElement("a");
                    a.setAttribute("name", attr.getName());
                    String value = attr.toStandardString(val);
                    if (value.indexOf("\n") >= 0) {
                        a.appendChild(doc.createTextNode(value));
                    } else {
                        a.setAttribute("val", attr.toStandardString(val));
                    }
                    elt.appendChild(a);
                }
            }
        }
    }

    Library findLibrary(Tool tool) {
        if (libraryContains(file, tool)) {
            return file;
        }
        for (Library lib : file.getLibraries()) {
            if (libraryContains(lib, tool)) {
                return lib;
            }

        }
        return null;
    }

    Library findLibrary(ComponentFactory source) {
        if (file.contains(source)) {
            return file;
        }
        for (Library lib : file.getLibraries()) {
            if (lib.contains(source)) {
                return lib;
            }

        }
        return null;
    }

    boolean libraryContains(Library lib, Tool query) {
        for (Tool tool : lib.getTools()) {
            if (tool.sharesSource(query)) {
                return true;
            }

        }
        return false;
    }
}
TOP

Related Classes of com.cburch.logisim.file.XmlWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.