package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
Copyright (C) 2011
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 .
*/
import java.util.Collection;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.InternalParameterizationErrors;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GlobalParameterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
/**
* Abstract class with shared code for parameterization handling.
*
* @author Erich Schubert
*/
public abstract class AbstractParameterization implements Parameterization {
// TODO: refactor "tryInstantiate" even in a higher class?
/**
* Errors
*/
java.util.Vector errors = new java.util.Vector();
/**
* The logger of the class.
*/
private final static Logging logger = Logging.getLogger(AbstractParameterization.class);
@Override
public Collection getErrors() {
return errors;
}
@Override
public boolean hasErrors() {
return errors.size() > 0;
}
@Override
public void reportError(ParameterException e) {
errors.add(e);
}
/**
* Log any error that has accumulated.
*/
public synchronized void logAndClearReportedErrors() {
for(ParameterException e : getErrors()) {
if(logger.isDebugging()) {
logger.warning(e.getMessage(), e);
}
else {
logger.warning(e.getMessage());
}
}
clearErrors();
}
/**
* Clear errors.
*/
public synchronized void clearErrors() {
// Do NOT use errors.clear(), since we might have an error report
// referencing the collection!
errors = new java.util.Vector();
}
/**
* Fail on errors, log any error that had occurred.
*
* @throws RuntimeException if any error has occurred.
*/
// TODO: make a multi-exception class?
public void failOnErrors() throws RuntimeException {
final int numerror = getErrors().size();
if(numerror > 0) {
logAndClearReportedErrors();
throw new RuntimeException(numerror + " errors occurred during parameterization.");
}
}
/**
* Report the internal parameterization errors to another parameterization
*
* @param config Other parameterization
*/
public synchronized void reportInternalParameterizationErrors(Parameterization config) {
final int numerror = getErrors().size();
if(numerror > 0) {
config.reportError(new InternalParameterizationErrors(numerror + " internal (re-) parameterization errors prevented execution.", getErrors()));
this.clearErrors();
}
}
@Override
public final boolean grab(Parameter, ?> opt) {
if(opt.isDefined()) {
logger.warning("Option " + opt.getName() + " is already set!");
}
try {
if(setValueForOption(opt)) {
return true;
}
// Try default value instead.
if(opt.tryDefaultValue()) {
return true;
}
// No value available.
return false;
}
catch(ParameterException e) {
reportError(e);
return false;
}
}
/**
* Perform the actual parameter assignment.
*
* @param opt Option to be set
* @return Success code (value available)
* @throws ParameterException on assignment errors.
*/
@Override
public abstract boolean setValueForOption(Parameter, ?> opt) throws ParameterException;
/** Upon destruction, report any errors that weren't handled yet. */
@Override
public void finalize() {
failOnErrors();
}
@Override
public boolean checkConstraint(GlobalParameterConstraint constraint) {
try {
constraint.test();
}
catch(ParameterException e) {
reportError(e);
return false;
}
return true;
}
@Override
public C tryInstantiate(Class r, Class> c) {
try {
return ClassGenericsUtil.tryInstantiate(r, c, this);
}
catch(Exception e) {
logger.exception(e);
reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
return null;
}
}
@Override
public C tryInstantiate(Class c) {
try {
return ClassGenericsUtil.tryInstantiate(c, c, this);
}
catch(Exception e) {
logger.exception(e);
reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
return null;
}
}
}