Repository: olingo-odata4 Updated Branches: refs/heads/master ee3501dd8 -> 233ea61f3
[OLINGO-568] Debug-support output for $search Signed-off-by: Christian Amend <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/233ea61f Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/233ea61f Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/233ea61f Branch: refs/heads/master Commit: 233ea61f3ba6cdaf1cd7891695b045b799fb7a58 Parents: ee3501d Author: Klaus Straubinger <[email protected]> Authored: Thu Nov 19 15:16:02 2015 +0100 Committer: Christian Amend <[email protected]> Committed: Thu Nov 19 15:44:58 2015 +0100 ---------------------------------------------------------------------- .../core/debug/DebugResponseHelperImpl.java | 36 +- .../olingo/server/core/debug/DebugTabBody.java | 22 +- .../olingo/server/core/debug/DebugTabUri.java | 103 ++++-- .../core/debug/ExpressionJsonVisitor.java | 337 +++++++------------ .../server/core/debug/JsonStreamWriter.java | 175 ---------- 5 files changed, 211 insertions(+), 462 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/233ea61f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugResponseHelperImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugResponseHelperImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugResponseHelperImpl.java index 4cc17e6..3fc797b 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugResponseHelperImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugResponseHelperImpl.java @@ -29,7 +29,6 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.commons.api.format.ContentType; @@ -42,9 +41,8 @@ import org.apache.olingo.server.api.debug.DebugSupport; import org.apache.olingo.server.api.debug.RuntimeMeasurement; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; -import com.fasterxml.jackson.core.JsonEncoding; -import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; public class DebugResponseHelperImpl implements DebugResponseHelper { @@ -141,7 +139,8 @@ public class DebugResponseHelperImpl implements DebugResponseHelper { try { CircleStreamBuffer csb = new CircleStreamBuffer(); outputStream = csb.getOutputStream(); - JsonGenerator gen = new JsonFactory().createGenerator(outputStream, JsonEncoding.UTF8); + // Create JSON generator (the object mapper is necessary to write expression trees). + JsonGenerator gen = new ObjectMapper().getFactory().createGenerator(outputStream); gen.writeStartObject(); DebugTab requestInfo = parts.get(0); @@ -232,11 +231,8 @@ public class DebugResponseHelperImpl implements DebugResponseHelper { .append("tbody > tr:hover { background-color: #cccccc; }\n") .append(".code { font-family: \"Courier New\", monospace; }\n") .append(".code, .tree li { line-height: 15px; }\n") - .append(".code a { text-decoration: underline; color: #666666; }\n") - .append(".xml .ns { font-style: italic; color: #999999; }\n") - .append("ul, .tree { list-style-type: none; }\n") - .append("div > ul.expr, div > .expand, .tree { padding-left: 0; }\n") - .append(".expr, .expand, .null, .numeric { padding-left: 1.5em; }\n") + .append("ul, .tree { padding-left: 0; list-style-type: none; }\n") + .append(".null, .numeric { padding-left: 1.5em; }\n") .append(".json { white-space: pre-wrap; }\n") .append("</style>\n") .append("</head>\n") @@ -269,12 +265,12 @@ public class DebugResponseHelperImpl implements DebugResponseHelper { gen.writeNull(); } else { gen.writeStartObject(); - for (Map.Entry<String, String> entry : entries.entrySet()) { - gen.writeFieldName(entry.getKey()); - if (entry.getValue() == null) { + for (final String name : entries.keySet()) { + gen.writeFieldName(name); + if (entries.get(name) == null) { gen.writeNull(); } else { - gen.writeString(entry.getValue()); + gen.writeString(entries.get(name)); } } gen.writeEndObject(); @@ -286,15 +282,11 @@ public class DebugResponseHelperImpl implements DebugResponseHelper { .append("<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n") .append("</thead>\n<tbody>\n"); if (entries != null && !entries.isEmpty()) { - for (final Entry<String, String> entry : entries.entrySet()) { - writer.append("<tr><td class=\"name\">").append(entry.getKey()).append("</td>") - .append("<td class=\"value\">"); - if (entry.getValue() != null) { - writer.append(escapeHtml(entry.getValue())); - } else { - writer.append("null"); - } - writer.append("</td></tr>\n"); + for (final String name : entries.keySet()) { + writer.append("<tr><td class=\"name\">").append(name).append("</td>") + .append("<td class=\"value\">") + .append(escapeHtml(entries.get(name))) + .append("</td></tr>\n"); } } writer.append("</tbody>\n</table>\n"); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/233ea61f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java index d290fc3..c75b6f6 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java @@ -18,19 +18,16 @@ */ package org.apache.olingo.server.core.debug; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Writer; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; import org.apache.commons.codec.binary.Base64; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.core.deserializer.FixedFormatDeserializerImpl; import com.fasterxml.jackson.core.JsonGenerator; @@ -134,20 +131,11 @@ public class DebugTabBody implements DebugTab { } private byte[] streamToBytes(InputStream input) { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); if (input != null) { try { - ByteBuffer inBuffer = ByteBuffer.allocate(8192); - ReadableByteChannel ic = Channels.newChannel(input); - WritableByteChannel oc = Channels.newChannel(buffer); - while (ic.read(inBuffer) > 0) { - inBuffer.flip(); - oc.write(inBuffer); - inBuffer.rewind(); - } - return buffer.toByteArray(); - } catch (IOException e) { - throw new ODataRuntimeException("Error on reading request content"); + return new FixedFormatDeserializerImpl().binary(input); + } catch (final DeserializerException e) { + throw new ODataRuntimeException("Error on reading request content", e); } } return null; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/233ea61f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java index 66c755a..d36221d 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java @@ -39,15 +39,18 @@ import org.apache.olingo.server.api.uri.queryoption.FilterOption; import org.apache.olingo.server.api.uri.queryoption.OrderByItem; import org.apache.olingo.server.api.uri.queryoption.OrderByOption; import org.apache.olingo.server.api.uri.queryoption.QueryOption; +import org.apache.olingo.server.api.uri.queryoption.SearchOption; import org.apache.olingo.server.api.uri.queryoption.SelectItem; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.api.uri.queryoption.SkipOption; import org.apache.olingo.server.api.uri.queryoption.TopOption; import org.apache.olingo.server.api.uri.queryoption.expression.Expression; +import org.apache.olingo.server.api.uri.queryoption.search.SearchExpression; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; /** * URI parser debug information. @@ -87,7 +90,8 @@ public class DebugTabUri implements DebugTab { } appendCommonJsonObjects(gen, uriInfo.getCountOption(), uriInfo.getSkipOption(), uriInfo.getTopOption(), - uriInfo.getFilterOption(), uriInfo.getOrderByOption(), uriInfo.getSelectOption(), uriInfo.getExpandOption()); + uriInfo.getFilterOption(), uriInfo.getOrderByOption(), uriInfo.getSelectOption(), uriInfo.getExpandOption(), + uriInfo.getSearchOption()); if (!uriInfo.getAliases().isEmpty()) { gen.writeFieldName("aliases"); @@ -104,7 +108,7 @@ public class DebugTabUri implements DebugTab { private void appendCommonJsonObjects(JsonGenerator gen, CountOption countOption, SkipOption skipOption, TopOption topOption, FilterOption filterOption, OrderByOption orderByOption, SelectOption selectOption, - ExpandOption expandOption) + ExpandOption expandOption, SearchOption searchOption) throws IOException { if (countOption != null) { gen.writeBooleanField("isCount", countOption.getValue()); @@ -120,7 +124,7 @@ public class DebugTabUri implements DebugTab { if (filterOption != null) { gen.writeFieldName("filter"); - appendJsonExpressionString(gen, filterOption.getExpression()); + appendExpressionJson(gen, filterOption.getExpression()); } if (orderByOption != null && !orderByOption.getOrders().isEmpty()) { @@ -141,6 +145,11 @@ public class DebugTabUri implements DebugTab { gen.writeFieldName("expand"); appendExpandedPropertiesJson(gen, expandOption.getExpandItems()); } + + if (searchOption != null) { + gen.writeFieldName("search"); + appendSearchJson(gen, searchOption.getSearchExpression()); + } } private void appendURIResourceParts(JsonGenerator gen, List<UriResource> uriResourceParts) throws IOException { @@ -182,7 +191,7 @@ public class DebugTabUri implements DebugTab { gen.writeStringField("nodeType", "order"); gen.writeStringField("sortorder", item.isDescending() ? "desc" : "asc"); gen.writeFieldName("expression"); - appendJsonExpressionString(gen, item.getExpression()); + appendExpressionJson(gen, item.getExpression()); gen.writeEndObject(); } gen.writeEndArray(); @@ -221,24 +230,24 @@ public class DebugTabUri implements DebugTab { gen.writeNumberField("levels", item.getLevelsOption().getValue()); } - appendCommonJsonObjects(gen, item.getCountOption(), item.getSkipOption(), item.getTopOption(), item - .getFilterOption(), item.getOrderByOption(), item.getSelectOption(), item.getExpandOption()); + appendCommonJsonObjects(gen, item.getCountOption(), item.getSkipOption(), item.getTopOption(), + item.getFilterOption(), item.getOrderByOption(), item.getSelectOption(), item.getExpandOption(), + item.getSearchOption()); gen.writeEndObject(); } - private void appendJsonExpressionString(JsonGenerator gen, Expression expression) throws IOException { + private void appendExpressionJson(JsonGenerator gen, final Expression expression) throws IOException { if (expression == null) { gen.writeNull(); - return; - } - String expressionJsonString; - try { - expressionJsonString = expression.accept(new ExpressionJsonVisitor()); - } catch (final ODataException e) { - expressionJsonString = "Exception in Debug Filter visitor occurred: " + e.getMessage(); + } else { + try { + final JsonNode tree = expression.accept(new ExpressionJsonVisitor()); + gen.writeTree(tree); + } catch (final ODataException e) { + gen.writeString("Exception in Debug Expression visitor occurred: " + e.getMessage()); + } } - gen.writeRawValue(expressionJsonString); } private void appendSelectedPropertiesJson(JsonGenerator gen, List<SelectItem> selectItems) throws IOException { @@ -270,28 +279,61 @@ public class DebugTabUri implements DebugTab { return selectedProperty; } + private void appendSearchJson(JsonGenerator json, final SearchExpression searchExpression) throws IOException { + json.writeStartObject(); + if (searchExpression.isSearchTerm()) { + json.writeStringField("nodeType", "searchTerm"); + json.writeStringField("searchTerm", searchExpression.asSearchTerm().getSearchTerm()); + } else if (searchExpression.isSearchBinary()) { + json.writeStringField("nodeType", "binary"); + json.writeStringField("operator", searchExpression.asSearchBinary().getOperator().toString()); + json.writeFieldName("left"); + appendSearchJson(json, searchExpression.asSearchBinary().getLeftOperand()); + json.writeFieldName("right"); + appendSearchJson(json, searchExpression.asSearchBinary().getRightOperand()); + } else if (searchExpression.isSearchUnary()) { + json.writeStringField("nodeType", "unary"); + json.writeStringField("operator", searchExpression.asSearchUnary().getOperator().toString()); + json.writeFieldName("operand"); + appendSearchJson(json, searchExpression.asSearchUnary().getOperand()); + } + json.writeEndObject(); + } + @Override public void appendHtml(final Writer writer) throws IOException { + // factory for JSON generators (the object mapper is necessary to write expression trees) + final JsonFactory jsonFactory = new ObjectMapper().getFactory(); + writer.append("<h2>Resource Path</h2>\n") - .append("<ul class=\"json\">\n<li>\n"); - JsonGenerator json = new JsonFactory().createGenerator(writer).setPrettyPrinter(new DefaultPrettyPrinter()); + .append("<ul>\n<li class=\"json\">"); + JsonGenerator json = jsonFactory.createGenerator(writer).useDefaultPrettyPrinter(); appendURIResourceParts(json, uriInfo.getUriResourceParts()); json.close(); writer.append("\n</li>\n</ul>\n"); + if (uriInfo.getSearchOption() != null) { + writer.append("<h2>Search Option</h2>\n") + .append("<ul>\n<li class=\"json\">"); + json = jsonFactory.createGenerator(writer).useDefaultPrettyPrinter(); + appendSearchJson(json, uriInfo.getSearchOption().getSearchExpression()); + json.close(); + writer.append("\n</li>\n</ul>\n"); + } + if (uriInfo.getFilterOption() != null) { writer.append("<h2>Filter Option</h2>\n") - .append("<ul class=\"json\">\n<li>\n"); - json = new JsonFactory().createGenerator(writer); - appendJsonExpressionString(json, uriInfo.getFilterOption().getExpression()); + .append("<ul>\n<li class=\"json\">"); + json = jsonFactory.createGenerator(writer).useDefaultPrettyPrinter(); + appendExpressionJson(json, uriInfo.getFilterOption().getExpression()); json.close(); writer.append("\n</li>\n</ul>\n"); } if (uriInfo.getOrderByOption() != null) { writer.append("<h2>OrderBy Option</h2>\n") - .append("<ul class=\"json\">\n<li>\n"); - json = new JsonFactory().createGenerator(writer); + .append("<ul>\n<li class=\"json\">"); + json = jsonFactory.createGenerator(writer).useDefaultPrettyPrinter(); appendOrderByItemsJson(json, uriInfo.getOrderByOption().getOrders()); json.close(); writer.append("\n</li>\n</ul>\n"); @@ -299,8 +341,8 @@ public class DebugTabUri implements DebugTab { if (uriInfo.getExpandOption() != null) { writer.append("<h2>Expand Option</h2>\n") - .append("<ul class=\"json\">\n<li>\n"); - json = new JsonFactory().createGenerator(writer); + .append("<ul>\n<li class=\"json\">"); + json = jsonFactory.createGenerator(writer).useDefaultPrettyPrinter(); appendExpandedPropertiesJson(json, uriInfo.getExpandOption().getExpandItems()); json.close(); writer.append("\n</li>\n</ul>\n"); @@ -315,23 +357,18 @@ public class DebugTabUri implements DebugTab { writer.append("</ul>\n"); } - if (uriInfo.getSearchOption() != null) { - writer.append("<h2>Search Option</h2>\n") - .append("<p>not yet shown here</p>\n"); - } - - if (uriInfo.getSkipOption() != null + if (uriInfo.getCountOption() != null + || uriInfo.getSkipOption() != null || uriInfo.getSkipTokenOption() != null || uriInfo.getTopOption() != null - || uriInfo.getCountOption() != null || uriInfo.getFormatOption() != null || uriInfo.getIdOption() != null) { writer.append("<h2>Unstructured System Query Options</h2>\n"); DebugResponseHelperImpl.appendHtmlTable(writer, getQueryOptionsMap(Arrays.asList( + uriInfo.getCountOption(), uriInfo.getSkipOption(), uriInfo.getSkipTokenOption(), uriInfo.getTopOption(), - uriInfo.getCountOption(), uriInfo.getFormatOption(), uriInfo.getIdOption()))); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/233ea61f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ExpressionJsonVisitor.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ExpressionJsonVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ExpressionJsonVisitor.java index b09a991..5b8ebc8 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ExpressionJsonVisitor.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ExpressionJsonVisitor.java @@ -18,8 +18,6 @@ */ package org.apache.olingo.server.core.debug; -import java.io.IOException; -import java.io.StringWriter; import java.util.List; import org.apache.olingo.commons.api.edm.EdmEnumType; @@ -38,21 +36,25 @@ import org.apache.olingo.server.api.uri.queryoption.expression.Literal; import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + /** - * A custom expression visitor which writes down the tree from top to bottom + * A custom expression visitor which converts the tree into a {@link JsonNode} tree. */ -public class ExpressionJsonVisitor implements ExpressionVisitor<String> { +public class ExpressionJsonVisitor implements ExpressionVisitor<JsonNode> { private static final String ANY_NAME = "ANY"; private static final String ALL_NAME = "ALL"; - private static final String STRING_NAME = "String"; private static final String UNKNOWN_NAME = "unknown"; + private static final String STRING_NAME = "String"; private static final String BOOLEAN_NAME = "Boolean"; private static final String NUMBER_NAME = "Number"; private static final String ENUM_NAME = "enum"; private static final String VALUES_NAME = "values"; private static final String NAME_NAME = "name"; - private static final String LAMBDA_REFERENCE_NAME = "lambdaReference"; private static final String ALIAS_NAME = "alias"; private static final String RESOURCE_SEGMENTS_NAME = "resourceSegments"; private static final String MEMBER_NAME = "member"; @@ -61,11 +63,11 @@ public class ExpressionJsonVisitor implements ExpressionVisitor<String> { private static final String EXPRESSION_NAME = "expression"; private static final String LAMBDA_VARIABLE_NAME = "lambdaVariable"; private static final String LAMBDA_FUNCTION_NAME = "lambdaFunction"; + private static final String LAMBDA_REFERENCE_NAME = "lambdaReference"; private static final String UNARY_NAME = "unary"; private static final String BINARY_NAME = "binary"; private static final String LEFT_NODE_NAME = "left"; private static final String RIGHT_NODE_NAME = "right"; - private static final String IO_EXCEPTION_OCCURRED_MESSAGE = "IOException occurred"; private static final String PARAMETERS_NAME = "parameters"; private static final String METHOD_NAME = "method"; private static final String OPERAND_NAME = "operand"; @@ -73,203 +75,133 @@ public class ExpressionJsonVisitor implements ExpressionVisitor<String> { private static final String OPERATOR_NAME = "operator"; private static final String NODE_TYPE_NAME = "nodeType"; + private final JsonNodeFactory nodeFactory = JsonNodeFactory.instance; + @Override - public String visitBinaryOperator(BinaryOperatorKind operator, String left, String right) + public JsonNode visitBinaryOperator(final BinaryOperatorKind operator, final JsonNode left, final JsonNode right) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, BINARY_NAME).separator().namedStringValue( - OPERATOR_NAME, operator.toString()).separator().namedStringValueRaw(TYPE_NAME, getType(operator)).separator() - .name(LEFT_NODE_NAME).unquotedValue(left).separator().name(RIGHT_NODE_NAME).unquotedValue(right).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + ObjectNode result = nodeFactory.objectNode() + .put(NODE_TYPE_NAME, BINARY_NAME) + .put(OPERATOR_NAME, operator.toString()) + .put(TYPE_NAME, getType(operator)); + result.set(LEFT_NODE_NAME, left); + result.set(RIGHT_NODE_NAME, right); + return result; } @Override - public String visitUnaryOperator(UnaryOperatorKind operator, String operand) throws ExpressionVisitException, - ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, UNARY_NAME).separator() - .namedStringValueRaw(OPERATOR_NAME, operator.toString()).separator().namedStringValueRaw(TYPE_NAME, - getType(operator)).separator().name(OPERAND_NAME).unquotedValue(operand).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + public JsonNode visitUnaryOperator(final UnaryOperatorKind operator, final JsonNode operand) + throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, UNARY_NAME) + .put(OPERATOR_NAME, operator.toString()) + .put(TYPE_NAME, getType(operator)) + .set(OPERAND_NAME, operand); } @Override - public String visitMethodCall(MethodKind methodCall, List<String> parameters) throws ExpressionVisitException, - ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, METHOD_NAME).separator() - .namedStringValueRaw(OPERATOR_NAME, methodCall.toString()).separator().namedStringValueRaw(TYPE_NAME, - getType(methodCall)).separator().name(PARAMETERS_NAME).beginArray(); - boolean first = true; - for (String parameter : parameters) { - if (first) { - first = false; - } else { - jsonStreamWriter.separator(); - } - jsonStreamWriter.unquotedValue(parameter); - } - jsonStreamWriter.endArray().endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); + public JsonNode visitMethodCall(final MethodKind methodCall, final List<JsonNode> parameters) + throws ExpressionVisitException, ODataApplicationException { + ObjectNode result = nodeFactory.objectNode() + .put(NODE_TYPE_NAME, METHOD_NAME) + .put(OPERATOR_NAME, methodCall.toString()) + .put(TYPE_NAME, getType(methodCall)); + ArrayNode jsonParameters = result.putArray(PARAMETERS_NAME); + for (final JsonNode parameter : parameters) { + jsonParameters.add(parameter); } + return result; } @Override - public String visitLambdaExpression(String lambdaFunction, String lambdaVariable, Expression expression) - throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, LAMBDA_FUNCTION_NAME).separator() - .namedStringValue(LAMBDA_VARIABLE_NAME, lambdaVariable).separator().name(EXPRESSION_NAME); - - // Write expression string object - String expressionJsonTree = expression.accept(this); - jsonStreamWriter.unquotedValue(expressionJsonTree).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + public JsonNode visitLambdaExpression(final String lambdaFunction, final String lambdaVariable, + final Expression expression) throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, LAMBDA_FUNCTION_NAME) + .put(LAMBDA_VARIABLE_NAME, lambdaVariable) + .set(EXPRESSION_NAME, expression.accept(this)); } @Override - public String visitLiteral(Literal literal) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, LITERAL_NAME).separator().namedStringValueRaw( - TYPE_NAME, getTypeString(literal.getType())).separator().namedStringValue(VALUE_NAME, literal.getText()) - .endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE); - } + public JsonNode visitLiteral(final Literal literal) throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, LITERAL_NAME) + .put(TYPE_NAME, getTypeString(literal.getType())) + .put(VALUE_NAME, literal.getText()); } @Override - public String visitMember(UriInfoResource member) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - List<UriResource> uriResourceParts = member.getUriResourceParts(); - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, MEMBER_NAME).separator() - .namedStringValueRaw(TYPE_NAME, getType(uriResourceParts)).separator(); - - // write all member properties in an array - jsonStreamWriter.name(RESOURCE_SEGMENTS_NAME).beginArray(); - if (uriResourceParts != null) { - boolean first = true; - for (UriResource segment : uriResourceParts) { - if (first) { - first = false; - } else { - jsonStreamWriter.separator(); - } - appendUriResourcePartObject(jsonStreamWriter, segment); + public JsonNode visitMember(final UriInfoResource member) + throws ExpressionVisitException, ODataApplicationException { + final List<UriResource> uriResourceParts = member.getUriResourceParts(); + ObjectNode result = nodeFactory.objectNode() + .put(NODE_TYPE_NAME, MEMBER_NAME) + .put(TYPE_NAME, getType(uriResourceParts)); + ArrayNode segments = result.putArray(RESOURCE_SEGMENTS_NAME); + if (uriResourceParts != null) { + for (final UriResource segment : uriResourceParts) { + if (segment instanceof UriResourceLambdaAll) { + final UriResourceLambdaAll all = (UriResourceLambdaAll) segment; + segments.add(visitLambdaExpression(ALL_NAME, all.getLambdaVariable(), all.getExpression())); + } else if (segment instanceof UriResourceLambdaAny) { + final UriResourceLambdaAny any = (UriResourceLambdaAny) segment; + segments.add(visitLambdaExpression(ANY_NAME, any.getLambdaVariable(), any.getExpression())); + } else if (segment instanceof UriResourcePartTyped) { + final String typeName = ((UriResourcePartTyped) segment).getType() + .getFullQualifiedName().getFullQualifiedNameAsString(); + segments.add(nodeFactory.objectNode() + .put(NODE_TYPE_NAME, segment.getKind().toString()) + .put(NAME_NAME, segment.toString()) + .put(TYPE_NAME, typeName)); + } else { + segments.add(nodeFactory.objectNode() + .put(NODE_TYPE_NAME, segment.getKind().toString()) + .put(NAME_NAME, segment.toString()) + .putNull(TYPE_NAME)); } } - jsonStreamWriter.endArray(); - - jsonStreamWriter.endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); } + return result; } @Override - public String visitAlias(String aliasName) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, ALIAS_NAME).separator() - .namedStringValue(ALIAS_NAME, aliasName).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + public JsonNode visitAlias(final String aliasName) throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, ALIAS_NAME) + .put(ALIAS_NAME, aliasName); } @Override - public String visitTypeLiteral(EdmType type) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, TYPE_NAME).separator() - .namedStringValueRaw(TYPE_NAME, getTypeString(type)).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + public JsonNode visitTypeLiteral(final EdmType type) throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, TYPE_NAME) + .put(TYPE_NAME, getTypeString(type)); } @Override - public String visitLambdaReference(String variableName) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, LAMBDA_REFERENCE_NAME).separator() - .namedStringValueRaw(NAME_NAME, variableName).endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); - } + public JsonNode visitLambdaReference(final String variableName) + throws ExpressionVisitException, ODataApplicationException { + return nodeFactory.objectNode() + .put(NODE_TYPE_NAME, LAMBDA_REFERENCE_NAME) + .put(NAME_NAME, variableName); } @Override - public String visitEnum(EdmEnumType type, List<String> enumValues) throws ExpressionVisitException, + public JsonNode visitEnum(final EdmEnumType type, final List<String> enumValues) throws ExpressionVisitException, ODataApplicationException { - try { - StringWriter writer = new StringWriter(); - JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); - jsonStreamWriter.beginObject().namedStringValueRaw(NODE_TYPE_NAME, ENUM_NAME).separator() - .namedStringValueRaw(TYPE_NAME, getTypeString(type)).separator(); - jsonStreamWriter.name(VALUES_NAME).beginArray(); - if (enumValues != null) { - boolean first = true; - for (String value : enumValues) { - if (first) { - first = false; - } else { - jsonStreamWriter.separator(); - } - jsonStreamWriter.stringValue(value); - } + ObjectNode result = nodeFactory.objectNode() + .put(NODE_TYPE_NAME, ENUM_NAME) + .put(TYPE_NAME, getTypeString(type)); + ArrayNode values = result.putArray(VALUES_NAME); + if (enumValues != null) { + for (final String enumValue : enumValues) { + values.add(enumValue); } - jsonStreamWriter.endArray(); - - jsonStreamWriter.endObject(); - writer.flush(); - return writer.toString(); - } catch (final IOException e) { - throw new ExpressionVisitException(IO_EXCEPTION_OCCURRED_MESSAGE, e); } + return result; } - private String getType(UnaryOperatorKind operator) { + private String getType(final UnaryOperatorKind operator) { switch (operator) { case MINUS: return NUMBER_NAME; @@ -280,72 +212,51 @@ public class ExpressionJsonVisitor implements ExpressionVisitor<String> { } } - private String getType(MethodKind methodCall) { + private String getType(final MethodKind methodCall) { switch (methodCall) { case STARTSWITH: case CONTAINS: case ENDSWITH: case ISOF: + case GEOINTERSECTS: return BOOLEAN_NAME; + case INDEXOF: case LENGTH: case ROUND: case FLOOR: case CEILING: + case YEAR: + case MONTH: case DAY: case HOUR: case MINUTE: - case MONTH: case SECOND: case FRACTIONALSECONDS: + case TOTALOFFSETMINUTES: + case TOTALSECONDS: return NUMBER_NAME; - case CAST: + case CONCAT: - case DATE: - case GEODISTANCE: - case GEOINTERSECTS: - case GEOLENGTH: - case MAXDATETIME: - case MINDATETIME: - case NOW: case SUBSTRING: - case TIME: case TOLOWER: - case TOTALOFFSETMINUTES: - case TOTALSECONDS: case TOUPPER: case TRIM: - case YEAR: return STRING_NAME; + + case CAST: + case GEODISTANCE: + case GEOLENGTH: + case MAXDATETIME: + case MINDATETIME: + case DATE: + case TIME: + case NOW: default: return UNKNOWN_NAME; } } - private void appendUriResourcePartObject(JsonStreamWriter jsonStreamWriter, UriResource segment) throws IOException, - ExpressionVisitException, ODataApplicationException { - if (segment instanceof UriResourceLambdaAll) { - UriResourceLambdaAll all = (UriResourceLambdaAll) segment; - String lambdaJsonObjectString = visitLambdaExpression(ALL_NAME, all.getLambdaVariable(), all.getExpression()); - jsonStreamWriter.unquotedValue(lambdaJsonObjectString); - return; - } else if (segment instanceof UriResourceLambdaAny) { - UriResourceLambdaAny any = (UriResourceLambdaAny) segment; - String lambdaJsonObjectString = visitLambdaExpression(ANY_NAME, any.getLambdaVariable(), any.getExpression()); - jsonStreamWriter.unquotedValue(lambdaJsonObjectString); - return; - } else if (segment instanceof UriResourcePartTyped) { - String typeName = - ((UriResourcePartTyped) segment).getType().getFullQualifiedName().getFullQualifiedNameAsString(); - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, segment.getKind().toString()).separator() - .namedStringValue(NAME_NAME, segment.toString()).separator().namedStringValueRaw(TYPE_NAME, typeName) - .endObject(); - } else { - jsonStreamWriter.beginObject().namedStringValue(NODE_TYPE_NAME, segment.getKind().toString()).separator() - .namedStringValue(NAME_NAME, segment.toString()).separator().namedStringValueRaw(TYPE_NAME, null).endObject(); - } - } - private String getType(BinaryOperatorKind operator) { switch (operator) { case MUL: @@ -371,22 +282,18 @@ public class ExpressionJsonVisitor implements ExpressionVisitor<String> { } } - private String getTypeString(EdmType type) { - if (type == null) { - return null; - } - return type.getFullQualifiedName().getFullQualifiedNameAsString(); + private String getTypeString(final EdmType type) { + return type == null ? null : type.getFullQualifiedName().getFullQualifiedNameAsString(); } - private String getType(List<UriResource> uriResourceParts) { + private String getType(final List<UriResource> uriResourceParts) { if (uriResourceParts == null || uriResourceParts.isEmpty()) { return null; } - UriResource lastSegment = uriResourceParts.get(uriResourceParts.size() - 1); - EdmType type = null; - if (lastSegment instanceof UriResourcePartTyped) { - type = ((UriResourcePartTyped) lastSegment).getType(); - } + final UriResource lastSegment = uriResourceParts.get(uriResourceParts.size() - 1); + final EdmType type = lastSegment instanceof UriResourcePartTyped ? + ((UriResourcePartTyped) lastSegment).getType() : + null; return type == null ? UNKNOWN_NAME : type.getFullQualifiedName().getFullQualifiedNameAsString(); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/233ea61f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/JsonStreamWriter.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/JsonStreamWriter.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/JsonStreamWriter.java deleted file mode 100644 index 113b45d..0000000 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/JsonStreamWriter.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.olingo.server.core.debug; - -import java.io.IOException; -import java.io.Writer; - -/** - * Writes JSON output. - * - */ -class JsonStreamWriter { - private final Writer writer; - - public JsonStreamWriter(final Writer writer) { - this.writer = writer; - } - - public JsonStreamWriter beginObject() throws IOException { - writer.append('{'); - return this; - } - - public JsonStreamWriter endObject() throws IOException { - writer.append('}'); - return this; - } - - public JsonStreamWriter beginArray() throws IOException { - writer.append('['); - return this; - } - - public JsonStreamWriter endArray() throws IOException { - writer.append(']'); - return this; - } - - public JsonStreamWriter name(final String name) throws IOException { - writer.append('"').append(name).append('"').append(':'); - return this; - } - - public JsonStreamWriter unquotedValue(final String value) throws IOException { - writer.append(value == null ? "null" : value); - return this; - } - - public JsonStreamWriter stringValueRaw(final String value) throws IOException { - if (value == null) { - writer.append("null"); - } else { - writer.append('"').append(value).append('"'); - } - return this; - } - - public JsonStreamWriter stringValue(final String value) throws IOException { - if (value == null) { - writer.append("null"); - } else { - writer.append('"'); - escape(value); - writer.append('"'); - } - return this; - } - - public JsonStreamWriter namedStringValueRaw(final String name, final String value) throws IOException { - name(name); - stringValueRaw(value); - return this; - } - - public JsonStreamWriter namedStringValue(final String name, final String value) throws IOException { - name(name); - stringValue(value); - return this; - } - - public JsonStreamWriter separator() throws IOException { - writer.append(','); - return this; - } - - /** - * Writes the JSON-escaped form of a Java String value according to RFC 4627. - * @param value the Java String - * @throws IOException if an I/O error occurs - */ - protected void escape(final String value) throws IOException { - // RFC 4627 says: "All Unicode characters may be placed within the - // quotation marks except for the characters that must be escaped: - // quotation mark, reverse solidus, and the control characters - // (U+0000 through U+001F)." - // All output here is done on character basis which should be faster - // than writing Strings. - for (int i = 0; i < value.length(); i++) { - final char c = value.charAt(i); - switch (c) { - case '\\': - writer.append('\\').append(c); - break; - case '"': - writer.append('\\').append(c); - break; - case '\b': - writer.append('\\').append('b'); - break; - case '\t': - writer.append('\\').append('t'); - break; - case '\n': - writer.append('\\').append('n'); - break; - case '\f': - writer.append('\\').append('f'); - break; - case '\r': - writer.append('\\').append('r'); - break; - case '\u0000': - case '\u0001': - case '\u0002': - case '\u0003': - case '\u0004': - case '\u0005': - case '\u0006': - case '\u0007': - case '\u000B': - case '\u000E': - case '\u000F': - case '\u0010': - case '\u0011': - case '\u0012': - case '\u0013': - case '\u0014': - case '\u0015': - case '\u0016': - case '\u0017': - case '\u0018': - case '\u0019': - case '\u001A': - case '\u001B': - case '\u001C': - case '\u001D': - case '\u001E': - case '\u001F': - final int lastHexDigit = c % 0x10; - writer.append('\\').append('u').append('0').append('0') - .append(c >= '\u0010' ? '1' : '0') - .append((char) ((lastHexDigit > 9 ? 'A' : '0') + lastHexDigit % 10)); - break; - default: - writer.append(c); - } - } - } -}
