diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/result/textwriter')
20 files changed, 249 insertions, 263 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java index 2e089274..22bde5be 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,7 +28,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.util.HashMap; import java.util.zip.GZIPOutputStream; import de.lmu.ifi.dbs.elki.logging.Logging; @@ -50,25 +49,15 @@ public class MultipleFilesOutput implements StreamFactory { private static final String GZIP_EXTENSION = ".gz"; /** - * Default stream to write to when no name is supplied. - */ - private PrintStream defaultStream = null; - - /** * Base file name. */ private File basename; /** - * HashMap of open print streams. - */ - private HashMap<String, PrintStream> map = new HashMap<String, PrintStream>(); - - /** * Control gzip compression of output. */ private boolean usegzip = false; - + /** * Logger for debugging. */ @@ -95,20 +84,6 @@ public class MultipleFilesOutput implements StreamFactory { } /** - * Retrieve/open the default output stream. - * - * @return default output stream - * @throws IOException - */ - private PrintStream getDefaultStream() throws IOException { - if(defaultStream != null) { - return defaultStream; - } - defaultStream = newStream("default"); - return defaultStream; - } - - /** * Open a new stream of the given name * * @param name file name (which will be appended to the base name) @@ -117,14 +92,10 @@ public class MultipleFilesOutput implements StreamFactory { */ private PrintStream newStream(String name) throws IOException { if (LOG.isDebuggingFiner()) { - LOG.debugFiner("Requested stream: "+name); - } - PrintStream res = map.get(name); - if(res != null) { - return res; + LOG.debugFiner("Requested stream: " + name); } // Ensure the directory exists: - if(!basename.exists()) { + if (!basename.exists()) { basename.mkdirs(); } String fn = basename.getAbsolutePath() + File.separator + name + EXTENSION; @@ -137,12 +108,11 @@ public class MultipleFilesOutput implements StreamFactory { // wrap into gzip stream. os = new GZIPOutputStream(os); } - res = new PrintStream(os); + PrintStream res = new PrintStream(os); if (LOG.isDebuggingFiner()) { - LOG.debugFiner("Opened new output stream:"+fn); + LOG.debugFiner("Opened new output stream:" + fn); } // cache. - map.put(name, res); return res; } @@ -151,12 +121,14 @@ public class MultipleFilesOutput implements StreamFactory { */ @Override public PrintStream openStream(String filename) throws IOException { - if(filename == null) { - return getDefaultStream(); - } return newStream(filename); } + @Override + public void closeStream(PrintStream stream) { + stream.close(); + } + /** * Get GZIP compression flag. * @@ -174,15 +146,4 @@ public class MultipleFilesOutput implements StreamFactory { protected void setGzipCompression(boolean usegzip) { this.usegzip = usegzip; } - - /** - * Close (and forget) all output streams. - */ - @Override - public synchronized void closeAllStreams() { - for (PrintStream s : map.values()) { - s.close(); - } - map.clear(); - } } diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java index 46472f52..eb2b6170 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -35,32 +35,32 @@ import java.util.zip.GZIPOutputStream; * Class to output all result data to a single stream (e.g. Stdout, single file) * * @author Erich Schubert - * */ public class SingleStreamOutput implements StreamFactory { /** * Output stream */ private PrintStream stream; - + /** * Constructor using stdout. + * * @throws IOException on IO error */ - public SingleStreamOutput() throws IOException { + public SingleStreamOutput() throws IOException { this(FileDescriptor.out); } - + /** * Constructor using stdout * * @param gzip Use gzip compression * @throws IOException on IO error */ - public SingleStreamOutput(boolean gzip) throws IOException { + public SingleStreamOutput(boolean gzip) throws IOException { this(FileDescriptor.out, gzip); } - + /** * Constructor with given file name. * @@ -91,7 +91,7 @@ public class SingleStreamOutput implements StreamFactory { public SingleStreamOutput(FileDescriptor out) throws IOException { this(new FileOutputStream(out)); } - + /** * Constructor with given FileDescriptor * @@ -102,7 +102,7 @@ public class SingleStreamOutput implements StreamFactory { public SingleStreamOutput(FileDescriptor out, boolean gzip) throws IOException { this(new FileOutputStream(out), gzip); } - + /** * Constructor with given FileOutputStream. * @@ -132,18 +132,16 @@ public class SingleStreamOutput implements StreamFactory { /** * Return the objects shared print stream. * - * @param filename ignored filename for SingleStreamOutput, as the name suggests + * @param filename ignored filename for SingleStreamOutput, as the name + * suggests */ @Override public PrintStream openStream(String filename) { return stream; } - /** - * Close output stream. - */ @Override - public void closeAllStreams() { - stream.close(); + public void closeStream(PrintStream stream) { + // Do NOT close. We may still need it. } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java index 0f27b354..431fdc2c 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,22 +29,27 @@ import java.io.PrintStream; /** * Interface for output handling (single file, multiple files, ...) * + * Note: these classes need to be rewritten. Contributions welcome! + * * @author Erich Schubert */ public interface StreamFactory { /** - * Retrieve a print stream for output using the given label. - * Note that multiple labels MAY result in the same PrintStream, so you - * should be printing to only one stream at a time to avoid mixing outputs. + * Retrieve a print stream for output using the given label. Note that + * multiple labels MAY result in the same PrintStream, so you should be + * printing to only one stream at a time to avoid mixing outputs. * * @param label Output label. * @return stream object for the given label * @throws IOException on IO error */ public PrintStream openStream(String label) throws IOException; - + /** - * Close (and forget) all streams the factory has opened. + * Close the given output stream (Note: when writing to a single stream + * output, it will actually not be closed!) + * + * @param stream Stream to close */ - public void closeAllStreams(); -}
\ No newline at end of file + public void closeStream(PrintStream stream); +} diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java index a8de4c46..5b56cee6 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java index e5b05883..0cbc81f2 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -33,6 +33,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import de.lmu.ifi.dbs.elki.data.Cluster; import de.lmu.ifi.dbs.elki.data.Clustering; @@ -62,13 +63,13 @@ import de.lmu.ifi.dbs.elki.result.textwriter.naming.NamingScheme; import de.lmu.ifi.dbs.elki.result.textwriter.naming.SimpleEnumeratingScheme; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterDoubleDoublePair; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectArray; -import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectComment; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectInline; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterPair; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterTextWriteable; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterTriple; import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterVector; import de.lmu.ifi.dbs.elki.utilities.HandlerList; +import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy; import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedParameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter; @@ -78,7 +79,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; import de.lmu.ifi.dbs.elki.utilities.pairs.Triple; /** - * Class to write a result to human-readable text output + * Class to write a result to human-readable text output. + * + * Note: these classes need to be rewritten. Contributions welcome! * * @author Erich Schubert * @@ -96,14 +99,13 @@ public class TextWriter { /** * Hash map for supported classes in writer. */ - public static final HandlerList<TextWriterWriterInterface<?>> writers = new HandlerList<TextWriterWriterInterface<?>>(); + public static final HandlerList<TextWriterWriterInterface<?>> writers = new HandlerList<>(); /** * Add some default handlers */ static { TextWriterObjectInline trivialwriter = new TextWriterObjectInline(); - writers.insertHandler(Object.class, new TextWriterObjectComment()); writers.insertHandler(Pair.class, new TextWriterPair()); writers.insertHandler(DoubleDoublePair.class, new TextWriterDoubleDoublePair()); writers.insertHandler(Triple.class, new TextWriterTriple()); @@ -129,7 +131,7 @@ public class TextWriter { /** * For producing unique filenames. */ - protected Map<String, Object> filenames = new HashMap<String, Object>(); + protected Map<String, Object> filenames = new HashMap<>(); /** * Try to find a unique file name. @@ -139,20 +141,19 @@ public class TextWriter { * @return unique filename */ protected String getFilename(Object result, String filenamepre) { - if(filenamepre == null || filenamepre.length() == 0) { + if (filenamepre == null || filenamepre.length() == 0) { filenamepre = "result"; } int i = 0; - while(true) { + while (true) { String filename; - if(i > 0) { + if (i > 0) { filename = filenamepre + "-" + i; - } - else { + } else { filename = filenamepre; } Object existing = filenames.get(filename); - if(existing == null || existing == result) { + if (existing == null || existing == result) { filenames.put(filename, result); return filename; } @@ -161,102 +162,54 @@ public class TextWriter { } /** - * Writes a header providing information concerning the underlying database - * and the specified parameter-settings. - * - * @param out the print stream where to write - * @param sr the settings to be written into the header - */ - protected void printSettings(TextWriterStream out, List<SettingsResult> sr) { - out.commentPrintSeparator(); - out.commentPrintLn("Settings:"); - - if(sr != null) { - for(SettingsResult settings : sr) { - Object last = null; - for(Pair<Object, Parameter<?>> setting : settings.getSettings()) { - if(setting.first != last && setting.first != null) { - if(last != null) { - out.commentPrintLn(""); - } - String name; - try { - if(setting.first instanceof Class) { - name = ((Class<?>) setting.first).getName(); - } - else { - name = setting.first.getClass().getName(); - } - if(ClassParameter.class.isInstance(setting.first)) { - name = ((ClassParameter<?>) setting.first).getValue().getName(); - } - } - catch(NullPointerException e) { - name = "[null]"; - } - out.commentPrintLn(name); - last = setting.first; - } - String name = setting.second.getOptionID().getName(); - String value = "[unset]"; - try { - if(setting.second.isDefined()) { - value = setting.second.getValueAsString(); - } - } - catch(NullPointerException e) { - value = "[null]"; - } - out.commentPrintLn(SerializedParameterization.OPTION_PREFIX + name + " " + value); - } - } - } - - out.commentPrintSeparator(); - out.flush(); - } - - /** * Stream output. * * @param db Database object * @param r Result class * @param streamOpener output stream manager + * @param filter Filter pattern * @throws UnableToComplyException when no usable results were found * @throws IOException on IO error */ - public void output(Database db, Result r, StreamFactory streamOpener) throws UnableToComplyException, IOException { - List<Relation<?>> ra = new LinkedList<Relation<?>>(); - List<OrderingResult> ro = new LinkedList<OrderingResult>(); - List<Clustering<?>> rc = new LinkedList<Clustering<?>>(); - List<IterableResult<?>> ri = new LinkedList<IterableResult<?>>(); - List<SettingsResult> rs = new LinkedList<SettingsResult>(); - List<Result> otherres = new LinkedList<Result>(); + @SuppressWarnings("unchecked") + public void output(Database db, Result r, StreamFactory streamOpener, Pattern filter) throws UnableToComplyException, IOException { + List<Relation<?>> ra = new LinkedList<>(); + List<OrderingResult> ro = new LinkedList<>(); + List<Clustering<?>> rc = new LinkedList<>(); + List<IterableResult<?>> ri = new LinkedList<>(); + List<SettingsResult> rs = new LinkedList<>(); + List<Result> otherres = new LinkedList<>(); - // collect other results + // Split result objects in different known types: { List<Result> results = ResultUtil.filterResults(r, Result.class); - for(Result res : results) { - if(res instanceof Database) { + for (Result res : results) { + if (filter != null) { + final String nam = res.getShortName(); + if (nam == null || !filter.matcher(nam).find()) { + continue; + } + } + if (res instanceof Database) { continue; } - if(res instanceof Relation) { + if (res instanceof Relation) { ra.add((Relation<?>) res); continue; } - if(res instanceof OrderingResult) { + if (res instanceof OrderingResult) { ro.add((OrderingResult) res); continue; } - if(res instanceof Clustering) { + if (res instanceof Clustering) { rc.add((Clustering<?>) res); continue; } - if(res instanceof IterableResult) { + if (res instanceof IterableResult) { ri.add((IterableResult<?>) res); continue; } - if(res instanceof SettingsResult) { + if (res instanceof SettingsResult) { rs.add((SettingsResult) res); continue; } @@ -264,36 +217,38 @@ public class TextWriter { } } - for(IterableResult<?> rii : ri) { - writeIterableResult(streamOpener, rii, rs); + writeSettingsResult(streamOpener, rs); + + for (IterableResult<?> rii : ri) { + writeIterableResult(streamOpener, rii); } - for(Clustering<?> c : rc) { + for (Clustering<?> c : rc) { NamingScheme naming = new SimpleEnumeratingScheme(c); - for(Cluster<?> clus : c.getAllClusters()) { - writeClusterResult(db, streamOpener, clus, ra, naming, rs); + for (Cluster<?> clus : c.getAllClusters()) { + writeClusterResult(db, streamOpener, (Clustering<Model>) c, (Cluster<Model>) clus, ra, naming); } } - for(OrderingResult ror : ro) { - writeOrderingResult(db, streamOpener, ror, ra, rs); + for (OrderingResult ror : ro) { + writeOrderingResult(db, streamOpener, ror, ra); } - for(Result otherr : otherres) { - writeOtherResult(streamOpener, otherr, rs); + for (Result otherr : otherres) { + writeOtherResult(streamOpener, otherr); } } private void printObject(TextWriterStream out, Database db, final DBIDRef objID, List<Relation<?>> ra) throws UnableToComplyException, IOException { SingleObjectBundle bundle = db.getBundle(objID); // Write database element itself. - for(int i = 0; i < bundle.metaLength(); i++) { + for (int i = 0; i < bundle.metaLength(); i++) { Object obj = bundle.data(i); - if(obj != null) { + if (obj != null) { TextWriterWriterInterface<?> owriter = out.getWriterFor(obj); - if(owriter == null) { + if (owriter == null) { throw new UnableToComplyException("No handler for database object itself: " + obj.getClass().getSimpleName()); } String lbl = null; // TODO: ugly compatibility hack... - if(TypeUtil.DBID.isAssignableFromType(bundle.meta(i))) { + if (TypeUtil.DBID.isAssignableFromType(bundle.meta(i))) { lbl = "ID"; } owriter.writeObject(out, lbl, obj); @@ -302,19 +257,19 @@ public class TextWriter { Collection<Relation<?>> dbrels = db.getRelations(); // print the annotations - if(ra != null) { - for(Relation<?> a : ra) { + if (ra != null) { + for (Relation<?> a : ra) { // Avoid duplicated output. - if(dbrels.contains(a)) { + if (dbrels.contains(a)) { continue; } String label = a.getShortName(); Object value = a.get(objID); - if(value == null) { + if (value == null) { continue; } TextWriterWriterInterface<?> writer = out.getWriterFor(value); - if(writer == null) { + if (writer == null) { // Ignore continue; } @@ -322,56 +277,41 @@ public class TextWriter { } } out.flush(); - out.flush(); - } - - private void writeOtherResult(StreamFactory streamOpener, Result r, List<SettingsResult> rs) throws UnableToComplyException, IOException { - PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName())); - TextWriterStream out = new TextWriterStream(outStream, writers); - TextWriterWriterInterface<?> owriter = out.getWriterFor(r); - if(owriter == null) { - throw new UnableToComplyException("No handler for result class: " + r.getClass().getSimpleName()); - } - // Write settings preamble - printSettings(out, rs); - // Write data - owriter.writeObject(out, null, r); - out.flush(); } - private void writeClusterResult(Database db, StreamFactory streamOpener, Cluster<?> clus, List<Relation<?>> ra, NamingScheme naming, List<SettingsResult> sr) throws FileNotFoundException, UnableToComplyException, IOException { + private void writeClusterResult(Database db, StreamFactory streamOpener, Clustering<Model> clustering, Cluster<Model> clus, List<Relation<?>> ra, NamingScheme naming) throws FileNotFoundException, UnableToComplyException, IOException { String filename = null; - if(naming != null) { + if (naming != null) { filename = filenameFromLabel(naming.getNameFor(clus)); - } - else { + } else { filename = "cluster"; } PrintStream outStream = streamOpener.openStream(getFilename(clus, filename)); TextWriterStream out = new TextWriterStream(outStream, writers); - printSettings(out, sr); // Write cluster information out.commentPrintLn("Cluster: " + naming.getNameFor(clus)); Model model = clus.getModel(); - if(model != ClusterModel.CLUSTER && model != null) { - TextWriterWriterInterface<?> mwri = writers.getHandler(model); - mwri.writeObject(out, null, model); + if (model != ClusterModel.CLUSTER && model != null) { + TextWriterWriterInterface<?> mwri = out.getWriterFor(model); + if (mwri != null) { + mwri.writeObject(out, null, model); + } } - if(clus.getParents().size() > 0) { + if (clustering.getClusterHierarchy().numParents(clus) > 0) { StringBuilder buf = new StringBuilder(); buf.append("Parents:"); - for(Cluster<?> parent : clus.getParents()) { - buf.append(" ").append(naming.getNameFor(parent)); + for (Hierarchy.Iter<Cluster<Model>> iter = clustering.getClusterHierarchy().iterParents(clus); iter.valid(); iter.advance()) { + buf.append(' ').append(naming.getNameFor(iter.get())); } out.commentPrintLn(buf.toString()); } - if(clus.getChildren().size() > 0) { + if (clustering.getClusterHierarchy().numChildren(clus) > 0) { StringBuilder buf = new StringBuilder(); buf.append("Children:"); - for(Cluster<?> child : clus.getChildren()) { - buf.append(" ").append(naming.getNameFor(child)); + for (Hierarchy.Iter<Cluster<Model>> iter = clustering.getClusterHierarchy().iterChildren(clus); iter.valid(); iter.advance()) { + buf.append(' ').append(naming.getNameFor(iter.get())); } out.commentPrintLn(buf.toString()); } @@ -382,48 +322,112 @@ public class TextWriter { for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { printObject(out, db, iter, ra); } - out.commentPrintSeparator(); out.flush(); + streamOpener.closeStream(outStream); } - private void writeIterableResult(StreamFactory streamOpener, IterableResult<?> ri, List<SettingsResult> sr) throws UnableToComplyException, IOException { + private void writeIterableResult(StreamFactory streamOpener, IterableResult<?> ri) throws UnableToComplyException, IOException { PrintStream outStream = streamOpener.openStream(getFilename(ri, ri.getShortName())); TextWriterStream out = new TextWriterStream(outStream, writers); - printSettings(out, sr); // hack to print collectionResult header information - if(ri instanceof CollectionResult<?>) { + if (ri instanceof CollectionResult<?>) { final Collection<String> hdr = ((CollectionResult<?>) ri).getHeader(); - if(hdr != null) { - for(String header : hdr) { + if (hdr != null) { + for (String header : hdr) { out.commentPrintLn(header); } out.flush(); } } Iterator<?> i = ri.iterator(); - while(i.hasNext()) { + while (i.hasNext()) { Object o = i.next(); TextWriterWriterInterface<?> writer = out.getWriterFor(o); - if(writer != null) { + if (writer != null) { writer.writeObject(out, null, o); } out.flush(); } - out.commentPrintSeparator(); out.flush(); + streamOpener.closeStream(outStream); } - private void writeOrderingResult(Database db, StreamFactory streamOpener, OrderingResult or, List<Relation<?>> ra, List<SettingsResult> sr) throws IOException, UnableToComplyException { + private void writeOrderingResult(Database db, StreamFactory streamOpener, OrderingResult or, List<Relation<?>> ra) throws IOException, UnableToComplyException { PrintStream outStream = streamOpener.openStream(getFilename(or, or.getShortName())); TextWriterStream out = new TextWriterStream(outStream, writers); - printSettings(out, sr); for (DBIDIter i = or.iter(or.getDBIDs()).iter(); i.valid(); i.advance()) { printObject(out, db, i, ra); } - out.commentPrintSeparator(); out.flush(); + streamOpener.closeStream(outStream); + } + + private void writeSettingsResult(StreamFactory streamOpener, List<SettingsResult> rs) throws UnableToComplyException, IOException { + if (rs.size() < 1) { + return; + } + SettingsResult r = rs.get(0); + PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName())); + TextWriterStream out = new TextWriterStream(outStream, writers); + // Write settings preamble + out.commentPrintLn("Settings:"); + + if (rs != null) { + for (SettingsResult settings : rs) { + Object last = null; + for (Pair<Object, Parameter<?>> setting : settings.getSettings()) { + if (setting.first != last && setting.first != null) { + if (last != null) { + out.commentPrintLn(""); + } + String name; + try { + if (setting.first instanceof Class) { + name = ((Class<?>) setting.first).getName(); + } else { + name = setting.first.getClass().getName(); + } + if (ClassParameter.class.isInstance(setting.first)) { + name = ((ClassParameter<?>) setting.first).getValue().getName(); + } + } catch (NullPointerException e) { + name = "[null]"; + } + out.commentPrintLn(name); + last = setting.first; + } + String name = setting.second.getOptionID().getName(); + String value = "[unset]"; + try { + if (setting.second.isDefined()) { + value = setting.second.getValueAsString(); + } + } catch (NullPointerException e) { + value = "[null]"; + } + out.commentPrintLn(SerializedParameterization.OPTION_PREFIX + name + " " + value); + } + } + } + out.flush(); + streamOpener.closeStream(outStream); + } + + private void writeOtherResult(StreamFactory streamOpener, Result r) throws UnableToComplyException, IOException { + if (writers.getHandler(r) != null) { + PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName())); + TextWriterStream out = new TextWriterStream(outStream, writers); + TextWriterWriterInterface<?> owriter = out.getWriterFor(r); + if (owriter == null) { + throw new UnableToComplyException("No handler for result class: " + r.getClass().getSimpleName()); + } + // Write data + owriter.writeObject(out, null, r); + out.flush(); + streamOpener.closeStream(outStream); + } } /** diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java index 7c905fb3..542be099 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,14 +25,16 @@ package de.lmu.ifi.dbs.elki.result.textwriter; import java.io.PrintStream; +import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectComment; import de.lmu.ifi.dbs.elki.utilities.HandlerList; /** * Representation of an output stream to a text file. * * @author Erich Schubert - * - * @apiviz.uses de.lmu.ifi.dbs.elki.result.textwriter.StreamFactory oneway - - wraps + * + * @apiviz.uses de.lmu.ifi.dbs.elki.result.textwriter.StreamFactory oneway - - + * wraps */ public class TextWriterStream { /** @@ -66,8 +68,8 @@ public class TextWriterStream { public static final String QUOTE = "# "; /** - * Comment separator line. - * Since this will be printed without {@link #QUOTE} infront, it should be quoted string itself. + * Comment separator line. Since this will be printed without {@link #QUOTE} + * infront, it should be quoted string itself. */ public static final String COMMENTSEP = "###############################################################"; @@ -80,12 +82,17 @@ public class TextWriterStream { * Marker used in text serialization (and re-parsing) */ public static final String SER_MARKER = "Serialization class:"; - + /** * Force incomments flag */ // TODO: solve this more gracefully - private boolean forceincomments = false; + private boolean forceincomments = false; + + /** + * Fallback writer, using toString. + */ + private TextWriterObjectComment fallbackwriter = new TextWriterObjectComment(); /** * Constructor. @@ -99,7 +106,7 @@ public class TextWriterStream { inline = new StringBuilder(); comment = new StringBuilder(); } - + /** * Print an object into the comments section * @@ -122,22 +129,21 @@ public class TextWriterStream { /** * Print a newline into the comments section. */ - public void commentPrintLn() { + public void commentPrintLn() { comment.append(NEWLINE); } - /** - * Print a separator line in the comments section. - */ + /** + * Print a separator line in the comments section. + */ public void commentPrintSeparator() { comment.append(COMMENTSEP + NEWLINE); } /** - * Print data into the inline part of the file. - * Data is sanitized: newlines are replaced with spaces, and text - * containing separators is put in quotes. Quotes and escape characters - * are escaped. + * Print data into the inline part of the file. Data is sanitized: newlines + * are replaced with spaces, and text containing separators is put in quotes. + * Quotes and escape characters are escaped. * * @param o object to print */ @@ -150,19 +156,19 @@ public class TextWriterStream { inline.append(SEPARATOR); } // remove newlines - String str = o.toString().replace(NEWLINE," "); + String str = o.toString().replace(NEWLINE, " "); // escaping - str = str.replace("\\","\\\\").replace("\"","\\\""); + str = str.replace("\\", "\\\\").replace("\"", "\\\""); // when needed, add quotes. if (str.contains(SEPARATOR)) { - str = "\""+str+"\""; + str = "\"" + str + "\""; } inline.append(str); } /** - * Print data into the inline part of the file WITHOUT checking for - * separators (and thus quoting). + * Print data into the inline part of the file WITHOUT checking for separators + * (and thus quoting). * * @param o object to print. */ @@ -175,15 +181,14 @@ public class TextWriterStream { inline.append(SEPARATOR); } // remove newlines - String str = o.toString().replace(NEWLINE," "); + String str = o.toString().replace(NEWLINE, " "); // escaping - str = str.replace("\\","\\\\").replace("\"","\\\""); + str = str.replace("\\", "\\\\").replace("\"", "\\\""); inline.append(str); } /** - * Flush output: - * write inline data, then write comment section. Reset streams. + * Flush output: write inline data, then write comment section. Reset streams. */ public void flush() { if (inline.length() > 0) { @@ -220,13 +225,26 @@ public class TextWriterStream { * @return appropriate write, if available */ public TextWriterWriterInterface<?> getWriterFor(Object o) { - return writers.getHandler(o); + if (o == null) { + return null; + } + TextWriterWriterInterface<?> writer = writers.getHandler(o); + if (writer == null) { + try { + if (o.getClass().getMethod("toString").getDeclaringClass() != Object.class) { + return fallbackwriter; + } + } catch (Exception e) { + return null; + } + } + return writer; } /** - * Restore a vector undoing any normalization that was applied. - * (This class does not support normalization, it is only provided - * by derived classes, which will then have to use generics.) + * Restore a vector undoing any normalization that was applied. (This class + * does not support normalization, it is only provided by derived classes, + * which will then have to use generics.) * * @param <O> Object class * @param v vector to restore diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java index cfaa3373..35fa487f 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java index 4b2c099f..a63d3726 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.naming; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java index c1d0f8e5..dacb342b 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.naming; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -47,12 +47,12 @@ public class SimpleEnumeratingScheme implements NamingScheme { /** * count how often each name occurred so far. */ - private Map<String, Integer> namecount = new HashMap<String, Integer>(); + private Map<String, Integer> namecount = new HashMap<>(); /** * Assigned cluster names. */ - private Map<Cluster<?>, String> names = new HashMap<Cluster<?>, String>(); + private Map<Cluster<?>, String> names = new HashMap<>(); /** * This is the postfix added to the first cluster, which will be removed when diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java index 600e731e..ab4b93d0 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java index 872df780..60f2f534 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java index 4af9d8a4..a9975195 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java index be195648..34d5b419 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java index d4da18f5..d3de4ff3 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java index a621ab4b..28c549d7 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java index 3c1440bc..1705f5cc 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java index 87a3661b..04e56ae5 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -32,7 +32,7 @@ import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterWriterInterface; * * @author Erich Schubert * - * @apiviz.uses TextWriteable + * @apiviz.has TextWriteable */ public class TextWriterTextWriteable extends TextWriterWriterInterface<TextWriteable> { /** diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java index 55dd7106..1efde342 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java index 1452c432..46197e21 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java index c83dd767..da527a67 100644 --- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team |