/* * Copyright (c) 2005–2012 Goethe Center for Scientific Computing - Simulation and Modelling (G-CSC Frankfurt) * Copyright (c) 2012-2015 Goethe Center for Scientific Computing - Computational Neuroscience (G-CSC Frankfurt) * * This file is part of NeuGen. * * NeuGen is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. * * see: http://opensource.org/licenses/LGPL-3.0 * file://path/to/NeuGen/LICENSE * * NeuGen is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * This version of NeuGen includes copyright notice and attribution requirements. * According to the LGPL this information must be displayed even if you modify * the source code of NeuGen. The copyright statement/attribution may not be removed. * * Attribution Requirements: * * If you create derived work you must do the following regarding copyright * notice and author attribution. * * Add an additional notice, stating that you modified NeuGen. In addition * you must cite the publications listed below. A suitable notice might read * "NeuGen source code modified by YourName 2012". * * Note, that these requirements are in full accordance with the LGPL v3 * (see 7. Additional Terms, b). * * Publications: * * S. Wolf, S. Grein, G. Queisser. NeuGen 2.0 - * Employing NeuGen 2.0 to automatically generate realistic * morphologies of hippocapal neurons and neural networks in 3D. * Neuroinformatics, 2013, 11(2), pp. 137-148, doi: 10.1007/s12021-012-9170-1 * * * J. P. Eberhard, A. Wanner, G. Wittum. NeuGen - * A tool for the generation of realistic morphology * of cortical neurons and neural networks in 3D. * Neurocomputing, 70(1-3), pp. 327-343, doi: 10.1016/j.neucom.2006.01.028 * */ package org.neugen.parsers; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import org.apache.log4j.Logger; import org.neugen.datastructures.DataStructureConstants; import org.neugen.datastructures.xml.XMLInt; import org.neugen.datastructures.xml.XMLNode; import org.neugen.datastructures.xml.XMLObject; import org.neugen.datastructures.xml.XMLReal; import org.neugen.datastructures.xml.XMLString; import org.neugen.gui.NeuGenConstants; import org.neugen.utils.Utils; /** * @author Sergei Wolf */ final class XMLRoot { //private List<DefaultXMLNode> children = new ArrayList<DefaultXMLNode>(); private XMLObject root; private String minor; private String major; private String key; public XMLRoot(String key) { this.key = key; root = new XMLObject(key, null, "root_node"); } public void setRoot(XMLObject root) { this.root = root; } public XMLObject getRoot() { return root; } public String getMajor() { return major; } public String getMinor() { return minor; } public void setRootProperties(String major, String minor) { this.major = major; this.minor = minor; } public String getKey() { return key; } } /** * Class to convert the root of the tree. * */ final class XMLRootCoverter implements Converter { private String filePrefix; public XMLRootCoverter() { } public XMLRootCoverter(String filePrefix) { this.filePrefix = filePrefix; } @Override public boolean canConvert(Class clazz) { return clazz.equals(XMLRoot.class); } // write data @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { //System.out.println("root converter"); XMLRoot rootContainer = (XMLRoot) source; writer.addAttribute(DataStructureConstants.MAJOR, rootContainer.getMajor()); writer.addAttribute(DataStructureConstants.MINOR, rootContainer.getMinor()); XMLObject root = rootContainer.getRoot(); for (int k = 0; k < root.getChildrenCount(); k++) { XMLNode xmlNode = root.getChild(k); XMLObject xmlObj = XMLObject.convert(xmlNode); if (xmlObj != null) { context.convertAnother(xmlObj, new XMLObjectConverter()); } else if (xmlNode instanceof XMLString) { context.convertAnother(xmlNode, new XMLStringConverter()); } else if (xmlNode instanceof XMLInt) { context.convertAnother(xmlNode, new XMLIntConverter()); } else if (xmlNode instanceof XMLReal) { context.convertAnother(xmlNode, new XMLRealConverter()); } } } //read data @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { //System.out.println("unmarshal: Root"); XMLRoot rootContainer = new XMLRoot(filePrefix); XMLObject root = rootContainer.getRoot(); String nodeName; while (reader.hasMoreChildren()) { reader.moveDown(); nodeName = reader.getNodeName(); if (nodeName.equals(DataStructureConstants.STRING)) { context.convertAnother(null, XMLString.class, new XMLStringConverter(root)); } else if (nodeName.equals(DataStructureConstants.OBJECT)) { context.convertAnother(null, XMLObject.class, new XMLObjectConverter(root)); } else if (nodeName.equals(DataStructureConstants.REAL)) { context.convertAnother(null, XMLReal.class, new XMLRealConverter(root)); } else if (nodeName.equals(DataStructureConstants.INT)) { context.convertAnother(null, XMLInt.class, new XMLIntConverter(root)); } reader.moveUp(); } rootContainer.setRoot(root); return rootContainer; } } /** * Class to convert XMLOjects. */ final class XMLObjectConverter implements Converter { private XMLObject parent; public XMLObjectConverter() { } public XMLObjectConverter(XMLObject parent) { this.parent = parent; } @Override public boolean canConvert(Class clazz) { return clazz.equals(XMLObject.class); } public void setParent(XMLObject parent) { this.parent = parent; } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { //System.out.println("Object converter"); XMLObject xmlObj = (XMLObject) source; String name = xmlObj.getKey(); String classdesc = xmlObj.getObjectClassName(); //System.out.println("name: " + name + " ,classdesc: " + classdesc); writer.startNode(DataStructureConstants.OBJECT); writer.addAttribute(DataStructureConstants.KEY, name); writer.addAttribute(DataStructureConstants.CLASSDESCRIPTOR, classdesc); for (int i = 0; i < xmlObj.getChildrenCount(); i++) { XMLNode child = xmlObj.getChild(i); XMLObject childObj = XMLObject.convert(child); if (childObj != null) { context.convertAnother(childObj, new XMLObjectConverter()); } else if (child instanceof XMLString) { context.convertAnother(child, new XMLStringConverter()); } else if (child instanceof XMLInt) { context.convertAnother(child, new XMLIntConverter()); } else if (child instanceof XMLReal) { context.convertAnother(child, new XMLRealConverter()); } } //empty tag for libxml parser: <tag></tag>, not </tag>. TODO: DTD allow empty tag for objects if (xmlObj.getChildrenCount() == 0) { writer.setValue("\n"); } writer.endNode(); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { //System.out.println("unmarshal: object converter"); String name = reader.getAttribute(DataStructureConstants.KEY); String classdescriptor = reader.getAttribute(DataStructureConstants.CLASSDESCRIPTOR); XMLObject currentObj = new XMLObject(name, parent, classdescriptor); while (reader.hasMoreChildren()) { reader.moveDown(); name = reader.getNodeName(); if (name.equals(DataStructureConstants.STRING)) { context.convertAnother(null, XMLString.class, new XMLStringConverter(currentObj)); } else if (name.equals(DataStructureConstants.OBJECT)) { context.convertAnother(null, XMLObject.class, new XMLObjectConverter(currentObj)); } else if (name.equals(DataStructureConstants.REAL)) { context.convertAnother(null, XMLReal.class, new XMLRealConverter(currentObj)); } else if (name.equals(DataStructureConstants.INT)) { context.convertAnother(null, XMLInt.class, new XMLIntConverter(currentObj)); } reader.moveUp(); } return currentObj; } } /** * Class to convert string nodes. */ final class XMLStringConverter implements Converter { private XMLObject parent; public XMLStringConverter() { } public XMLStringConverter(XMLObject parent) { this.parent = parent; } @Override public boolean canConvert(Class clazz) { return clazz.equals(XMLString.class); } //write data @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { //System.out.println("string converter"); XMLString strNode = (XMLString) source; writer.startNode(DataStructureConstants.STRING); writer.addAttribute(DataStructureConstants.KEY, strNode.getKey()); //System.out.println("string key " + strNode.getName()); writer.setValue(strNode.value()); writer.endNode(); } //read Data @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { //System.out.println("unmarshal string converter"); String name = reader.getAttribute(DataStructureConstants.KEY); String value = reader.getValue(); //System.out.println("name: " + name + " ,value: " + value); XMLString xmlStr = new XMLString(name, parent, false, value); return xmlStr; } } /** * Class to read/write int xml nodes. */ final class XMLIntConverter implements Converter { private XMLObject parent; public XMLIntConverter() { } public XMLIntConverter(XMLObject parent) { this.parent = parent; } @Override public boolean canConvert(Class clazz) { return clazz.equals(XMLInt.class); } //write data @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { // System.out.println("string converter"); XMLInt strNode = (XMLInt) source; writer.startNode(DataStructureConstants.INT); writer.addAttribute(DataStructureConstants.KEY, strNode.getKey()); writer.setValue(String.valueOf(strNode.value())); writer.endNode(); } //read Data @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { //System.out.println("unmarshal: int converter"); String name = reader.getAttribute(DataStructureConstants.KEY); String value = reader.getValue(); int lVal = (Integer.valueOf(value)).intValue(); // System.out.println("name: " + name + " ,value: " + value); XMLInt xmlInt = new XMLInt(name, parent, false, lVal); return xmlInt; } } /** * Class to convert real nodes. */ final class XMLRealConverter implements Converter { private XMLObject parent; public XMLRealConverter(XMLObject parent) { this.parent = parent; } public XMLRealConverter() { } //write data @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { // System.out.println("string converter"); XMLReal strNode = (XMLReal) source; writer.startNode(DataStructureConstants.REAL); writer.addAttribute(DataStructureConstants.KEY, strNode.getKey()); writer.setValue(String.valueOf(strNode.value())); writer.endNode(); } //read Data @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { //System.out.println("unmarshal: real converter"); String name = reader.getAttribute(DataStructureConstants.KEY); String value = reader.getValue(); float dVal = (Float.valueOf(value)).floatValue(); // System.out.println("name: " + name + " ,value: " + value); XMLReal xmlReal = new XMLReal(name, parent, false, dVal); return xmlReal; } @Override public boolean canConvert(Class clazz) { return clazz.equals(XMLReal.class); } } public final class NeuGenConfigStreamer { private final static Logger logger = Logger.getLogger(NeuGenConfigStreamer.class.getName()); private String absProjectPath; public NeuGenConfigStreamer(String absPath) { absProjectPath = absPath; } public NeuGenConfigStreamer() { super(); } public XMLObject streamIn(File file) throws FileNotFoundException, IOException { String fileName = file.getPath(); String filePrefix = Utils.getPrefix(file); XStream xstream = new XStream(); xstream.registerConverter(new XMLRootCoverter(filePrefix)); xstream.alias(DataStructureConstants.XED, XMLRoot.class); XMLRoot rootContainer = (XMLRoot) xstream.fromXML(new FileInputStream(fileName)); XMLObject root = rootContainer.getRoot(); return root; } // writes tree with xstream public void streamOut(XMLObject root, File file) throws IOException { XStream xstream = new XStream(); xstream.registerConverter(new XMLRootCoverter()); xstream.registerConverter(new XMLObjectConverter()); xstream.registerConverter(new XMLStringConverter()); xstream.registerConverter(new XMLIntConverter()); xstream.registerConverter(new XMLRealConverter()); xstream.alias(DataStructureConstants.XED, XMLRoot.class); //write dtd.txt //File fileIn = new File(fileName); try { String absDTDPath = absProjectPath + System.getProperty("file.separator") + NeuGenConstants.DTD_FNAME; if (absProjectPath == null) { absDTDPath = NeuGenConstants.DTD_FNAME; } logger.info("path of DTD.txt: " + absDTDPath); FileInputStream in = new FileInputStream(absDTDPath); FileOutputStream out = new FileOutputStream(file); byte[] buf = new byte[4096]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } out.close(); in.close(); } catch (IOException e) { logger.error(e, e); } FileWriter writer = new FileWriter(file, true); writer.write("\n"); //serialize String filePrefix = Utils.getPrefix(file); XMLRoot rootContainer = new XMLRoot(filePrefix); rootContainer.setRootProperties("1", "0"); rootContainer.setRoot(root); xstream.toXML(rootContainer, writer); } public static void main(String args[]) throws IOException { //NGStreamer test = new NGStreamer(); //read from file //DefaultXMLObject root = test.streamIn("Param.neu"); //write to file //test.streamOut(root, "testTarget.xml"); } }