/* * 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.generator; import java.util.Iterator; import java.util.List; import com.rapidminer.example.Attribute; import com.rapidminer.example.Attributes; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.table.DoubleArrayDataRow; import com.rapidminer.example.table.MemoryExampleTable; import com.rapidminer.generator.GenerationException; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.ProcessSetupError.Severity; import com.rapidminer.operator.SimpleProcessSetupError; import com.rapidminer.operator.UserError; import com.rapidminer.operator.io.AbstractExampleSource; import com.rapidminer.operator.ports.metadata.AttributeMetaData; import com.rapidminer.operator.ports.metadata.ExampleSetMetaData; import com.rapidminer.operator.ports.metadata.MetaData; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeExpression; import com.rapidminer.parameter.ParameterTypeList; import com.rapidminer.parameter.ParameterTypeString; import com.rapidminer.parameter.ParameterTypeStringCategory; import com.rapidminer.parameter.UndefinedParameterError; import com.rapidminer.tools.math.function.ExpressionParser; /** * This operator produces an {@link ExampleSet} containing only * one example whose Attribute values are derived from a user specified list. * * @author Sebastian Land */ public class UserSpecificationDataGenerator extends AbstractExampleSource { public static final String PARAMETER_VALUES = "attribute_values"; public static final String PARAMETER_ATTRIBUTE_NAME = "attribute_name"; public static final String PARAMETER_ATTRIBUTE_VALUE = "attribute_value"; /** The parameter name for "The name of the attribute of which the type should be changed." */ public static final String PARAMETER_NAME = "name"; /** The parameter name for "The target type of the attribute (only changed if parameter change_attribute_type is true)." */ public static final String PARAMETER_TARGET_ROLE = "target_role"; public static final String PARAMETER_ROLES = "set_additional_roles"; private static final String REGULAR_NAME = "regular"; private static final String[] TARGET_ROLES = new String[] { REGULAR_NAME, Attributes.ID_NAME, Attributes.LABEL_NAME, Attributes.PREDICTION_NAME, Attributes.CLUSTER_NAME, Attributes.WEIGHT_NAME, Attributes.BATCH_NAME }; public UserSpecificationDataGenerator(OperatorDescription description) { super(description); } @Override public MetaData getGeneratedMetaData() throws OperatorException { ExampleSetMetaData emd = new ExampleSetMetaData(); emd.setNumberOfExamples(1); emd.attributesAreKnown(); ExpressionParser parser = new ExpressionParser(true); try { Iterator<String[]> j = getParameterList(PARAMETER_VALUES).iterator(); while (j.hasNext()) { String[] nameFunctionPair = j.next(); String name = nameFunctionPair[0]; String function = nameFunctionPair[1]; parser.addAttributeMetaData(emd, name, function); } // now proceed with Attribute rules if (isParameterSet(PARAMETER_ROLES)) { List<String[]> list = getParameterList(PARAMETER_ROLES); for (String[] pairs: list) { setRoleMetaData(emd, pairs[0], pairs[1]); } } } catch (UndefinedParameterError e) {} return emd; } private void setRoleMetaData(ExampleSetMetaData metaData, String name, String targetRole) { AttributeMetaData amd = metaData.getAttributeByName(name); if (amd != null) { if (targetRole != null) { if (REGULAR_NAME.equals(targetRole)) { amd.setRegular(); } else { AttributeMetaData oldRole = metaData.getAttributeByRole(targetRole); if (oldRole != null && oldRole != amd) { addError(new SimpleProcessSetupError(Severity.WARNING, this.getPortOwner(), "already_contains_role", targetRole)); metaData.removeAttribute(oldRole); } amd.setRole(targetRole); } } } } @Override public ExampleSet createExampleSet() throws OperatorException { ExpressionParser parser = new ExpressionParser(true); MemoryExampleTable table = new MemoryExampleTable(); table.addDataRow(new DoubleArrayDataRow(new double[0])); ExampleSet exampleSet = table.createExampleSet(); Iterator<String[]> j = getParameterList(PARAMETER_VALUES).iterator(); while (j.hasNext()) { String[] nameFunctionPair = j.next(); String name = nameFunctionPair[0]; String function = nameFunctionPair[1]; try { parser.addAttribute(exampleSet, name, function); } catch (GenerationException e) { throw new UserError(this, e, 108, e.getMessage()); } checkForStop(); } // now set roles if (isParameterSet(PARAMETER_ROLES)) { List<String[]> list = getParameterList(PARAMETER_ROLES); for (String[] pairs: list) { setRole(exampleSet, pairs[0], pairs[1]); } } return exampleSet; } private void setRole(ExampleSet exampleSet, String name, String newRole) throws UserError { Attribute attribute = exampleSet.getAttributes().get(name); if (attribute == null) { throw new UserError(this, 111, name); } exampleSet.getAttributes().remove(attribute); if ((newRole == null) || (newRole.trim().length() == 0)) throw new UserError(this, 205, PARAMETER_TARGET_ROLE); if (newRole.equals(REGULAR_NAME)) { exampleSet.getAttributes().addRegular(attribute); } else { exampleSet.getAttributes().setSpecialAttribute(attribute, newRole); } } @Override public List<ParameterType> getParameterTypes() { List<ParameterType> types = super.getParameterTypes(); types.add(new ParameterTypeList(PARAMETER_VALUES, "This parameter defines the attributes and their values in the single example returned.", new ParameterTypeString(PARAMETER_ATTRIBUTE_NAME, "This is the name of the generated attribute.", false), new ParameterTypeExpression(PARAMETER_ATTRIBUTE_VALUE, "An expression that is parsed to derive the value of this attribute."), false)); types.add(new ParameterTypeList(PARAMETER_ROLES, "This parameter defines additional attribute role combinations.", new ParameterTypeString(PARAMETER_NAME, "The name of the attribute whose role should be changed.", false, false), new ParameterTypeStringCategory(PARAMETER_TARGET_ROLE, "The target role of the attribute (only changed if parameter change_attribute_type is true).", TARGET_ROLES, TARGET_ROLES[0]), false)); return types; } }