/** * Parses the provided expression and iterates over the {@link ExampleSet}, interprets attributes * as variables, evaluates the function and creates a new attribute with the given name that takes * the expression's value. The type of the attribute depends on the expression type and is {@link * Ontology#NOMINAL} for strings, {@link Ontology#INTEGER} for integers, {@link Ontology#REAL} for * reals, {@link Ontology#DATE_TIME} for Dates, and {@link Ontology#BINOMINAL} with values * "true" and "false" for booleans. If the executing operator is defined, * there will be a check for stop before the calculation of each example. * * @param exampleSet the example set to which the generated attribute is added * @param name the new attribute name * @param expression the expression used to generate attribute values * @param parser the expression parser used to parse the expression argument * @param resolver the example resolver which is used by the parser to resolve example values * @param executingOperator the operator calling this method. <code>null</code> is allowed. If not * null the operator will be used to check for stop * @throws ProcessStoppedException in case the process was stopped by the user * @throws ExpressionException in case parsing the expression fails */ public static Attribute addAttribute( ExampleSet exampleSet, String name, String expression, ExpressionParser parser, ExampleResolver resolver, Operator executingOperator) throws ProcessStoppedException, ExpressionException { // parse the expression Expression parsedExpression = parser.parse(expression); Attribute newAttribute = null; // if != null this needs to be overridden Attribute existingAttribute = exampleSet.getAttributes().get(name); StringBuffer appendix = new StringBuffer(); String targetName = name; if (existingAttribute != null) { // If an existing attribute will be overridden, first a unique temporary name has to be // generated by appending a random string to the attribute's name until it's a unique // attribute name. After the new attribute is build, it's name is set the 'targetName' // at the end of this method. // do { appendix.append(RandomGenerator.getGlobalRandomGenerator().nextString(5)); } while (exampleSet.getAttributes().get(name + appendix.toString()) != null); name = name + appendix.toString(); } ExpressionType resultType = parsedExpression.getExpressionType(); int ontology = resultType.getAttributeType(); if (ontology == Ontology.BINOMINAL) { newAttribute = AttributeFactory.createAttribute(name, Ontology.BINOMINAL); newAttribute.getMapping().mapString("false"); newAttribute.getMapping().mapString("true"); } else { newAttribute = AttributeFactory.createAttribute(name, ontology); } // set construction description newAttribute.setConstruction(expression); // add new attribute to table and example set exampleSet.getExampleTable().addAttribute(newAttribute); exampleSet.getAttributes().addRegular(newAttribute); // create attribute of correct type and all values for (Example example : exampleSet) { if (executingOperator != null) { executingOperator.checkForStop(); } // bind example to resolver resolver.bind(example); // calculate result try { switch (resultType) { case DOUBLE: case INTEGER: example.setValue(newAttribute, parsedExpression.evaluateNumerical()); break; case DATE: Date date = parsedExpression.evaluateDate(); example.setValue(newAttribute, date == null ? Double.NaN : date.getTime()); break; default: example.setValue(newAttribute, parsedExpression.evaluateNominal()); break; } } finally { // avoid memory leaks resolver.unbind(); } } // remove existing attribute (if necessary) if (existingAttribute != null) { AttributeRole oldRole = exampleSet.getAttributes().getRole(existingAttribute); exampleSet.getAttributes().remove(existingAttribute); newAttribute.setName(targetName); // restore role from old attribute to new attribute if (oldRole.isSpecial()) { exampleSet.getAttributes().setSpecialAttribute(newAttribute, oldRole.getSpecialName()); } } // update example resolver after meta data change resolver.addAttributeMetaData( new AttributeMetaData(exampleSet.getAttributes().getRole(newAttribute), exampleSet, true)); return newAttribute; }