/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure 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. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package es.eucm.ead.editor.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.TreeMap; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.stream.StreamResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.InputSource; /** * Utility class that prettifies data.xml files so that they become easier to * compare or read. * * @author mfreire */ public class DataPrettifier { static private Logger logger = LoggerFactory .getLogger(DataPrettifier.class); static final public HashSet<String> translatedAttributes = new HashSet<String>(); static final public String keymapElement = "keyMap"; static final public String keymapEntry = "entry"; /** * Prettify an input into an output. * @param input file; requires two passes (the first one reads the mappings) * @param output file; created in a single pass * @throws IOException */ public static void prettify(File input, File output) throws IOException { TreeMap<String, String> mappings = new TreeMap<String, String>(); // fist pass: build map FileInputStream in = null; try { in = new FileInputStream(input); XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader reader = inputFactory.createXMLStreamReader(in); boolean inMappings = false; while (true) { int event = reader.next(); if (event == XMLStreamConstants.END_DOCUMENT) { reader.close(); break; } if (event == XMLStreamConstants.START_ELEMENT) { if (reader.getLocalName().equals(keymapElement)) { inMappings = true; } if (inMappings && reader.getLocalName().equals(keymapEntry)) { // in mapping list - now we can build our mappings mappings.put(reader.getAttributeValue(0), reader .getAttributeValue(1)); logger.debug("Mapped {} to {}", new Object[] { reader.getAttributeValue(0), reader.getAttributeValue(1) }); } } if (event == XMLStreamConstants.END_ELEMENT && reader.getLocalName().equals(keymapElement)) { inMappings = false; } } } catch (Exception e) { logger.error("Unable to prettify (step 1)", e); } finally { if (in != null) { in.close(); } } // second pass: read while translating with map in = null; try { ByteArrayOutputStream cache = new ByteArrayOutputStream(); in = new FileInputStream(input); XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLStreamReader reader = inputFactory.createXMLStreamReader(in); XMLOutputFactory outputFactory = XMLOutputFactory.newFactory(); logger.debug("Output factory is {}", outputFactory.getClass() .getName()); XMLStreamWriter writer = outputFactory.createXMLStreamWriter(cache); writer.writeStartDocument(); while (true) { int event = reader.next(); if (event == XMLStreamConstants.END_DOCUMENT) { reader.close(); writer.writeEndDocument(); writer.close(); break; } if ((reader.isStartElement() || reader.isEndElement()) && (reader.getLocalName().equals(keymapElement) || reader .getLocalName().equals(keymapEntry))) { // ignore the keymap and its entries continue; } if (event == XMLStreamConstants.START_ELEMENT) { writer.writeStartElement(reader.getLocalName()); logger.debug("Started {}", reader.getLocalName()); // not in mappings list - copy element for (int i = reader.getAttributeCount() - 1; i >= 0; i--) { String name = reader.getAttributeLocalName(i); String value = reader.getAttributeValue(i); if (translatedAttributes.contains(name) && mappings.containsKey(value)) { logger.debug("\t(switch {} ::= {}", new Object[] { value, mappings.get(value) }); value = mappings.get(value); } writer.writeAttribute(name, value); logger.debug("\tattr: {} --> {}", new Object[] { name, value }); } } switch (event) { case XMLStreamConstants.CDATA: writer.writeCData(reader.getText()); break; case XMLStreamConstants.CHARACTERS: case XMLStreamConstants.SPACE: writer.writeCharacters(reader.getText()); break; case XMLStreamConstants.COMMENT: writer.writeComment(reader.getText()); break; case XMLStreamConstants.END_ELEMENT: writer.writeEndElement(); break; default: break; } } // now, prettify it (using mojo from http://stackoverflow.com/a/4472580/15472) Transformer serializer = SAXTransformerFactory.newInstance() .newTransformer(); serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); serializer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2"); //serializer.setOutputProperty("{http://xml.customer.org/xslt}indent-amount", "2"); Source xmlSource = new SAXSource(new InputSource( new ByteArrayInputStream(cache.toByteArray()))); StreamResult res = new StreamResult(new FileOutputStream(output)); serializer.transform(xmlSource, res); } catch (Exception e) { throw new IOException("Unable to prettify (step 2)", e); } finally { if (in != null) { in.close(); } } } public static void main(String[] args) throws Exception { String s1 = args.length > 0 ? args[0] : "/tmp/y1/data.xml"; String s2 = args.length > 1 ? args[1] : "/tmp/y1/d1.xml"; File f1 = new File(s1); File f11 = new File(s2); DataPrettifier.prettify(f1, f11); //File f2 = new File("/tmp/y2/data.xml"); //File f21 = new File("/tmp/y2/d1.xml"); //DataPrettifier.prettify(f2, f21); } }