Commit f83e7c07 authored by Georg's avatar Georg
Browse files

continued type checking

parent 5be7c236
......@@ -3,11 +3,15 @@ package de.uniwue.model;
import java.util.ArrayList;
import java.util.List;
import de.uniwue.query.DataType;
public class Concept {
public static String intTermCodes;
public String name;
public Model model;
public String name;
public List<String> termCodes;
......@@ -24,4 +28,18 @@ public class Concept {
fields.add(field);
}
public DataType getDataType() {
DataType dataType = new DataType(name, DataType.CONCEPT, false);
return dataType;
}
public ConceptField getField(String aName) {
for (ConceptField aField : fields) {
if (aField.name.equals(aName)) {
return aField;
}
}
throw new RuntimeException("field '" + aName + "' does not exist");
}
}
......@@ -2,12 +2,30 @@ package de.uniwue.model;
import java.util.List;
import de.uniwue.query.DataType;
public class ConceptField {
public Concept parent;
public String name;
public List<String> types;
public boolean isArray;
public DataType getDataType() {
if (types.size() == 1) {
String fieldType = types.get(0);
if (fieldType.equals("Duration")) {
return DataType.DURATION;
} else {
return new DataType(fieldType, DataType.CONCEPT, isArray);
}
} else {
return DataType.ANY;
}
}
}
......@@ -19,10 +19,19 @@ public class Model {
public static Model fromJSON(String jsonString) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
Object model = objectMapper.readValue(jsonString, Model.class);
return (Model) model;
Model model = objectMapper.readValue(jsonString, Model.class);
for (Concept aConc : model.concepts) {
aConc.model = model;
if (aConc.fields != null) {
for (ConceptField aField : aConc.fields) {
aField.parent = aConc;
}
}
model.conceptMap.put(aConc.name, aConc);
}
return model;
}
public String toJSON() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(Include.NON_NULL);
......
......@@ -103,6 +103,7 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
return Graph_2_CQL_Mapper.system;
}
@Override
protected void clear() {
super.clear();
parsingRetrieveClause = false;
......@@ -915,21 +916,25 @@ public class CQL_2_Graph_Mapper extends System_2_Graph_Mapper {
private void parseQuantityLiteralContext(QuantityLiteralContext ql) {
String prettyPrint = prettyPrint(ql);
QueryOperator lastOp = currentOp;
addOp(OperatorType.QUANTITY);
QuantityContext quantity = ql.quantity();
String text = quantity.NUMBER().getText();
parseNumber(text);
UnitContext unit = quantity.unit();
DateTimePrecisionContext dateTimePrecision = unit.dateTimePrecision();
PluralDateTimePrecisionContext pluralDateTimePrecision = unit.pluralDateTimePrecision();
if (pluralDateTimePrecision != null) {
String timePrecision = pluralDateTimePrecision.getText();
addOp(OperatorType.DURATION);
parseNumber(text);
currentOp.addParameter(timePrecision);
} else if (dateTimePrecision != null) {
String timePrecision = dateTimePrecision.getText();
addOp(OperatorType.DURATION);
parseNumber(text);
currentOp.addParameter(timePrecision);
} else {
String unitString = unit.STRING().getText().replaceAll("'", "");
addOp(OperatorType.QUANTITY);
parseNumber(text);
currentOp.addParameter(unitString);
}
currentOp = lastOp;
......
......@@ -50,6 +50,7 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
initializeOpMappings(opMap);
}
@Override
protected void initialize(QueryOperator aQuery) {
super.initialize(aQuery);
aliases = new HashMap<QueryOperator, String>();
......@@ -388,12 +389,11 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
} else if (anOp.type == OperatorType.QUANTITY) {
result += anOp.getParameters().get(0).asPrimitive().value + " ";
String unitString = anOp.getParameters().get(1).asPrimitive().value;
if (unitString.matches(
"days|day|months|month|years|year|seconds|second|minutes|minute|hours|hour|weeks|week|milliseconds|millisecond")) {
result += unitString;
} else {
result += "'" + unitString + "'";
}
result += "'" + unitString + "'";
} else if (anOp.type == OperatorType.DURATION) {
result += anOp.getParameters().get(0).asPrimitive().value + " ";
String unitString = anOp.getParameters().get(1).asPrimitive().value;
result += unitString;
} else if (anOp.type == OperatorType.FIELD) {
String frstExp = writeExpr(anOp.getParameters().get(0));
String sndExp = anOp.getParameters().get(1).asConcept().getIteratorSelector();
......@@ -444,6 +444,7 @@ public class Graph_2_CQL_Mapper extends Graph_2_System_Mapper {
aMap.addOp("exists", OperatorType.EXISTS);
aMap.addOp("", OperatorType.QUANTITY);
aMap.addOp("", OperatorType.DURATION);
aMap.addOp("", OperatorType.INTERVAL);
aMap.addOp("", OperatorType.LIST);
aMap.addOp("", OperatorType.TO_LIST);
......
......@@ -3,7 +3,7 @@ package de.uniwue.query;
public class DataType {
public static DataType ANY, STRING, BOOLEAN, NUMBER, INTEGER, DOUBLE, INTERVAL, DATETIME, CONCEPT,
QUANTITY;
QUANTITY, DURATION;
public static DataType LIST_OF_ANY, LIST_OF_STRING, LIST_OF_BOOLEAN, LIST_OF_NUMBER,
LIST_OF_INTEGER, LIST_OF_DOUBLE, LIST_OF_INTERVAL, LIST_OF_DATETIME, LIST_OF_CONCEPT,
......@@ -44,6 +44,7 @@ public class DataType {
DATETIME = new DataType("Datetime");
CONCEPT = new DataType("Concept");
QUANTITY = new DataType("Quantity");
DURATION = new DataType("Duration", QUANTITY);
LIST_OF_ANY = new DataType("Any", ANY, true);
LIST_OF_STRING = new DataType("String", LIST_OF_ANY, true);
LIST_OF_BOOLEAN = new DataType("Boolean", LIST_OF_ANY, true);
......@@ -56,6 +57,7 @@ public class DataType {
LIST_OF_QUANTITY = new DataType("Quantity", LIST_OF_ANY, true);
}
@Override
public String toString() {
String result = name;
if (isList) {
......
......@@ -4,6 +4,9 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import de.uniwue.model.Concept;
import de.uniwue.model.ConceptField;
public class OperatorInterfaces {
private static Set<OperatorType> opsReturningBOOLEAN = new HashSet<OperatorType>(
......@@ -39,17 +42,26 @@ public class OperatorInterfaces {
}
}
public static boolean conformsType(DataType typeToCheck, DataType typeToCheckTo) {
DataType currentType = typeToCheck;
while ((currentType != null) && (currentType != typeToCheckTo)) {
currentType = currentType.parent;
}
if (currentType == typeToCheckTo) {
return true;
} else {
return false;
}
}
public static void checkParamType(QueryOperator anOp, int paramIndex, DataType desiredType) {
Expression aParam = anOp.getParameters().get(paramIndex);
DataType actualType = aParam.getDataType();
DataType currentType = actualType;
while ((currentType != null) && (currentType != desiredType)) {
currentType = currentType.parent;
}
if (currentType != desiredType) {
if (!conformsType(actualType, desiredType)) {
throw new RuntimeException("Operator '" + anOp.type + "' expects for parameter number "
+ paramIndex + " the type " + desiredType + " but it was " + actualType);
}
int x = 0;
}
public static DataType getReturnDataType(QueryOperator anOp) {
......@@ -60,8 +72,8 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.AFTER) {
return DataType.BOOLEAN;
} else if (anOp.type == OperatorType.ALIAS_REF) {
throw new RuntimeException("TODO");
// return DataType.CONCEPT;
DataType parentDataType = anOp.resolveAlias().getDataType();
return new DataType(parentDataType.name, DataType.CONCEPT, false);
} else if (anOp.type == OperatorType.ALLTRUE) {
return DataType.BOOLEAN;
} else if (anOp.type == OperatorType.AND) {
......@@ -84,6 +96,8 @@ public class OperatorInterfaces {
return DataType.DATETIME;
} else if (anOp.type == OperatorType.DIVIDE) {
return DataType.NUMBER;
} else if (anOp.type == OperatorType.DURATION) {
return DataType.DURATION;
} else if (anOp.type == OperatorType.DURATION_BETWEEN) {
return DataType.BOOLEAN;
} else if (anOp.type == OperatorType.DURATIONIN) {
......@@ -100,14 +114,16 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.EXP) {
return DataType.NUMBER;
} else if (anOp.type == OperatorType.FIELD) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
DataType parentType = anOp.getParameters().get(0).getDataType();
String value = anOp.getParameters().get(1).asPrimitive().value;
Concept concept = anOp.getModel().conceptMap.get(parentType.name);
ConceptField field = concept.getField(value);
return field.getDataType();
} else if (anOp.type == OperatorType.FIELD_WITH_TYPE) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
} else if (anOp.type == OperatorType.FILTER) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
return getReturnDataType(anOp.getParameters().get(0).asOperator());
} else if (anOp.type == OperatorType.FIRST) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
......@@ -125,8 +141,13 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.IS) {
return DataType.BOOLEAN;
} else if (anOp.type == OperatorType.ITERATE) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
String value = anOp.getParameters().get(0).asPrimitive().value;
Concept concept = anOp.getModel().conceptMap.get(value);
if (concept == null) {
throw new RuntimeException("no concept for iterator '" + value + "'");
}
DataType dataType = concept.getDataType();
return new DataType(dataType.name, dataType.parent, true);
} else if (anOp.type == OperatorType.LAST) {
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
......@@ -135,6 +156,8 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.LESS_OR_EQUAL) {
return DataType.BOOLEAN;
} else if (anOp.type == OperatorType.LIST) {
DataType dataType = anOp.getParameters().get(0).getDataType();
throw new RuntimeException("TODO");
// return DataType.LIST_OF_ANY;
} else if (anOp.type == OperatorType.LN) {
......@@ -224,17 +247,32 @@ public class OperatorInterfaces {
}
public static void checkIsList(QueryOperator anOp, int paramIndex) {
if (!anOp.getParameters().get(paramIndex).getDataType().isList) {
DataType dataType = anOp.getParameters().get(paramIndex).getDataType();
if (!dataType.isList) {
throw new RuntimeException(
"parameter " + paramIndex + " of op " + anOp.type + " has to be a list but isn't");
}
}
public static void checkStdArithmeticOp(QueryOperator anOp) {
checkParamCount(anOp, 2);
DataType dataType1 = anOp.getParameters().get(0).getDataType();
DataType dataType2 = anOp.getParameters().get(1).getDataType();
if (!conformsType(dataType1, DataType.NUMBER) && !conformsType(dataType1, DataType.QUANTITY)) {
throw new RuntimeException("std arithmetic operators can only process numbers or quantities");
}
if (dataType1 != dataType2) {
throw new RuntimeException(
"both parameters in std arithmetic operators have to be same type");
}
int x = 0;
}
public static void check(QueryOperator anOp) {
if (anOp.type == OperatorType.ABS) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER });
} else if (anOp.type == OperatorType.ADD) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.AFTER) {
checkParamTypes(anOp, new DataType[] { DataType.DATETIME, DataType.DATETIME });
} else if (anOp.type == OperatorType.ALIAS_REF) {
......@@ -263,6 +301,8 @@ public class OperatorInterfaces {
checkParamTypes(anOp, new DataType[] { DataType.STRING });
} else if (anOp.type == OperatorType.DIVIDE) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
} else if (anOp.type == OperatorType.DURATION) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.STRING });
} else if (anOp.type == OperatorType.DURATION_BETWEEN) {
checkParamTypes(anOp, new DataType[] { DataType.DATETIME, DataType.DATETIME });
} else if (anOp.type == OperatorType.DURATIONIN) {
......@@ -311,11 +351,12 @@ public class OperatorInterfaces {
checkParamCount(anOp, 1);
checkIsList(anOp, 0);
} else if (anOp.type == OperatorType.LESS) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.LESS_OR_EQUAL) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.LIST) {
checkAllParamsType(anOp, DataType.ANY);
DataType dataType = anOp.getParameters().get(0).getDataType();
checkAllParamsType(anOp, dataType);
} else if (anOp.type == OperatorType.LN) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
} else if (anOp.type == OperatorType.LOG) {
......@@ -331,9 +372,9 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.MODULO) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
} else if (anOp.type == OperatorType.MORE) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.MORE_OR_EQUAL) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.MULTIPLY) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
} else if (anOp.type == OperatorType.NEGATE) {
......@@ -362,7 +403,7 @@ public class OperatorInterfaces {
} else if (anOp.type == OperatorType.STDDEV) {
checkAllParamsType(anOp, DataType.NUMBER);
} else if (anOp.type == OperatorType.SUBTRACT) {
checkParamTypes(anOp, new DataType[] { DataType.NUMBER, DataType.NUMBER });
checkStdArithmeticOp(anOp);
} else if (anOp.type == OperatorType.SUM) {
checkAllParamsType(anOp, DataType.NUMBER);
} else if (anOp.type == OperatorType.TIME) {
......
......@@ -91,6 +91,7 @@ public enum OperatorType {
// constructors
VALUESET,
QUANTITY,
DURATION,
LIST,
INTERVAL
;
......
......@@ -78,6 +78,7 @@ public class QueryOperator extends Expression {
this(null, opType);
}
@Override
public QueryOperator clone() {
QueryOperator result = new QueryOperator(type);
for (Expression anExp : getParameters()) {
......@@ -137,7 +138,7 @@ public class QueryOperator extends Expression {
checkDuplicateAliases();
checkParentChildSynchonicity();
checkAliasExistenceForAliasRefs();
// checkInterface();
checkInterface();
for (QueryOperator anOp : getOperators()) {
anOp.checkConsistency();
}
......@@ -421,6 +422,7 @@ public class QueryOperator extends Expression {
}
}
@Override
public DataType getDataType() {
return OperatorInterfaces.getReturnDataType(this);
}
......
......@@ -5,6 +5,7 @@ import java.text.ParseException;
import org.junit.Test;
import de.uniwue.misc.util.ResourceUtil;
import de.uniwue.model.Model;
import de.uniwue.query.CQL.CQL_2_Graph_Mapper;
import de.uniwue.query.CQL.Graph_2_CQL_Mapper;
......@@ -60,7 +61,8 @@ public class Test_CQL_2_CQL {
private void initialize() throws IOException {
String modelJSONFilePath = "classpath:v3/model.json";
cqlModel = Model.fromJSON(modelJSONFilePath);
String modelJSONString = ResourceUtil.loadFileAsString(modelJSONFilePath);
cqlModel = Model.fromJSON(modelJSONString);
cql2Graph = new CQL_2_Graph_Mapper();
graph2CQL = new Graph_2_CQL_Mapper();
}
......@@ -76,6 +78,7 @@ public class Test_CQL_2_CQL {
String originalQuery = aMultiQuery.system2QueryString.get(CQL_2_Graph_Mapper.getSystem());
if (originalQuery != null) {
QueryOperator query = cql2Graph.parse(originalQuery, cqlModel);
query.checkConsistency();
String graphString = query.toString();
String desiredGraphStringResult = aMultiQuery.system2QueryString.get(Mapper.graphSystemName);
if (!graphString.equals(desiredGraphStringResult)) {
......
......@@ -46,7 +46,7 @@ QUERY(
ALIAS_REF('A'),
'length'
),
QUANTITY(
DURATION(
120,
'days'
)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment