Java tutorial
/* * TURNUS, the co-exploration framework * * Copyright (C) 2014 EPFL SCI STI MM * * This file is part of TURNUS. * * TURNUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TURNUS 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with TURNUS. If not, see <http://www.gnu.org/licenses/>. * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining it * with Eclipse (or a modified version of Eclipse or an Eclipse plugin or * an Eclipse library), containing parts covered by the terms of the * Eclipse Public License (EPL), the licensors of this Program grant you * additional permission to convey the resulting work. Corresponding Source * for a non-source form of such a combination shall include the source code * for the parts of Eclipse libraries used as well as that of the covered work. * */ package co.turnus.trace.io; import static co.turnus.trace.io.XmlTraceMarkup.ATTRIBUTE; import static co.turnus.trace.io.XmlTraceMarkup.ATTRIBUTE_NAME; import static co.turnus.trace.io.XmlTraceMarkup.COUNT; import static co.turnus.trace.io.XmlTraceMarkup.DEPENDENCY; import static co.turnus.trace.io.XmlTraceMarkup.DEPENDENCY_KIND; import static co.turnus.trace.io.XmlTraceMarkup.DEPENDENCY_SOURCE; import static co.turnus.trace.io.XmlTraceMarkup.DEPENDENCY_TARGET; import static co.turnus.trace.io.XmlTraceMarkup.DIRECTION; import static co.turnus.trace.io.XmlTraceMarkup.ENTRY; import static co.turnus.trace.io.XmlTraceMarkup.GUARD; import static co.turnus.trace.io.XmlTraceMarkup.PORT; import static co.turnus.trace.io.XmlTraceMarkup.SOURCE_PORT; import static co.turnus.trace.io.XmlTraceMarkup.STEP; import static co.turnus.trace.io.XmlTraceMarkup.STEP_ACTION; import static co.turnus.trace.io.XmlTraceMarkup.STEP_ACTOR; import static co.turnus.trace.io.XmlTraceMarkup.STEP_ACTOR_CLASS; import static co.turnus.trace.io.XmlTraceMarkup.STEP_FIRING; import static co.turnus.trace.io.XmlTraceMarkup.TARGET_PORT; import static co.turnus.trace.io.XmlTraceMarkup.TRACE; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_BOOLEAN; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_INTEGER; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_LIST; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_MAP; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_REAL; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_SET; import static co.turnus.trace.io.XmlTraceMarkup.TYPE_STRING; import static co.turnus.trace.io.XmlTraceMarkup.VALUE; import static co.turnus.trace.io.XmlTraceMarkup.VARIABLE; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import javanet.staxutils.IndentingXMLStreamWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.commons.compress.compressors.CompressorStreamFactory; import co.turnus.TurnusExtension; import co.turnus.TurnusRuntimeException; import co.turnus.generic.Attributable; import co.turnus.util.TurnusUtils; import co.turnus.trace.Dependency; import co.turnus.trace.Dependency.Kind; import co.turnus.trace.Step; import com.google.common.collect.Iterables; public class XmlTraceStreamWriter { private XMLStreamWriter writer; private OutputStream stream; private boolean compressedXml; public XmlTraceStreamWriter(File file) { switch (TurnusUtils.getExtension(file)) { case TurnusExtension.TRACE_COMPRESSED: compressedXml = true; break; case TurnusExtension.TRACE: compressedXml = false; break; default: throw new TurnusRuntimeException("Trace file writer: unsupported file extension"); } try { stream = new FileOutputStream(file); if (compressedXml) { stream = new CompressorStreamFactory().createCompressorOutputStream(CompressorStreamFactory.GZIP, stream); } stream = new BufferedOutputStream(stream); } catch (Exception e) { throw new TurnusRuntimeException("Error opening the trace file output stream", e.getCause()); } } public void close() { try { writeEndDocument(); writer.flush(); writer.close(); stream.close(); } catch (Exception e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } private boolean hasEmptyAttributes(Attributable attributable) { return Iterables.isEmpty(attributable.getKeyAttributes()); } public void open() { try { XMLOutputFactory factory = XMLOutputFactory.newInstance(); writer = factory.createXMLStreamWriter(stream); if (!compressedXml) { writer = new IndentingXMLStreamWriter(writer); } writeStartDocument(); } catch (XMLStreamException e) { throw new TurnusRuntimeException("Error opening the trace stream writer", e.getCause()); } } public void write(Dependency dep) { try { boolean noAttributes = hasEmptyAttributes(dep); if (noAttributes) { writer.writeEmptyElement(DEPENDENCY); } else { writer.writeStartElement(DEPENDENCY); } writer.writeAttribute(DEPENDENCY_SOURCE, Long.toString(dep.getSource().getID())); writer.writeAttribute(DEPENDENCY_TARGET, Long.toString(dep.getTarget().getID())); Kind kind = dep.getKind(); writer.writeAttribute(DEPENDENCY_KIND, dep.getKind().literal()); switch (kind) { case FSM: { break; } case TOKENS: { writer.writeAttribute(SOURCE_PORT, dep.getSourcePort()); writer.writeAttribute(TARGET_PORT, dep.getTargetPort()); writer.writeAttribute(COUNT, Integer.toString(dep.getCount())); break; } case STATEVAR: { writer.writeAttribute(VARIABLE, dep.getVariable()); writer.writeAttribute(DIRECTION, dep.getDirection().literal()); break; } case PORT: { writer.writeAttribute(PORT, dep.getPort()); writer.writeAttribute(DIRECTION, dep.getDirection().literal()); break; } case GUARD: { writer.writeAttribute(GUARD, dep.getGuard()); writer.writeAttribute(DIRECTION, dep.getDirection().literal()); break; } default: throw new TurnusRuntimeException("Unsupported Dependence kind " + dep); } if (!noAttributes) { writeAttributes(dep); writer.writeEndElement(); } } catch (XMLStreamException e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } public void write(Step step) { try { boolean noAttributes = hasEmptyAttributes(step); if (noAttributes) { writer.writeEmptyElement(STEP); } else { writer.writeStartElement(STEP); } writer.writeAttribute(STEP_FIRING, Long.toString(step.getID())); writer.writeAttribute(STEP_ACTOR, step.getActor()); writer.writeAttribute(STEP_ACTION, step.getAction()); writer.writeAttribute(STEP_ACTOR_CLASS, step.getActorClass()); if (!noAttributes) { writeAttributes(step); writer.writeEndElement(); } } catch (XMLStreamException e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } public void writeAttribute(String name, Object value) { try { writer.writeStartElement(ATTRIBUTE); writer.writeAttribute(ATTRIBUTE_NAME, name); writeObject(value); writer.writeEndElement(); } catch (XMLStreamException e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } public void writeAttributes(Attributable attributable) { for (String key : attributable.getKeyAttributes()) { writeAttribute(key, attributable.getAttribute(key)); } } private void writeEndDocument() { try { // </trace> writer.writeEndElement(); // close the document writer.writeEndDocument(); } catch (Exception e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } @SuppressWarnings("rawtypes") private void writeObject(Object v) { try { if (v instanceof Boolean) { writer.writeEmptyElement(TYPE_BOOLEAN); writer.writeAttribute(VALUE, Boolean.toString((Boolean) v)); } else if (v instanceof Byte || v instanceof Short || v instanceof Integer) { writer.writeEmptyElement(TYPE_INTEGER); writer.writeAttribute(VALUE, Integer.toString((Integer) v)); } else if (v instanceof Long) { writer.writeEmptyElement(TYPE_INTEGER); writer.writeAttribute(VALUE, Long.toString((Long) v)); } else if (v instanceof Float) { writer.writeEmptyElement(TYPE_REAL); writer.writeAttribute(VALUE, Float.toString((Float) v)); } else if (v instanceof Double) { writer.writeEmptyElement(TYPE_REAL); writer.writeAttribute(VALUE, Double.toString((Double) v)); } else if (v instanceof String) { writer.writeEmptyElement(TYPE_STRING); writer.writeAttribute(VALUE, (String) v); } else if (v instanceof List) { writer.writeStartElement(TYPE_LIST); for (Object o : (List) v) { writeObject(o); } writer.writeEndElement(); } else if (v instanceof Set) { writer.writeStartElement(TYPE_SET); for (Object o : (Set) v) { writeObject(o); } writer.writeEndElement(); } else if (v instanceof Map) { writer.writeStartElement(TYPE_MAP); for (Object k : ((Map) v).keySet()) { writer.writeStartElement(ENTRY); writeObject(k); writeObject(((Map) v).get(k)); writer.writeEndElement(); } writer.writeEndElement(); } } catch (XMLStreamException e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } private void writeStartDocument() { try { String date = new SimpleDateFormat("yyyy.MM.dd, HH:mm:ss").format(new Date()); writer.writeStartDocument(); writer.writeComment("Trace exported the " + date); writer.writeStartElement(TRACE); } catch (XMLStreamException e) { throw new TurnusRuntimeException("Trace Writer Error: " + e.getLocalizedMessage(), e.getCause()); } } }