/******************************************************************************* * Copyright 2013 SAP AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.sap.core.odata.core.uri.expression; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.Locale; import org.apache.log4j.xml.DOMConfigurator; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sap.core.odata.api.edm.EdmEntityType; import com.sap.core.odata.api.edm.EdmException; import com.sap.core.odata.api.edm.EdmProperty; import com.sap.core.odata.api.edm.EdmType; import com.sap.core.odata.api.exception.MessageReference; import com.sap.core.odata.api.exception.ODataApplicationException; import com.sap.core.odata.api.exception.ODataMessageException; import com.sap.core.odata.api.uri.expression.CommonExpression; import com.sap.core.odata.api.uri.expression.ExceptionVisitExpression; import com.sap.core.odata.api.uri.expression.ExpressionKind; import com.sap.core.odata.api.uri.expression.ExpressionParserException; import com.sap.core.odata.api.uri.expression.ExpressionVisitor; import com.sap.core.odata.api.uri.expression.SortOrder; import com.sap.core.odata.core.exception.MessageService; import com.sap.core.odata.core.exception.MessageService.Message; /** * @author SAP AG */ public class ParserTool { static { DOMConfigurator.configureAndWatch("log4j.xml"); } private static final Logger log = LoggerFactory.getLogger(ParserTool.class); private static boolean debug = false; private String expression; private CommonExpression tree; private CommonExpression curNode; private Exception curException; private static final Locale DEFAULT_LANGUAGE = new Locale("test", "SAP"); public static void dout(final String out) { if (debug) { ParserTool.log.debug(out); } } public static void out(final String out) { ParserTool.log.debug(out); } public ParserTool(final String expression, final boolean isOrder, final boolean addTestfunctions, final boolean allowOnlyBinary) { dout("ParserTool - Testing: " + expression); this.expression = expression; try { if (!isOrder) { FilterParserImplTool parser = new FilterParserImplTool(null); if (addTestfunctions) { parser.addTestfunctions(); } tree = parser.parseFilterString(expression, allowOnlyBinary).getExpression(); } else { OrderByParserImpl parser = new OrderByParserImpl(null); tree = parser.parseOrderByString(expression); } } catch (ExpressionParserException e) { curException = e; } catch (ExpressionParserInternalError e) { curException = e; } curNode = tree; } public ParserTool(final String expression, final boolean isOrder, final boolean addTestfunctions, final boolean allowOnlyBinary, final EdmEntityType resourceEntityType) { dout("ParserTool - Testing: " + expression); this.expression = expression; try { if (!isOrder) { FilterParserImplTool parser = new FilterParserImplTool(resourceEntityType); if (addTestfunctions) { parser.addTestfunctions(); } tree = parser.parseFilterString(expression, allowOnlyBinary).getExpression(); } else { OrderByParserImpl parser = new OrderByParserImpl(resourceEntityType); tree = parser.parseOrderByString(expression); } } catch (ExpressionParserException e) { curException = e; } catch (ExpressionParserInternalError e) { curException = e; } curNode = tree; } ParserTool aKind(final ExpressionKind kind) { String info = "GetInfoKind(" + expression + ")-->"; dout(" " + info + "Expected: " + kind.toString() + " Actual: " + curNode.getKind().toString()); assertEquals(info, kind, curNode.getKind()); return this; } public ParserTool aUriLiteral(final String uriLiteral) { String info = "GetUriLiteral(" + expression + ")-->"; dout(" " + info + "Expected: " + uriLiteral + " Actual: " + curNode.getUriLiteral()); assertEquals(info, uriLiteral, curNode.getUriLiteral()); return this; } /** * Verifies that the thrown exception is of {@paramref expected} * * @param expected * Expected Exception class * @return ParserTool */ public ParserTool aExType(final Class<? extends Exception> expected) { String info = "GetExceptionType(" + expression + ")-->"; if (curException == null) { fail("Error in aExType: Expected exception " + expected.getName()); } dout(" " + info + "Expected: " + expected.getName() + " Actual: " + curException.getClass().getName()); if (expected != curException.getClass()) { fail(" " + info + "Expected: " + expected.getName() + " Actual: " + curException.getClass().getName()); } return this; } /** * Verifies that the message text of the thrown exception serialized is * {@paramref messageText} * * @param messageText * Expected message text * @return this */ public ParserTool aExMsgText(final String messageText) { String info = "aExMessageText(" + expression + ")-->"; if (curException == null) { fail("Error in aExMessageText: Expected exception."); } ODataMessageException messageException; try { messageException = (ODataMessageException) curException; } catch (ClassCastException ex) { fail("Error in aExNext: curException not an ODataMessageException"); return this; } Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); info = " " + info + "Expected: '" + messageText + "' Actual: '" + ms.getText() + "'"; dout(info); assertEquals(info, messageText, ms.getText()); return this; } /** * Verifies that all place holders in the message text definition of the * thrown exception are provided with content * * @return ParserTool */ public ParserTool aExMsgContentAllSet() { String info = "aExMessageTextNoEmptyTag(" + expression + ")-->"; if (curException == null) { fail("Error in aExMessageText: Expected exception."); } ODataMessageException messageException; try { messageException = (ODataMessageException) curException; } catch (ClassCastException ex) { fail("Error in aExNext: curException not an ODataMessageException"); return this; } Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); info = " " + info + "Messagetext: '" + ms.getText() + "contains [%"; dout(info); if (ms.getText().contains("[%")) { fail(info); } return this; } /** * Verifies that the message text of the thrown exception is not empty * * @return ParserTool */ public ParserTool aExMsgNotEmpty() { String info = "aExTextNotEmpty(" + expression + ")-->"; if (curException == null) { fail("Error in aExMessageText: Expected exception."); } ODataMessageException messageException; try { messageException = (ODataMessageException) curException; } catch (ClassCastException ex) { fail("Error in aExNext: curException not an ODataMessageException"); return this; } Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); info = " " + info + "check if Messagetext is empty"; dout(info); if (ms.getText().length() == 0) { fail(info); } return this; } public ParserTool aExKey(final MessageReference expressionExpectedAtPos) { String expectedKey = expressionExpectedAtPos.getKey(); ODataMessageException messageException; String info = "GetExceptionType(" + expression + ")-->"; if (curException == null) { fail("Error in aExType: Expected exception"); } try { messageException = (ODataMessageException) curException; } catch (ClassCastException ex) { fail("Error in aExNext: curException not an ODataMessageException"); return this; } String actualKey = messageException.getMessageReference().getKey(); dout(" " + info + "Expected key: " + expectedKey + " Actual: " + actualKey); if (expectedKey != actualKey) { fail(" " + info + "Expected: " + expectedKey + " Actual: " + actualKey); } return this; } public ParserTool printExMessage() { ODataMessageException messageException; if (curException == null) { fail("Error in aExMsgPrint: Expected exception"); } try { messageException = (ODataMessageException) curException; } catch (ClassCastException ex) { fail("Error in aExNext: curException not an ODataMessageException"); return this; } Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); out("Messge --> "); out(" " + ms.getText()); out("Messge <-- "); return this; } public String getExceptionText() { ODataMessageException messageException = (ODataMessageException) curException; Message ms = MessageService.getMessage(DEFAULT_LANGUAGE, messageException.getMessageReference()); return ms.getText(); } public ParserTool printSerialized() { String actual = null; ExpressionVisitor visitor = new VisitorTool(); try { actual = tree.accept(visitor).toString(); } catch (ExceptionVisitExpression e) { fail("Error in visitor:" + e.getLocalizedMessage()); } catch (ODataApplicationException e) { fail("Error in visitor:" + e.getLocalizedMessage()); } out("Messge --> "); out(" " + actual); out("Messge <-- "); return this; } public ParserTool exPrintStack() { curException.printStackTrace(); return this; } public ParserTool exNext() { try { curException = (Exception) curException.getCause(); } catch (ClassCastException ex) { fail("Error in aExNext: Cause not an Exception"); } return this; } private void checkNoException(final String infoMethod) { if (curException != null) { fail("Error in " + infoMethod + ": exception '" + getExceptionText() + "' occured!"); } } public ParserTool aEdmType(final EdmType type) { checkNoException("aEdmType"); String info = "GetEdmType(" + expression + ")-->"; try { if (curNode.getEdmType() == null) { dout(" " + info + "Expected: " + type.getName() + " Actual: " + "null"); fail("Error in aEdmType: type of curNode is null"); } dout(" " + info + "Expected: " + type.getName() + " Actual: " + curNode.getEdmType().getName()); } catch (EdmException e) { fail("Error in aEdmType:" + e.getLocalizedMessage()); } assertEquals(info, type, curNode.getEdmType()); return this; } public ParserTool aSortOrder(final SortOrder orderType) { String info = "GetSortOrder(" + expression + ")-->"; if (curNode.getKind() != ExpressionKind.ORDER) { String out = info + "Expected: " + ExpressionKind.ORDER + " Actual: " + curNode.getKind().toString(); dout(" " + out); fail(out); } OrderExpressionImpl orderExpression = (OrderExpressionImpl) curNode; dout(" " + info + "Expected: " + orderType.toString() + " Actual: " + orderExpression.getSortOrder().toString()); assertEquals(info, orderType, orderExpression.getSortOrder()); return this; } public ParserTool aExpr() { String info = "GetExpr(" + expression + ")-->"; if ((curNode.getKind() != ExpressionKind.ORDER) && (curNode.getKind() != ExpressionKind.FILTER)) { String out = info + "Expected: " + ExpressionKind.ORDER + " or " + ExpressionKind.FILTER + " Actual: " + curNode.getKind().toString(); dout(" " + out); fail(out); } if (curNode.getKind() == ExpressionKind.FILTER) { FilterExpressionImpl filterExpression = (FilterExpressionImpl) curNode; curNode = filterExpression.getExpression(); } else { OrderExpressionImpl orderByExpression = (OrderExpressionImpl) curNode; curNode = orderByExpression.getExpression(); } return this; } public ParserTool aEdmProperty(final EdmProperty string) { String info = "GetEdmProperty(" + expression + ")-->"; if (curNode.getKind() != ExpressionKind.PROPERTY) { String out = info + "Expected: " + ExpressionKind.PROPERTY + " Actual: " + curNode.getKind().toString(); dout(" " + out); fail(out); } PropertyExpressionImpl propertyExpression = (PropertyExpressionImpl) curNode; try { dout(" " + info + "Expected: Property'" + string.getName() + "' Actual: " + propertyExpression.getEdmProperty().getName()); } catch (EdmException e) { fail("Error in aEdmProperty:" + e.getLocalizedMessage()); } assertEquals(info, string, propertyExpression.getEdmProperty()); return this; } public ParserTool aSerializedCompr(final String expected) { aSerialized(compress(expected)); return this; } public ParserTool aSerialized(final String expected) { checkNoException("aSerialized"); String actual = null; ExpressionVisitor visitor = new VisitorTool(); try { actual = tree.accept(visitor).toString(); } catch (ExceptionVisitExpression e) { fail("Error in visitor:" + e.getLocalizedMessage()); } catch (ODataApplicationException e) { fail("Error in visitor:" + e.getLocalizedMessage()); } String info = "GetSerialized(" + expression + ")-->"; dout(" " + info + "Expected: " + expected + " Actual: " + actual); assertEquals(info, expected, actual); return this; } public ParserTool left() { switch (curNode.getKind()) { case BINARY: curNode = ((BinaryExpressionImpl) curNode).getLeftOperand(); break; case MEMBER: curNode = ((MemberExpressionImpl) curNode).getPath(); break; case LITERAL: case METHOD: case PROPERTY: String info = "param(" + expression + ")-->"; info = " " + info + "Expected: " + ExpressionKind.BINARY.toString() + " or " + ExpressionKind.MEMBER.toString() + " Actual: " + curNode.getKind(); dout(info); fail(info); break; case UNARY: curNode = ((UnaryExpressionImpl) curNode).getOperand(); break; default: break; } return this; } public ParserTool right() { switch (curNode.getKind()) { case BINARY: curNode = ((BinaryExpressionImpl) curNode).getRightOperand(); break; case MEMBER: curNode = ((MemberExpressionImpl) curNode).getProperty(); break; case LITERAL: case METHOD: case PROPERTY: String info = "param(" + expression + ")-->"; info = " " + info + "Expected: " + ExpressionKind.BINARY.toString() + " or " + ExpressionKind.MEMBER.toString() + " Actual: " + curNode.getKind(); dout(info); fail(info); break; case UNARY: curNode = ((UnaryExpressionImpl) curNode).getOperand(); break; default: break; } return this; } public ParserTool order(final int i) { if (curNode.getKind() != ExpressionKind.ORDERBY) { String info = "param(" + expression + ")-->"; info = " " + info + "Expected: " + ExpressionKind.ORDERBY.toString() + " Actual: " + curNode.getKind(); dout(info); fail(info); } OrderByExpressionImpl orderByExpressionImpl = (OrderByExpressionImpl) curNode; if (i >= orderByExpressionImpl.getOrdersCount()) { String info = "param(" + expression + ")-->"; info = " " + info + "Too wrong index! Expected max: " + orderByExpressionImpl.getOrdersCount() + " Actual: " + i; dout(info); fail(info); } curNode = orderByExpressionImpl.getOrders().get(i); return this; } public ParserTool param(final int i) { if (curNode.getKind() != ExpressionKind.METHOD) { String info = "param(" + expression + ")-->"; info = " " + info + "Expected: " + ExpressionKind.METHOD.toString() + " Actual: " + curNode.getKind(); dout(info); fail(info); } MethodExpressionImpl methodExpressionImpl = (MethodExpressionImpl) curNode; if (i >= methodExpressionImpl.getParameterCount()) { String info = "param(" + expression + ")-->"; info = " " + info + "Too wrong index! Expected max: " + methodExpressionImpl.getParameterCount() + " Actual: " + i; dout(info); fail(info); } curNode = methodExpressionImpl.getParameters().get(i); return this; } public ParserTool root() { curNode = tree; return this; } static public String compress(final String expression) { String ret = ""; char[] charArray = expression.trim().toCharArray(); Character oldChar = null; for (char x : charArray) { if ((x != ' ') || (oldChar == null) || (oldChar != ' ')) { ret += x; } oldChar = x; } ret = ret.replace("{ ", "{"); ret = ret.replace(" }", "}"); return ret; } public static class testParserTool { @Test public void testCompr() { // leading and trainling spaces assertEquals("Error in parsertool", compress(" a"), "a"); assertEquals("Error in parsertool", compress("a "), "a"); assertEquals("Error in parsertool", compress(" a "), "a"); assertEquals("Error in parsertool", compress("{ a}"), "{a}"); assertEquals("Error in parsertool", compress("{ a}"), "{a}"); assertEquals("Error in parsertool", compress("{a }"), "{a}"); assertEquals("Error in parsertool", compress("{ a }"), "{a}"); assertEquals("Error in parsertool", compress("{ a }"), "{a}"); assertEquals("Error in parsertool", compress("{ a a }"), "{a a}"); assertEquals("Error in parsertool", compress("{ a a }"), "{a a}"); assertEquals("Error in parsertool", compress(" { a a } "), "{a a}"); assertEquals("Error in parsertool", compress(" { a { } a } "), "{a {} a}"); } } public ParserTool exRoot() { return this; } }