diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/application')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java | 638 | ||||
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java | 93 |
2 files changed, 136 insertions, 595 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java index c09c74eb..373960a5 100644 --- a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java +++ b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java @@ -24,559 +24,63 @@ package de.lmu.ifi.dbs.elki.application; */ import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStreamWriter; -import java.net.URL; -import java.util.LinkedList; -import java.util.Random; -import java.util.regex.Pattern; +import java.util.List; -import javax.xml.XMLConstants; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorMain; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterface; +import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterfaceDynamic; import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorStatic; import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.GammaDistribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.NormalDistribution; -import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.UniformDistribution; +import de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection; +import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; +import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; -import de.lmu.ifi.dbs.elki.utilities.xml.XMLNodeIterator; /** * Generate a data set based on a specified model (using an XML specification) * * @author Erich Schubert * - * @apiviz.composedOf GeneratorMain - * @apiviz.has GeneratorSingleCluster oneway - - creates - * @apiviz.has GeneratorStatic oneway - - creates + * @apiviz.composedOf GeneratorXMLDatabaseConnection */ public class GeneratorXMLSpec extends AbstractApplication { - // TODO: move XML parsing into data package. - /** * The logger for this class. */ private static final Logging logger = Logging.getLogger(GeneratorXMLSpec.class); /** - * A pattern defining whitespace. - */ - public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+"); - - /** - * Parameter to give the configuration file - */ - public static final OptionID CONFIGFILE_ID = OptionID.getOrCreateOptionID("bymodel.spec", "The generator specification file."); - - /** - * Parameter to give the configuration file - */ - public static final OptionID RANDOMSEED_ID = OptionID.getOrCreateOptionID("bymodel.randomseed", "The random generator seed."); - - /** - * Parameter to give the configuration file - */ - public static final OptionID SIZE_SCALE_ID = OptionID.getOrCreateOptionID("bymodel.sizescale", "Factor for scaling the specified cluster sizes."); - - /** - * File name of the generators XML Schema file. + * Line separator for output */ - private static final String GENERATOR_SCHEMA_FILE = GeneratorXMLSpec.class.getPackage().getName().replace('.', '/') + '/' + "GeneratorByModel.xsd"; + public final static String LINE_SEPARATOR = System.getProperty("line.separator"); /** - * The configuration file. - */ - File specfile; - - /** - * Parameter for scaling the cluster sizes. - */ - double sizescale = 1.0; - - /** - * The actual generator class - */ - public GeneratorMain gen = new GeneratorMain(); - - /** - * Random generator used for initializing cluster generators. - */ - private Random clusterRandom = null; - - /** - * Set testAgainstModel flag + * Output file. */ - private boolean testAgainstModel = true; + private File outputFile; /** - * Output file. + * The original data source. */ - private File outputFile; + private GeneratorXMLDatabaseConnection generator; /** * Constructor. * * @param verbose Verbose flag * @param output Output file - * @param specfile Specification file - * @param sizescale Size scaling - * @param clusterRandom Random number generator + * @param generator GeneratorXMLDatabaseConnection */ - public GeneratorXMLSpec(boolean verbose, File output, File specfile, double sizescale, Random clusterRandom) { + public GeneratorXMLSpec(boolean verbose, File output, GeneratorXMLDatabaseConnection generator) { super(verbose); this.outputFile = output; - this.specfile = specfile; - this.sizescale = sizescale; - this.clusterRandom = clusterRandom; - if(this.clusterRandom == null) { - this.clusterRandom = new Random(); - } - } - - /** - * Load the XML configuration file. - * - * @throws UnableToComplyException - */ - private void loadXMLSpecification(File specfile) throws UnableToComplyException { - try { - InputStream in = new FileInputStream(specfile); - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); - URL url = ClassLoader.getSystemResource(GENERATOR_SCHEMA_FILE); - if(url != null) { - try { - Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(url); - dbf.setSchema(schema); - dbf.setIgnoringElementContentWhitespace(true); - } - catch(Exception e) { - logger.warning("Could not set up XML Schema validation for speciciation file."); - } - } - else { - logger.warning("Could not set up XML Schema validation for speciciation file."); - } - Document doc = dbf.newDocumentBuilder().parse(in); - Node root = doc.getDocumentElement(); - if(root.getNodeName() == "dataset") { - processElementDataset(root); - } - else { - throw new UnableToComplyException("Experiment specification has incorrect document element: " + root.getNodeName()); - } - } - catch(FileNotFoundException e) { - throw new UnableToComplyException("Can't open specification file.", e); - } - catch(SAXException e) { - throw new UnableToComplyException("Error parsing specification file.", e); - } - catch(IOException e) { - throw new UnableToComplyException("IO Exception loading specification file.", e); - } - catch(ParserConfigurationException e) { - throw new UnableToComplyException("Parser Configuration Error", e); - } - } - - /** - * Process a 'dataset' Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementDataset(Node cur) throws UnableToComplyException { - // *** get parameters - String seedstr = ((Element) cur).getAttribute("random-seed"); - if(seedstr != null && seedstr != "") { - clusterRandom = new Random((int) (Integer.valueOf(seedstr) * sizescale)); - } - String testmod = ((Element) cur).getAttribute("test-model"); - if(testmod != null && testmod != "") { - testAgainstModel = (Integer.valueOf(testmod) != 0); - } - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "cluster") { - processElementCluster(child); - } - else if(child.getNodeName() == "static") { - processElementStatic(child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'cluster' Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementCluster(Node cur) throws UnableToComplyException { - int size = -1; - double overweight = 1.0; - - String sizestr = ((Element) cur).getAttribute("size"); - if(sizestr != null && sizestr != "") { - size = (int) (Integer.valueOf(sizestr) * sizescale); - } - - String name = ((Element) cur).getAttribute("name"); - - String dcostr = ((Element) cur).getAttribute("density-correction"); - if(dcostr != null && dcostr != "") { - overweight = Double.valueOf(dcostr); - } - - if(size < 0) { - throw new UnableToComplyException("No valid cluster size given in specification file."); - } - if(name == null || name == "") { - throw new UnableToComplyException("No cluster name given in specification file."); - } - - // *** add new cluster object - Random newRand = new Random(clusterRandom.nextLong()); - GeneratorSingleCluster cluster = new GeneratorSingleCluster(name, size, overweight, newRand); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "uniform") { - processElementUniform(cluster, child); - } - else if(child.getNodeName() == "normal") { - processElementNormal(cluster, child); - } - else if(child.getNodeName() == "gamma") { - processElementGamma(cluster, child); - } - else if(child.getNodeName() == "rotate") { - processElementRotate(cluster, child); - } - else if(child.getNodeName() == "translate") { - processElementTranslate(cluster, child); - } - else if(child.getNodeName() == "clip") { - processElementClipping(cluster, child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - - gen.addCluster(cluster); - } - - /** - * Process a 'uniform' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementUniform(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double min = 0.0; - double max = 1.0; - - String minstr = ((Element) cur).getAttribute("min"); - if(minstr != null && minstr != "") { - min = Double.valueOf(minstr); - } - String maxstr = ((Element) cur).getAttribute("max"); - if(maxstr != null && maxstr != "") { - max = Double.valueOf(maxstr); - } - - // *** new uniform generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new UniformDistribution(min, max, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'normal' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementNormal(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double mean = 0.0; - double stddev = 1.0; - String meanstr = ((Element) cur).getAttribute("mean"); - if(meanstr != null && meanstr != "") { - mean = Double.valueOf(meanstr); - } - String stddevstr = ((Element) cur).getAttribute("stddev"); - if(stddevstr != null && stddevstr != "") { - stddev = Double.valueOf(stddevstr); - } - - // *** New normal distribution generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new NormalDistribution(mean, stddev, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'gamma' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementGamma(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - double k = 1.0; - double theta = 1.0; - String kstr = ((Element) cur).getAttribute("k"); - if(kstr != null && kstr != "") { - k = Double.valueOf(kstr); - } - String thetastr = ((Element) cur).getAttribute("theta"); - if(thetastr != null && thetastr != "") { - theta = Double.valueOf(thetastr); - } - - // *** New normal distribution generator - Random random = cluster.getNewRandomGenerator(); - Distribution generator = new GammaDistribution(k, theta, random); - cluster.addGenerator(generator); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'rotate' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementRotate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - int axis1 = 0; - int axis2 = 0; - double angle = 0.0; - - String a1str = ((Element) cur).getAttribute("axis1"); - if(a1str != null && a1str != "") { - axis1 = Integer.valueOf(a1str); - } - String a2str = ((Element) cur).getAttribute("axis2"); - if(a2str != null && a2str != "") { - axis2 = Integer.valueOf(a2str); - } - String anstr = ((Element) cur).getAttribute("angle"); - if(anstr != null && anstr != "") { - angle = Double.valueOf(anstr); - } - if(axis1 <= 0 || axis1 > cluster.getDim()) { - throw new UnableToComplyException("Invalid axis1 number given in specification file."); - } - if(axis1 <= 0 || axis1 > cluster.getDim()) { - throw new UnableToComplyException("Invalid axis2 number given in specification file."); - } - if(axis1 == axis2) { - throw new UnableToComplyException("Invalid axis numbers given in specification file."); - } - - // Add rotation to cluster. - cluster.addRotation(axis1 - 1, axis2 - 1, Math.toRadians(angle)); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'translate' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementTranslate(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - Vector offset = null; - String vstr = ((Element) cur).getAttribute("vector"); - if(vstr != null && vstr != "") { - offset = parseVector(vstr); - } - if(offset == null) { - throw new UnableToComplyException("No translation vector given."); - } - - // *** add new translation - cluster.addTranslation(offset); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'clipping' Element in the XML stream. - * - * @param cluster - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementClipping(GeneratorSingleCluster cluster, Node cur) throws UnableToComplyException { - Vector cmin = null; - Vector cmax = null; - - String minstr = ((Element) cur).getAttribute("min"); - if(minstr != null && minstr != "") { - cmin = parseVector(minstr); - } - String maxstr = ((Element) cur).getAttribute("max"); - if(maxstr != null && maxstr != "") { - cmax = parseVector(maxstr); - } - if(cmin == null || cmax == null) { - throw new UnableToComplyException("No or incomplete clipping vectors given."); - } - - // *** set clipping - cluster.setClipping(cmin, cmax); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Process a 'static' cluster Element in the XML stream. - * - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementStatic(Node cur) throws UnableToComplyException { - String name = ((Element) cur).getAttribute("name"); - if(name == null) { - throw new UnableToComplyException("No cluster name given in specification file."); - } - - LinkedList<Vector> points = new LinkedList<Vector>(); - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeName() == "point") { - processElementPoint(points, child); - } - else if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - // *** add new cluster object - GeneratorStatic cluster = new GeneratorStatic(name, points); - - gen.addCluster(cluster); - if(logger.isVerbose()) { - logger.verbose("Loaded cluster " + cluster.name + " from specification."); - } - } - - /** - * Parse a 'point' element (point vector for a static cluster) - * - * @param points current list of points (to append to) - * @param cur Current document nod - * @throws UnableToComplyException - */ - private void processElementPoint(LinkedList<Vector> points, Node cur) throws UnableToComplyException { - Vector point = null; - String vstr = ((Element) cur).getAttribute("vector"); - if(vstr != null && vstr != "") { - point = parseVector(vstr); - } - if(point == null) { - throw new UnableToComplyException("No translation vector given."); - } - - // *** add new point - points.add(point); - - // TODO: check for unknown attributes. - for(Node child : new XMLNodeIterator(cur.getFirstChild())) { - if(child.getNodeType() == Node.ELEMENT_NODE) { - logger.warning("Unknown element in XML specification file: " + child.getNodeName()); - } - } - } - - /** - * Parse a string into a vector. - * - * TODO: move this into utility package? - * - * @param s String to parse - * @return Vector - * @throws UnableToComplyException - */ - private Vector parseVector(String s) throws UnableToComplyException { - String[] entries = WHITESPACE_PATTERN.split(s); - double[] d = new double[entries.length]; - for(int i = 0; i < entries.length; i++) { - try { - d[i] = Double.valueOf(entries[i]); - } - catch(NumberFormatException e) { - throw new UnableToComplyException("Could not parse vector."); - } - } - return new Vector(d); + this.generator = generator; } /** @@ -584,15 +88,7 @@ public class GeneratorXMLSpec extends AbstractApplication { */ @Override public void run() throws UnableToComplyException { - if(logger.isVerbose()) { - logger.verbose("Loading specification ..."); - } - loadXMLSpecification(specfile); - if(logger.isVerbose()) { - logger.verbose("Generating clusters ..."); - } - gen.setTestAgainstModel(testAgainstModel); - gen.generate(); + MultipleObjectsBundle data = generator.loadData(); if(logger.isVerbose()) { logger.verbose("Writing output ..."); } @@ -604,7 +100,7 @@ public class GeneratorXMLSpec extends AbstractApplication { } OutputStreamWriter outStream = new FileWriter(outputFile, true); - gen.writeClusters(outStream); + writeClusters(outStream, data); outStream.flush(); outStream.close(); @@ -621,6 +117,68 @@ public class GeneratorXMLSpec extends AbstractApplication { } /** + * Write the resulting clusters to an output stream. + * + * @param outStream output stream + * @param data Generated data + * @throws IOException thrown on write errors + */ + public void writeClusters(OutputStreamWriter outStream, MultipleObjectsBundle data) throws IOException { + List<GeneratorInterface> clusters = generator.gen.getGenerators(); + // compute global discard values + int totalsize = 0; + int totaldisc = 0; + assert (clusters.size() > 0); + for(GeneratorInterface curclus : clusters) { + totalsize = totalsize + curclus.getSize(); + if(curclus instanceof GeneratorSingleCluster) { + totaldisc = totaldisc + ((GeneratorSingleCluster) curclus).getDiscarded(); + } + } + double globdens = (double) (totalsize + totaldisc) / totalsize; + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Number of clusters: " + clusters.size() + LINE_SEPARATOR); + for(GeneratorInterface curclus : clusters) { + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Cluster: " + curclus.getName() + LINE_SEPARATOR); + outStream.write("########################################################" + LINE_SEPARATOR); + outStream.write("## Size: " + curclus.getSize() + LINE_SEPARATOR); + if(curclus instanceof GeneratorSingleCluster) { + GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; + Vector cmin = cursclus.getClipmin(); + Vector cmax = cursclus.getClipmax(); + if(cmin != null && cmax != null) { + outStream.write("## Clipping: " + cmin.toString() + " - " + cmax.toString() + LINE_SEPARATOR); + } + outStream.write("## Density correction factor: " + cursclus.getDensityCorrection() + LINE_SEPARATOR); + outStream.write("## Generators:" + LINE_SEPARATOR); + for(Distribution gen : cursclus.getAxes()) { + outStream.write("## " + gen.toString() + LINE_SEPARATOR); + } + if(cursclus.getTrans() != null && cursclus.getTrans().getTransformation() != null) { + outStream.write("## Affine transformation matrix:" + LINE_SEPARATOR); + outStream.write(FormatUtil.format(cursclus.getTrans().getTransformation(), "## ") + LINE_SEPARATOR); + } + } + if(curclus instanceof GeneratorInterfaceDynamic) { + GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus; + outStream.write("## Discards: " + cursclus.getDiscarded() + " Retries left: " + cursclus.getRetries() + LINE_SEPARATOR); + double corf = /* cursclus.overweight */(double) (cursclus.getSize() + cursclus.getDiscarded()) / cursclus.getSize() / globdens; + outStream.write("## Density correction factor estimation: " + corf + LINE_SEPARATOR); + + } + outStream.write("########################################################" + LINE_SEPARATOR); + for(Vector p : curclus.getPoints()) { + for(int i = 0; i < p.getRowDimensionality(); i++) { + outStream.write(p.get(i) + " "); + } + outStream.write(curclus.getName()); + outStream.write(LINE_SEPARATOR); + } + } + } + + /** * Parameterization class. * * @author Erich Schubert @@ -629,50 +187,26 @@ public class GeneratorXMLSpec extends AbstractApplication { */ public static class Parameterizer extends AbstractApplication.Parameterizer { /** - * The configuration file. - */ - File specfile = null; - - /** - * Parameter for scaling the cluster sizes. - */ - double sizescale = 1.0; - - /** - * Random generator used for initializing cluster generators. + * Output file. */ - private Random clusterRandom = null; + private File outputFile = null; /** - * Output file. + * Data generator */ - private File outputFile = null; + private GeneratorXMLDatabaseConnection generator = null; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); // Output file outputFile = getParameterOutputFile(config, "the file to write the generated data set into, if the file already exists, the generated points will be appended to this file."); - // Specification file - final FileParameter cfgparam = new FileParameter(CONFIGFILE_ID, FileParameter.FileType.INPUT_FILE); - if(config.grab(cfgparam)) { - specfile = cfgparam.getValue(); - } - // Cluster size scaling - final DoubleParameter scalepar = new DoubleParameter(SIZE_SCALE_ID, 1.0); - if(config.grab(scalepar)) { - sizescale = scalepar.getValue(); - } - // Random generator - final IntParameter seedpar = new IntParameter(RANDOMSEED_ID, true); - if(config.grab(seedpar)) { - clusterRandom = new Random(seedpar.getValue()); - } + generator = config.tryInstantiate(GeneratorXMLDatabaseConnection.class); } @Override protected GeneratorXMLSpec makeInstance() { - return new GeneratorXMLSpec(verbose, outputFile, specfile, sizescale, clusterRandom); + return new GeneratorXMLSpec(verbose, outputFile, generator); } } diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java index b5bb516e..05af4b4d 100644 --- a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java +++ b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java @@ -196,39 +196,40 @@ public class DocumentParameters { public void run() { // Try a V3 style parameterizer first. Parameterizer par = ClassGenericsUtil.getParameterizer(cls); - if (par != null) { + if(par != null) { par.configure(track); - return; } - try { - Object instance = ClassGenericsUtil.tryInstantiate(Object.class, cls, track); - for(Pair<Object, Parameter<?, ?>> pair : track.getAllParameters()) { - if(pair.first == null) { - pair.first = instance; + else { + try { + ClassGenericsUtil.tryInstantiate(Object.class, cls, track); + } + catch(java.lang.NoSuchMethodException e) { + logger.warning("Could not instantiate class " + cls.getName() + " - no appropriate constructor or parameterizer found."); + } + catch(java.lang.reflect.InvocationTargetException e) { + if(e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + if(e.getCause() instanceof Error) { + throw (Error) e.getCause(); } - options.add(pair); + throw new RuntimeException(e.getCause()); } - } - catch(java.lang.NoSuchMethodException e) { - logger.warning("Could not instantiate class "+cls.getName()+" - no appropriate constructor or parameterizer found."); - } - catch(java.lang.reflect.InvocationTargetException e) { - if(e.getCause() instanceof RuntimeException) { - throw (RuntimeException) e.getCause(); + catch(RuntimeException e) { + throw e; } - if(e.getCause() instanceof Error) { - throw (Error) e.getCause(); + catch(Exception e) { + throw new RuntimeException(e); + } + catch(java.lang.Error e) { + throw new RuntimeException(e); } - throw new RuntimeException(e.getCause()); - } - catch(RuntimeException e) { - throw e; - } - catch(Exception e) { - throw new RuntimeException(e); } - catch(java.lang.Error e) { - throw new RuntimeException(e); + for(Pair<Object, Parameter<?, ?>> pair : track.getAllParameters()) { + if(pair.first == null) { + pair.first = cls; + } + options.add(pair); } } }, null); @@ -296,7 +297,7 @@ public class DocumentParameters { boolean inlist = false; if(byo != null) { for(Pair<Parameter<?, ?>, Class<?>> pair : byo) { - if(pair.second == c) { + if(pair.second.equals(c)) { inlist = true; break; } @@ -306,9 +307,6 @@ public class DocumentParameters { byopt.add(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c)); } } - if(!byopt.contains(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c))) { - byopt.add(o.getOptionID(), new Pair<Parameter<?, ?>, Class<?>>(o, c)); - } } es.shutdownNow(); logger.debug("byClass: " + byclass.size() + " byOpt: " + byopt.size()); @@ -435,7 +433,7 @@ public class DocumentParameters { elemdd.appendChild(elemp); // class restriction? if(opt instanceof ClassParameter<?>) { - appendClassRestriction(htmldoc, (ClassParameter<?>) opt, elemdd); + appendClassRestriction(htmldoc, ((ClassParameter<?>) opt).getRestrictionClass(), elemdd); } // default value? completions? appendDefaultValueIfSet(htmldoc, opt, elemdd); @@ -509,7 +507,7 @@ public class DocumentParameters { Collections.sort(opts, new SortByOption()); for(OptionID oid : opts) { - Parameter<?, ?> firstopt = byopt.get(oid).get(0).getFirst(); + final Parameter<?, ?> firstopt = byopt.get(oid).get(0).getFirst(); // DT = definition term Element optdt = htmldoc.createElement(HTMLUtil.HTML_DT_TAG); // Anchor for references @@ -533,8 +531,17 @@ public class DocumentParameters { optdd.appendChild(elemp); } // class restriction? + Class<?> superclass = null; if(firstopt instanceof ClassParameter<?>) { - appendClassRestriction(htmldoc, (ClassParameter<?>) firstopt, optdd); + // Find superclass heuristically + superclass = ((ClassParameter<?>) firstopt).getRestrictionClass(); + for (Pair<Parameter<?, ?>, Class<?>> clinst : byopt.get(oid)) { + ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst(); + if (!cls.getRestrictionClass().equals(superclass) && cls.getRestrictionClass().isAssignableFrom(superclass)) { + superclass = cls.getRestrictionClass(); + } + } + appendClassRestriction(htmldoc, superclass, optdd); } // default value? appendDefaultValueIfSet(htmldoc, firstopt, optdd); @@ -566,8 +573,8 @@ public class DocumentParameters { ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst(); if(cls.getRestrictionClass() != null) { // TODO: if it is null, it could still be different! - if(!cls.getRestrictionClass().equals(((ClassParameter<?>) firstopt).getRestrictionClass())) { - appendClassRestriction(htmldoc, cls, classli); + if(!cls.getRestrictionClass().equals(superclass)) { + appendClassRestriction(htmldoc, cls.getRestrictionClass(), classli); } } else { @@ -599,22 +606,22 @@ public class DocumentParameters { p.appendChild(defa); } - private static void appendClassRestriction(Document htmldoc, ClassParameter<?> opt, Element elemdd) { - if(opt.getRestrictionClass() == null) { - logger.warning("No restriction class for Parameter " + opt.getName()); + private static void appendClassRestriction(Document htmldoc, Class<?> restriction, Element elemdd) { + if(restriction == null) { + logger.warning("No restriction class!"); return; } Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG); p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION)); - if(opt.getRestrictionClass().isInterface()) { + if(restriction.isInterface()) { p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_IMPLEMENTING)); } else { p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_EXTENDING)); } Element defa = htmldoc.createElement(HTMLUtil.HTML_A_TAG); - defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(opt.getRestrictionClass().getName())); - defa.setTextContent(opt.getRestrictionClass().getName()); + defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(restriction.getName())); + defa.setTextContent(restriction.getName()); p.appendChild(defa); elemdd.appendChild(p); } @@ -645,8 +652,8 @@ public class DocumentParameters { elemdd.appendChild(ul); } // Report when not in properties file. - if (Properties.ELKI_PROPERTIES.getProperty(opt.getRestrictionClass().getName()).length == 0) { - logger.warning(opt.getRestrictionClass().getName()+" not in properties. No autocompletion available in release GUI."); + if(Properties.ELKI_PROPERTIES.getProperty(opt.getRestrictionClass().getName()).length == 0) { + logger.warning(opt.getRestrictionClass().getName() + " not in properties. No autocompletion available in release GUI."); } } } |