/* * 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.meta; import java.util.LinkedList; import java.util.List; import com.rapidminer.operator.ExecutionUnit; import com.rapidminer.operator.OperatorChain; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.Value; import com.rapidminer.operator.ports.InputPorts; import com.rapidminer.operator.ports.MultiInputPortPairExtender; import com.rapidminer.operator.ports.MultiOutputPortPairExtender; import com.rapidminer.operator.ports.OutputPorts; import com.rapidminer.operator.ports.Port; import com.rapidminer.operator.ports.metadata.SubprocessTransformRule; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeString; /** * <p>This operator performs the inner operators and delivers the result of the * inner operators. If any error occurs during this subprocess, this error * will be neglected and this operator simply will return no additional * input.</p> * * <p>Please use this operator with care since it will also cover errors which * are not expected by the analyst. In combination with a process branch, however, * it can be used to handle exceptions in the analysis process (i.e. expected errors). * </p> * * @author Ingo Mierswa, Marius Helf */ public class ExceptionHandling extends OperatorChain { public static final String PARAMETER_EXCEPTION_MACRO = "exception_macro"; private boolean withoutError = true; private Exception exception; private static final int TRY_SUBPROCESS = 0; private static final int CATCH_SUBPROCESS = 1; private final MultiOutputPortPairExtender inputExtender = new MultiOutputPortPairExtender("in", getInputPorts(), new OutputPorts[] { getSubprocess(0).getInnerSources(), getSubprocess(1).getInnerSources() }); private final MultiInputPortPairExtender outputExtender = new MultiInputPortPairExtender("out", getOutputPorts(), new InputPorts[] { getSubprocess(0).getInnerSinks(), getSubprocess(1).getInnerSinks() }); public ExceptionHandling(OperatorDescription description) { super(description, "Try", "Catch"); inputExtender.start(); getTransformer().addRule(inputExtender.makePassThroughRule()); getTransformer().addRule(new SubprocessTransformRule(getSubprocess(0))); getTransformer().addRule(new SubprocessTransformRule(getSubprocess(1))); getTransformer().addRule(outputExtender.makePassThroughRule()); outputExtender.start(); addValue(new Value("success", "Indicates whether the execution was successful") { @Override public Object getValue() { return withoutError; } @Override public boolean isNominal() { return true; } }); addValue(new Value("exception", "The exception that occured during execution.") { @Override public Object getValue() { return exception; } @Override public boolean isNominal() { return true; } }); } @Override public void doWork() throws OperatorException { withoutError = true; exception = null; ExecutionUnit tryProcess = getSubprocess(TRY_SUBPROCESS); ExecutionUnit catchProcess = getSubprocess(CATCH_SUBPROCESS); tryProcess.getInnerSinks().clear(Port.CLEAR_DATA); catchProcess.getInnerSinks().clear(Port.CLEAR_DATA); inputExtender.passDataThrough(); try { tryProcess.execute(); outputExtender.passDataThrough(TRY_SUBPROCESS); } catch (Exception e) { logWarning("Error occurred and will be neglected by " + getName() + ": " + e.getMessage()); if (isParameterSet(PARAMETER_EXCEPTION_MACRO)) { getProcess().getMacroHandler().addMacro(getParameterAsString(PARAMETER_EXCEPTION_MACRO), e.getMessage()); } withoutError = false; this.exception = e; catchProcess.execute(); outputExtender.passDataThrough(CATCH_SUBPROCESS); } } @Override public List<ParameterType> getParameterTypes() { List<ParameterType> types = new LinkedList<ParameterType>(); types.add(new ParameterTypeString(PARAMETER_EXCEPTION_MACRO, "The name of the macro a potentially occuring exception message will be stored in.", true)); types.addAll(super.getParameterTypes()); return types; } }