/* * RapidMiner * * Copyright (C) 2001-2011 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.OutputStream; import java.util.LinkedList; import java.util.List; import java.util.zip.GZIPInputStream; import com.rapidminer.operator.ports.OutputPort; import com.rapidminer.operator.ports.ProcessingStep; import com.rapidminer.tools.LogService; import com.rapidminer.tools.LoggingHandler; import com.rapidminer.tools.XMLSerialization; /** * This is an abstract superclass for all IOObject. It provides basic implementations for all * methods of the IOObject interface. In addition, it also provides static methods which can be * used for reading IOObjects from XML strings and input streams / files containing the XML * serialization. * * @author Ingo Mierswa */ public abstract class AbstractIOObject implements IOObject { private static final long serialVersionUID = 7131412868947165460L; /** The source of this IOObect. Might be null. */ private String source = null; /** The current working operator. */ private transient LoggingHandler loggingHandler; private transient LinkedList<ProcessingStep> processingHistory = new LinkedList<ProcessingStep>(); /** Sets the source of this IOObject. */ public void setSource(String sourceName) { this.source = sourceName; } /** Returns the source of this IOObject (might return null if the source is unknown). */ public String getSource() { return source; } @Override public void appendOperatorToHistory(Operator operator, OutputPort port) { if (processingHistory == null) { processingHistory = new LinkedList<ProcessingStep>(); if (operator.getProcess() != null) processingHistory.add(new ProcessingStep(operator, port)); } ProcessingStep newStep = new ProcessingStep(operator, port); if (operator.getProcess() != null && (processingHistory.isEmpty() || !processingHistory.getLast().equals(newStep))) { processingHistory.add(newStep); } } @Override public List<ProcessingStep> getProcessingHistory() { if (processingHistory == null) processingHistory = new LinkedList<ProcessingStep>(); return processingHistory; } /** Gets the logging associated with the operator currently working on this * IOObject or the global log service if no operator was set. */ public LoggingHandler getLog() { if (this.loggingHandler != null) { return this.loggingHandler; } else { return LogService.getGlobal(); } } /** Sets the current working operator, i.e. the operator which is currently * working on this IOObject. This might be used for example for logging. */ public void setLoggingHandler(LoggingHandler loggingHandler) { this.loggingHandler = loggingHandler; } /** * Returns not a copy but the very same object. This is ok for IOObjects * which cannot be altered after creation. However, IOObjects which might be * changed (e.g. {@link com.rapidminer.example.ExampleSet}s) should * overwrite this method and return a proper copy. */ public IOObject copy() { return this; } /** Initializes the writing of this object. This method is invoked before * the actual writing is performed. The default implementation does nothing. * * This method should also be used for clean up * processes which should be performed before the actual writing is done. For * example, models might decide to keep the example set information directly * after learning (e.g. for visualization reasons) but not to write them down. * Please note that all fields will be written into files unless they are set * to null in this method or they are marked as transient. */ protected void initWriting() {} /** Just serializes this object with help of a {@link XMLSerialization}. * Initializes {@link #initWriting()} before the actual writing is performed. */ public final void write(OutputStream out) throws IOException { initWriting(); XMLSerialization.getXMLSerialization().writeXML(this, out); } /** Deserializes an IOObect from the given XML stream. * TODO: Make private and remove deprecated annotation * @throws IOException if any IO error occurs. * @throws IllegalStateException if {@link XMLSerialization#init(ClassLoader)} has never been called. * @deprecated Use {@link #read(InputStreamProvider, String)} to be able to read all formats (xml zipped/not zipped and binary) */ @Deprecated public static IOObject read(InputStream in) throws IOException { final XMLSerialization serializer = XMLSerialization.getXMLSerialization(); if (serializer == null) throw new IllegalStateException("XMLSerialization not initialized, please invoke XMLSerialization.init(ClassLoader) before using this method."); return (IOObject)serializer.fromXML(in); } /** This interface is needed since we must reset the stream in case of an exception. */ public static interface InputStreamProvider { public InputStream getInputStream() throws IOException; } public static IOObject read(final File file) throws IOException { return read(new InputStreamProvider() { @Override public InputStream getInputStream() throws IOException { return new FileInputStream(file); } }); } public static IOObject read(final byte[] buf) throws IOException { return read(new InputStreamProvider() { @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(buf); } }); } public static IOObject read(InputStreamProvider inProvider) throws IOException { ObjectInputStream objectIn = null; try { // try if the object was written as a serializable object objectIn = new ObjectInputStream(inProvider.getInputStream()); IOObject object = (IOObject)objectIn.readObject(); objectIn.close(); // done in finally return object; } catch (Exception e) { // if not serialized, then try the usual serialization (xml) InputStream in = null; try { in = new GZIPInputStream(inProvider.getInputStream()); } catch (IOException e1) { // do nothing and simply use the given input stream in = inProvider.getInputStream(); } try { return read(in); } finally { if (in != null) { try { in.close(); } catch (IOException e1) { } } } } finally { if (objectIn != null) try { objectIn.close(); } catch (IOException e) { } } } }