package de.tud.inf.example;
import java.util.List;
import com.rapidminer.example.table.ExampleTable;
import com.rapidminer.tools.Ontology;
import de.tud.inf.example.set.attributevalues.ComplexValueFactory;
import de.tud.inf.example.table.ComplexAttributeDescription;
import de.tud.inf.example.table.RelationalAttribute;
/**
*
* @author Antje Gruner
* checks, if complex attributes, defined by attribute description, can be instantiated (semantically, syntax is checked in complexArffReader
*
*
*/
public class ComplexAttributeConstraintChecker {
public static boolean checkConstraints(ExampleTable et, List<ComplexAttributeDescription> etDep) throws RuntimeException{
String messg = "";
//String lineSep = Tools.getLineSeparators(2);
String lineSep = "\n";
//test each description
for(ComplexAttributeDescription cad: etDep){
int valueType = Ontology.ATTRIBUTE_VALUE_TYPE.mapName(cad.getSymbol());
if(valueType == -1){
messg = "attribute value type " + cad.getSymbol() + " is unknown";
}
else if(Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.COMPLEX_VALUE)){
if(Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.UNIFORM) && (cad.getParamIndexes().length >1) )
messg += "uncertain value with uniform pdf expects exactly one parameter (uncertainty)" + lineSep;
//do some checks on inner attributes
if(cad.getAttributeIndexes() == null || cad.getAttributeIndexes().length == 0)
messg += "attribute " +cad.getName()+ " must contain at least one inner attribute";
//do some tests on gauss attribute
if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.GAUSS))
//1. gauss expects as parameters! one relational attribute
if(cad.getParamIndexes().length != 1)
messg += "gauss attribute must have one relational parameter attribute, which stores values of variance matrix";
else{
//1.2 check if parameter attribute is relational
int pId = cad.getParamIndexes()[0];
for(int i=0;i<et.getNumberOfAttributes();i++)
if(et.getAttribute(i).getTableIndex() == pId)
if(!et.getAttribute(i).isRelational()) messg += "gauss attribute " +cad.getName() + "'s parameter attribute must be relational" + lineSep;
else {
RelationalAttribute relA = (RelationalAttribute)et.getAttribute(i);
//test if relational parameter attribute can serve as variance matrix attribute
if(relA.getInnerAttributeCount() == 0 || relA.getInnerAttributeCount() > 2)
messg += "gauss attribute " +cad.getName() + "'s parameter attribute must have one or two inner attributes, which store values of covariance matrix" + lineSep;
else if (!relA.getInnerAttributeAt(0).isNumerical())
messg += "gauss attribute " +cad.getName() + "'s parameter attribute first inner attribute serves as key for matrix entries and therefore must be numerical" + lineSep;
}
}
//do some checks on proxy attribute values (geometries), e.g. matrix, map, point list etc.
else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.GEOMETRY)){
//1. just one attribute should be wrapped
if(cad.getAttributeIndexes().length != 1) messg += "attribute " +cad.getName() + " must have exactly one inner attribute " + lineSep;
//2. this attribute must be relational
RelationalAttribute relA = null;
for(int i=0;i<et.getNumberOfAttributes();i++)
if(et.getAttribute(i).getTableIndex() == cad.getAttributeIndexes()[0])
if(!et.getAttribute(i).isRelational()) messg += "attribute " +cad.getName() + "'s inner attribute must be relational " + lineSep;
else relA = (RelationalAttribute)et.getAttribute(i);
if(relA != null){
if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.MAP)){
if (relA.getInnerAttributeCount() != 1)
messg += "map attribute " +cad.getName() + " must wrap relational attribute with exactly one inner attribute";
}
else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.POINT_LIST)){
if (relA.getInnerAttributeCount() != 3)
messg += "point list attribute " +cad.getName() + " must wrap relational attribute with exactly three inner attributes (x, y, z)";
}
else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.DATA_MAP)){
if (relA.getInnerAttributeCount() != 2)
messg += "data map attribute " +cad.getName() + " must wrap relational attribute with exactly two inner attributes (key, value)";
}
//constraints concerning matrix attributes
else if(Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.MATRIX)){
String[] pList = cad.getHint().split(ComplexValueFactory.getParameterSep());
if(pList.length != 2)
messg += "Hint of matrix attribute "+ cad.getName() +" is not valid, must be 'rows_columns' ";
else{
try{
Integer.parseInt(pList[0]);
Integer.parseInt(pList[1]);
}catch (NumberFormatException e){
messg += messg += "Hint of matrix attribute "+ cad.getName() +" is not valid, must be 'rows_columns' ";
}
}
if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.SIMPLE_MATRIX)){
if (relA.getInnerAttributeCount() != 1)
messg += "matrix attribute " +cad.getName() + " must wrap a relational attribute with exactly one inner attribute" + lineSep;
}
else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.SPARSE_MATRIX)){
//sparse matrix inner relational attributes
if (relA.getInnerAttributeCount() != 2)
messg += "sparse matrix attribute " +cad.getName() + " must wrap relational attribute with exactly two inner attributes";
else if(!Ontology.ATTRIBUTE_VALUE_TYPE.isA(relA.getInnerAttributeAt(0).getValueType(),Ontology.NUMERICAL))
messg += "sparse matrix attribute " +cad.getName() + " must wrap relational attribute which inner first attribute serves as key and therefore must be numerical" + lineSep;
}
else if (Ontology.ATTRIBUTE_VALUE_TYPE.isA(valueType, Ontology.SPARSE_BINARY_MATRIX)){
if (relA.getInnerAttributeCount() != 1)
messg += "sparse matrix attribute " +cad.getName() + " must wrap relational attribute with exactly one inner attribute";
else if(!Ontology.ATTRIBUTE_VALUE_TYPE.isA(relA.getInnerAttributeAt(0).getValueType(),Ontology.NUMERICAL))
messg += "sparse matrix attribute " +cad.getName() + " must wrap a relational attribute which inner attribute serves as key and therefore must be numerical" + lineSep;
}
}
}
else messg+= "complex attribute " + cad.getName() + " must wrap one attribute which is relational";
}
}
}
if(messg != ""){
throw new RuntimeException(messg);
}
return true;
}
}