/** *

Parameter handling and option descriptions.

* *
    *
  1. Option ID: Any parameter must have an {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID OptionID}.
    * These are Singleton objects to uniquely identify the option. They should be "public static".
    * The OptionID specifies the parameter name and a generic description. *

    * * Example code: *

    {@code  // Defining option IDs
     * public static final OptionID DISTANCE_FUNCTION_ID =
     *   OptionID.getOrCreateOptionID(
     *     "algorithm.distancefunction",
     *     "Distance function to determine the distance between database objects."
     *   ); 
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm AbstractDistanceBasedAlgorithm}.) *
  2. * *
  3. Parameter Object: To obtain a value, you must use a * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.AbstractParameter Parameter} * object.
    * Parameter objects handle parsing of values into the desired type, and various * subclasses for common types are provided. It is not desirable to subclass these types * too much, since a UI should be able to offer content assistance for input. *

    * * Parameters often have types and constraints attached to them, and may be flagged optional * or have a default value. Note that a parameter with a default value is by definition optional, * so there is no constructor with both a default value and the optional flag. *

    * * Due to restrictions imposed by Java Generics, * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ListParameter ListParameter} based * types do not have the full set of constructors, since a List of Constraints and a List of * Default values produce the same signature. In such a signature conflict situation, you can use * a full constructor either by giving {@code null} as constraints (and a list of default values) or * by giving constraints and setting optional to {@code false}. *

    * * Notice the difference between an * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter ObjectParameter} and a * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter ClassParameter}. The first is * meant to carry a single object (which as fallback can be initialized with a class, resulting * in a new object of that class), the second is meant for a "object factory" use. *

    * * Example code: *

    {@code  // Defining Parameters
     * final ObjectParameter> DISTANCE_FUNCTION_PARAM =
     *   new ObjectParameter>(
     *     DISTANCE_FUNCTION_ID,
     *     DistanceFunction.class,
     *     EuclideanDistanceFunction.class
     *   ); 
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm DistanceBasedAlgorithm}.) *
  4. * *
  5. Initialization: Initialization happens in the constructor, which must have the * signature {@code Class(Parameterization config)} or using a static method {@code parameterize(Parameterization config)}.
    * The {@code config} object manages configuration data, whichever source it is coming from * (e.g. command line, XML, lists, ...) *

    * * The {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization Parameterization} * class offers the method * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization#grab grab} * , which returns {@code true} when the parameter value is defined and satisfies the given constraints. *

    * * Initialization should happen in a delayed-fail way. Failure is managed by the Parameterization object, * and not failing immediately allows for reporting all configuration errors (and all options) in a single * run. As such, when reporting a configuration error, you should not throw the error, but * instead call {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization#reportError reportError} * and leave error handling to the Parameterization class. Note that this method will return * eventually, so you might need to use try-catch-report blocks. *

    * * The static {@code parameterize(Parameterization config)} factory method may return {@code null} * when Parameterization failed. Otherwise, it must return an instance of the given class or a * subclass. Example: LPNormDistanceFunction returns an instance of EuclideanDistance for p=2. *

    * * When writing constructors, try to make error handling as local as possible, to report as many errors * at once as possible. *

    * * Example code: *

    {@code  // Getting parameters
     * protected DistanceBasedAlgorithm(Parameterization config) {
     *   super(config);
     *   if (config.grab(DISTANCE_FUNCTION_PARAM)) {
     *     distanceFunction = DISTANCE_FUNCTION_PARAM.instantiateClass(config);
     *   }
     * }
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm DistanceBasedAlgorithm}.) *

    * *

    {@code  // Using flags
     * protected AbstractApplication(Parameterization config) {
     *   super(config);
     *   if(config.grab(VERBOSE_FLAG)) {
     *     verbose = VERBOSE_FLAG.getValue();
     *   }
     * }
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.application.AbstractApplication AbstractApplication}.) *

    * * The {@code if config.grab} statement ensures that the parameter was set. Note that the configuration * manager is passed on to the child instance. *

  6. * *
  7. Compound conditionals: Sometimes, more than one parameter value is required. * However, {@code config.grab(...) && config.grab(...)} is not working as intended, since * a negative results in the first config.grab statement will prevent the evaluation of the second. * Instead, the following code should be used: *
    {@code // Compound parameter dependency
     * config.grab(FIRST_OPTION);
     * config.grab(SECOND_OPTION);
     * if (FIRST_OPTION.isDefined() && SECOND_OPTION.isDefined()) {
     *   // Now we have validated values for both available.
     * }
     * }
    *
  8. * *
  9. Global Constraints: additional global constraints can be added using * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization#checkConstraint checkConstraint} *

    * * Example code: *

    {@code  // Global constraints
     * config.grab(NORMALIZATION_PARAM);
     * config.grab(NORMALIZATION_UNDO_FLAG);
     * GlobalParameterConstraint gpc =
     *   new ParameterFlagGlobalConstraint, Class>>(
     *     NORMALIZATION_PARAM, null,
     *     NORMALIZATION_UNDO_FLAG, true);
     * if (config.checkConstraint(gpc)) {
     *   // Code that depends on the constraints being satisfied.
     * }
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.KDDTask KDDTask}.) *

    * * TODO: Much of the constraint functionality can be solved much easier by direct Java code and * {@code reportError}. Unless the constraints can be used by a GUI for input assistance, we should * consider replacing them with direct code. *

  10. * *
  11. Error reporting: *
    {@code  // Proper dealing with errors
     * try {
     *   // code that might fail with an IO exception
     * } except(IOException e) {
     *   config.reportError(new WrongParameterValueException(...));
     * }
     * // process remaining parameters, to report additional errors. 
     * }
    *
  12. * *
  13. Command line parameterization: * Command line parameters are handled by the class * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedParameterization SerializedParameterization} * which provided convenient constructors from String arrays: *
    {@code  // Use command line parameters
     * SerializedParameterization params = new SerializedParameterization(args);
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.application.AbstractApplication AbstractApplication}.) *
  14. * *
  15. Internal Parameterization: * Often one algorithm will need to call another algorithm, with specific parameters. * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization ListParameterization} * offers convenience function for this that do not require String serialization. *
    {@code  // Internal parameterization
     * ListParameterization parameters = new ListParameterization();
     *
     * parameters.addParameter(PCAFilteredRunner.PCA_EIGENPAIR_FILTER, FirstNEigenPairFilter.class);
     * parameters.addParameter(FirstNEigenPairFilter.EIGENPAIR_FILTER_N, correlationDimension);
     * }
    * (This example is from {@link de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ERiC ERiC}.) *
  16. * *
  17. Combined parameterization: * Sometimes, an algorithm will pre-define some parameters, while additional parameters can be * supplied by the user. This can be done using a chained parameterization as provided by * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ChainedParameterization ChainedParameterization} *
    {@code  // predefine some parameters
     * ListParameterization opticsParameters = new ListParameterization();
     * opticsParameters.addParameter(OPTICS.DISTANCE_FUNCTION_ID, DiSHDistanceFunction.class);
     * // ... more parameters ...
     * ChainedParameterization chain = new ChainedParameterization(opticsParameters, config);
     * chain.errorsTo(opticsParameters);
     * optics = new OPTICS(chain);
     * opticsParameters.failOnErrors();
     * }
    * (This example code is from {@link de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.DiSH DiSH}.) *

    * Note how error handling is performed by explicity specification of an error target and by * calling failOnErrors() at the end of parameterization. *

    * * (Note: the current implementation of this approach may be inadequate for XML or Tree based * parameterization, due to tree inconsistencies. This is an open TODO issue) *

  18. * *
  19. Tracking parameterizations:: * Sometimes (e.g. for help functions, re-running, configuration templates etc.) it is * required to track all parameters an (sub-) algorithm consumed. This can be done using * a {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParameters TrackParameters} * wrapper around the configuration. The wrapper does not have own configuration items or error * recording, instead everything is forwarded to the inner configuration. It does however keep track * of consumed values, that can then be used for re-parameterization of an Algorithm. *
    {@code  // config is an existing parameterization
     * TrackParameters trackpar = new TrackParameters(config);
     * Database tmpDB = PARTITION_DB_PARAM.instantiateClass(trackpar);
     * Collection> dbpars = trackpar.getGivenParameters();
     * }
    * (This is an example from {@link de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.COPAC COPAC}.) *
  20. * *
  21. Advanced tracking: * When parameterizing a sub-algorithm, it can be useful to provide some parameters that should * not be tracked (because the actual values will only be available afterwards). This is possible * by using a ChainedParameterization of untracked and tracked values. *

    * * Example: *

    {@code  // config is an existing parameterization
     * ListParameterization myconfig = new ListParameterization();
     * // dummy values for input and output
     * myconfig.addParameter(INPUT_ID, "/dev/null");
     * myconfig.addParameter(OUTPUT_ID, "/dev/null");      
     * TrackParameters track = new TrackParameters(config);
     * ChainedParameterization chain = new ChainedParameterization(myconfig, track);
     * wrapper = WRAPPER_PARAM.instantiateClass(chain);
     * }
    *
  22. *
* *

For documentation, the classes should also be annotated with * {@link de.lmu.ifi.dbs.elki.utilities.documentation.Title} * {@link de.lmu.ifi.dbs.elki.utilities.documentation.Description} and * {@link de.lmu.ifi.dbs.elki.utilities.documentation.Reference} (where possible).

* * @apiviz.excludeSubtypes de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable */ /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team 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 . */ package de.lmu.ifi.dbs.elki.utilities.optionhandling;