towards better error handling
diff --git a/src/main/antlr/CollectionQuery.g4 b/src/main/antlr/CollectionQuery.g4
index f46bbbf..da73081 100644
--- a/src/main/antlr/CollectionQuery.g4
+++ b/src/main/antlr/CollectionQuery.g4
@@ -38,6 +38,7 @@
COLON : ':';
DASH : '-';
TILDE : '~';
+NEGTILDE : '!~';
SINCE : 'since';
UNTIL : 'until';
IN : 'in';
@@ -97,7 +98,7 @@
;
operator
-: (NEG? EQ) | LT | GT | LEQ | GEQ | TILDE;
+: (NEG? EQ) | LT | GT | LEQ | GEQ | TILDE | NEGTILDE;
expr
: constraint
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
index eee2507..ffdceae 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AbstractSyntaxTree.java
@@ -11,6 +11,7 @@
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import de.ids_mannheim.korap.util.QueryException;
public abstract class AbstractSyntaxTree {
@@ -209,7 +210,7 @@
frame = "frame:contains";
}
group.put("frame", frame);
- addMessage(303, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
"Position frames are now expressed through 'frames'.");
return group;
}
@@ -231,7 +232,7 @@
group.put("class", classCount);
group.put("classOut", classCount);
}
- addMessage(303, "Deprecated 2014-10-07: 'class' only to be supported until 3 months from deprecation date. " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-10-07: 'class' only to be supported until 3 months from deprecation date. " +
"Classes are now defined using the 'classOut' attribute.");
group.put("operands", new ArrayList<Object>());
return group;
@@ -245,7 +246,7 @@
group.put("classIn", Arrays.asList(classIn));
group.put("classOut", classOut);
group.put("class", classOut);
- addMessage(303, "Deprecated 2014-10-07: 'class' only to be supported until 3 months from deprecation date. " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-10-07: 'class' only to be supported until 3 months from deprecation date. " +
"Classes are now defined using the 'classOut' attribute.");
group.put("operands", new ArrayList<Object>());
return group;
@@ -299,7 +300,7 @@
if (max != null) {
group.put("max", max);
}
- addMessage(303, "Deprecated 2014-07-24: 'min' and 'max' to be supported until 3 months from deprecation date.");
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-07-24: 'min' and 'max' to be supported until 3 months from deprecation date.");
return group;
}
@@ -388,20 +389,4 @@
}
return number;
}
-
- public static void checkUnbalancedPars(String q) throws QueryException {
- int openingPars = StringUtils.countMatches(q, "(");
- int closingPars = StringUtils.countMatches(q, ")");
- int openingBrkts = StringUtils.countMatches(q, "[");
- int closingBrkts = StringUtils.countMatches(q, "]");
- int openingBrcs = StringUtils.countMatches(q, "{");
- int closingBrcs = StringUtils.countMatches(q, "}");
- if (openingPars != closingPars) throw new QueryException(
- "Your query string contains an unbalanced number of parantheses.");
- if (openingBrkts != closingBrkts) throw new QueryException(
- "Your query string contains an unbalanced number of brackets.");
- if (openingBrcs != closingBrcs) throw new QueryException(
- "Your query string contains an unbalanced number of braces.");
- }
-
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
index fdda503..f23d200 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/AqlTree.java
@@ -22,6 +22,7 @@
import de.ids_mannheim.korap.query.annis.AqlLexer;
import de.ids_mannheim.korap.query.annis.AqlParser;
+import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
import de.ids_mannheim.korap.util.QueryException;
/**
@@ -708,21 +709,25 @@
}
}
- private ParserRuleContext parseAnnisQuery (String p) throws QueryException {
- Lexer poliqarpLexer = new AqlLexer((CharStream)null);
+ private ParserRuleContext parseAnnisQuery (String query) throws QueryException {
+ Lexer lexer = new AqlLexer((CharStream)null);
ParserRuleContext tree = null;
+ Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
// Like p. 111
try {
// Tokenize input data
- ANTLRInputStream input = new ANTLRInputStream(p);
- poliqarpLexer.setInputStream(input);
- CommonTokenStream tokens = new CommonTokenStream(poliqarpLexer);
+ ANTLRInputStream input = new ANTLRInputStream(query);
+ lexer.setInputStream(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new AqlParser(tokens);
// Don't throw out erroneous stuff
parser.setErrorHandler(new BailErrorStrategy());
- parser.removeErrorListeners();
+ lexer.removeErrorListeners();
+ lexer.addErrorListener(errorListener);
+ parser.removeErrorListeners();
+ parser.addErrorListener(errorListener);
// Get starting rule from parser
Method startRule = AqlParser.class.getMethod("start");
@@ -731,8 +736,8 @@
// Some things went wrong ...
catch (Exception e) {
+ System.err.println("ERROR: "+errorListener.generateFullErrorMsg());
log.error(e.getMessage());
- System.err.println( e.getMessage() );
}
if (tree == null) {
@@ -752,6 +757,7 @@
"cat=\"S\" & cat=/NP/ & cat=/PP/ > #2",
"pos & tok & #1 . node",
"cat=/S/ & cat=/NP/ & cat=/PP/ > #1",
+ "(cat=\"a\" | cat=\"b\") & tok"
};
// AqlTree.verbose=true;
for (String q : queries) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryTree.java
index d237e74..5b0b0df 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CollectionQueryTree.java
@@ -1,7 +1,9 @@
package de.ids_mannheim.korap.query.serialize;
+import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
import de.ids_mannheim.korap.query.serialize.util.CollectionQueryLexer;
import de.ids_mannheim.korap.query.serialize.util.CollectionQueryParser;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import de.ids_mannheim.korap.util.QueryException;
import org.antlr.v4.runtime.*;
@@ -212,7 +214,7 @@
String type = (String) term.get("type");
if (type == null || type.equals("type:regex")) {
if (!(match.equals("match:eq") || match.equals("match:ne") || match.equals("match:contains") || match.equals("match:containsnot"))) {
- addError(302, "You used an inequation operator with a string value.");
+ addError(StatusCodes.INCOMPATIBLE_OPERATOR_AND_OPERAND, "You used an inequation operator with a string value.");
return false;
}
}
@@ -306,7 +308,7 @@
break;
default:
out = match;
- addError(302, "Unknown operator '"+match+"'.");
+ addError(StatusCodes.UNKNOWN_QUERY_ELEMENT, "Unknown operator '"+match+"'.");
break;
}
return out;
@@ -440,27 +442,32 @@
}
}
- private ParserRuleContext parseCollectionQuery(String p) throws QueryException {
- Lexer collectionQueryLexer = new CollectionQueryLexer((CharStream) null);
+ private ParserRuleContext parseCollectionQuery(String query) throws QueryException {
+ Lexer lexer = new CollectionQueryLexer((CharStream) null);
ParserRuleContext tree = null;
+ Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
// Like p. 111
try {
// Tokenize input data
- ANTLRInputStream input = new ANTLRInputStream(p);
- collectionQueryLexer.setInputStream(input);
- CommonTokenStream tokens = new CommonTokenStream(collectionQueryLexer);
+ ANTLRInputStream input = new ANTLRInputStream(query);
+ lexer.setInputStream(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new CollectionQueryParser(tokens);
// Don't throw out erroneous stuff
parser.setErrorHandler(new BailErrorStrategy());
+ lexer.removeErrorListeners();
+ lexer.addErrorListener(errorListener);
parser.removeErrorListeners();
+ parser.addErrorListener(errorListener);
// Get starting rule from parser
Method startRule = CollectionQueryParser.class.getMethod("start");
tree = (ParserRuleContext) startRule.invoke(parser, (Object[]) null);
}
// Some things went wrong ...
catch (Exception e) {
+ System.err.println("ERROR: "+errorListener.generateFullErrorMsg());
System.err.println("Parsing exception message: " + e);
}
if (tree == null) {
@@ -476,12 +483,11 @@
query = "(textClass=wissenschaft & textClass=politik) | textClass=ausland";
query = "textClass=Sport & year=2014";
query = "title!~mannheim";
- query = "title=1984-14";
+ query = "title = /ada\\)ad/";
CollectionQueryTree.verbose = true;
CollectionQueryTree filter = null;
try {
filter = new CollectionQueryTree(query);
- filter.verbose = true;
} catch (QueryException e) {
e.printStackTrace();
}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
index 1dfb430..ae0397e 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/CosmasTree.java
@@ -4,6 +4,7 @@
import de.ids_mannheim.korap.query.cosmas2.c2psParser;
import de.ids_mannheim.korap.query.serialize.util.CosmasCondition;
import de.ids_mannheim.korap.query.serialize.util.ResourceMapper;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import de.ids_mannheim.korap.util.QueryException;
import org.antlr.runtime.ANTLRStringStream;
@@ -877,7 +878,7 @@
posOptions.put("frames", positions);
posOptions.put("classRefCheck", classRefCheck);
posOptions.put("frame", "frame:"+frame);
- addMessage(303, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
"Position frames are now expressed through 'frames' and 'sharedClasses'");
if (exclnode != null) {
@@ -964,7 +965,7 @@
posOptions.put("frames", positions);
posOptions.put("classRefCheck", classRefCheck);
posOptions.put("frame", "frame:"+frame);
- addMessage(303, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-09-22: 'frame' only to be supported until 3 months from deprecation date. " +
"Position frames are now expressed through 'frames' and 'sharedClasses'");
if (exclnode != null) {
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
index 32f5918..3117220 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/PoliqarpPlusTree.java
@@ -2,7 +2,10 @@
import de.ids_mannheim.korap.query.poliqarp.PoliqarpPlusLexer;
import de.ids_mannheim.korap.query.poliqarp.PoliqarpPlusParser;
+import de.ids_mannheim.korap.query.serialize.util.Antlr4DescriptiveErrorListener;
+import de.ids_mannheim.korap.query.serialize.util.StatusCodes;
import de.ids_mannheim.korap.util.QueryException;
+
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTree;
import org.slf4j.Logger;
@@ -10,12 +13,11 @@
import java.lang.reflect.Method;
import java.util.*;
-import java.util.regex.Pattern;
/**
* Map representation of Poliqarp syntax tree as returned by ANTLR
*
- * @author joachim
+ * @author Joachim Bingel (bingel@ids-mannheim.de)
*/
public class PoliqarpPlusTree extends Antlr4AbstractSyntaxTree {
@@ -91,7 +93,7 @@
quantGroup.put("boundary", makeBoundary(minmax[0], minmax[1]));
if (minmax[0] != null) quantGroup.put("min", minmax[0]);
if (minmax[1] != null) quantGroup.put("max", minmax[1]);
- addMessage(303, "Deprecated 2014-07-24: 'min' and 'max' to be " +
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, "Deprecated 2014-07-24: 'min' and 'max' to be " +
"supported until 3 months from deprecation date.");
putIntoSuperObject(quantGroup);
objectStack.push(quantGroup);
@@ -219,7 +221,6 @@
if (nodeCat.equals("span")) {
List<ParseTree> negations = getChildrenWithCat(node, "!");
boolean negated = false;
- boolean isRegex = false;
if (negations.size() % 2 == 1) negated = true;
LinkedHashMap<String,Object> span = makeSpan();
ParseTree keyNode = getFirstChildWithCat(node, "key");
@@ -344,8 +345,7 @@
} catch (NumberFormatException e) {
String err = "The specified class reference in the " +
"shrink/split-Operator is not a number.";
- addError(302, err);
- throw new QueryException(err);
+ addError(StatusCodes.UNDEFINED_CLASS_REFERENCE, err);
}
}
}
@@ -361,8 +361,7 @@
String warning = "Deprecated 2014-07-24: "+type + "() as a match reducer " +
"to a specific class is deprecated in favor of focus() and will " +
"only be supported for 3 months after deprecation date.";
- log.warn(warning);
- requestMap.put("warning", warning);
+ addMessage(StatusCodes.DEPRECATED_QUERY_ELEMENT, warning);
}
if (classRefOp != null) {
referenceGroup.put("classRefOp", "classRefOp:" + classRefOp);
@@ -673,20 +672,23 @@
private ParserRuleContext parsePoliqarpQuery(String p) throws QueryException {
- checkUnbalancedPars(p);
- Lexer poliqarpLexer = new PoliqarpPlusLexer((CharStream) null);
+ Lexer lexer = new PoliqarpPlusLexer((CharStream) null);
ParserRuleContext tree = null;
+ Antlr4DescriptiveErrorListener errorListener = new Antlr4DescriptiveErrorListener(query);
// Like p. 111
try {
// Tokenize input data
ANTLRInputStream input = new ANTLRInputStream(p);
- poliqarpLexer.setInputStream(input);
- CommonTokenStream tokens = new CommonTokenStream(poliqarpLexer);
+ lexer.setInputStream(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
parser = new PoliqarpPlusParser(tokens);
// Don't throw out erroneous stuff
parser.setErrorHandler(new BailErrorStrategy());
- parser.removeErrorListeners();
+ lexer.removeErrorListeners();
+ lexer.addErrorListener(errorListener);
+ parser.removeErrorListeners();
+ parser.addErrorListener(errorListener);
// Get starting rule from parser
Method startRule = PoliqarpPlusParser.class.getMethod("request");
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
index ef47d2f..a34f7c2 100644
--- a/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/QuerySerializer.java
@@ -3,6 +3,7 @@
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
+import de.ids_mannheim.korap.query.poliqarp.PoliqarpPlusParser;
import de.ids_mannheim.korap.util.QueryException;
import de.ids_mannheim.korap.utils.JsonUtils;
import de.ids_mannheim.korap.utils.KorAPLogger;
@@ -19,7 +20,22 @@
* @author bingel, hanl
*/
public class QuerySerializer {
+
+ public enum QueryLanguage {
+ POLIQARPPLUS, ANNIS, COSMAS2, CQL, CQP
+ }
+
+ static HashMap<String, Class<? extends AbstractSyntaxTree>> qlProcessorAssignment;
+ static {
+ qlProcessorAssignment = new HashMap<String, Class<? extends AbstractSyntaxTree>>();
+ qlProcessorAssignment.put("poliqarpplus", PoliqarpPlusTree.class);
+ qlProcessorAssignment.put("cosmas2", CosmasTree.class);
+ qlProcessorAssignment.put("annis", AqlTree.class);
+ qlProcessorAssignment.put("cql", CQLTree.class);
+ }
+
+
private Logger qllogger = KorAPLogger.initiate("ql");
public static String queryLanguageVersion;
@@ -32,7 +48,6 @@
private org.slf4j.Logger log = LoggerFactory
.getLogger(QuerySerializer.class);
-
/**
* @param args
* @throws QueryException
@@ -46,7 +61,6 @@
String[] queries;
if (args.length == 0) {
queries = new String[]{
- "foo"
};
} else
queries = new String[]{args[0]};
@@ -100,9 +114,6 @@
throw new QueryException(queryLanguage + " is not a supported query language!");
}
toJSON();
- Map<String, Object> requestMap = ast.getRequestMap();
- System.out.println(requestMap);
-// mapper.writeValue(new File(outFile), requestMap);
}
public QuerySerializer setQuery(String query, String ql, String version)