[OLINGO-196] Improved innerError handling (XML/JSON)

Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/6a5fc6ce
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/6a5fc6ce
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/6a5fc6ce

Branch: refs/heads/Olingo-129_PocJpaDataStore
Commit: 6a5fc6ce6d41329360f63688fb8bc2ddf14c63b6
Parents: c8cdf37
Author: Michael Bolz <[email protected]>
Authored: Wed Mar 26 15:10:37 2014 +0100
Committer: Michael Bolz <[email protected]>
Committed: Wed Mar 26 15:10:37 2014 +0100

----------------------------------------------------------------------
 .../ep/consumer/JsonErrorDocumentConsumer.java  |  49 +++++++-
 .../ep/consumer/XmlErrorDocumentConsumer.java   |  31 ++++-
 .../consumer/JsonErrorDocumentConsumerTest.java |  44 +++++++
 .../consumer/XmlErrorDocumentConsumerTest.java  | 124 +++++++++++--------
 4 files changed, 188 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/6a5fc6ce/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumer.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumer.java
 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumer.java
index 9348b2a..5f5610b 100644
--- 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumer.java
+++ 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumer.java
@@ -127,12 +127,49 @@ public class JsonErrorDocumentConsumer {
   }
 
   private void parseInnerError(final JsonReader reader, final 
ODataErrorContext errorContext) throws IOException {
-    // implementation for parse content as provided by 
JsonErrorDocumentProducer
-    String innerError = reader.nextString();
-    errorContext.setInnerError(innerError);
-    // implementation for OData v2 Section 2.2.8.1.2 JSON Error Response
-    // (RFC4627 Section 2.2 -> https://www.ietf.org/rfc/rfc4627.txt))
-    // currently not provided
+    if(reader.peek() == JsonToken.STRING) {
+      // implementation for parse content as provided by 
JsonErrorDocumentProducer
+      String innerError = reader.nextString();
+      errorContext.setInnerError(innerError);
+    } else if(reader.peek() == JsonToken.BEGIN_OBJECT) {
+      // implementation for OData v2 Section 2.2.8.1.2 JSON Error Response
+      // (RFC4627 Section 2.2 -> https://www.ietf.org/rfc/rfc4627.txt))
+      // currently partial provided
+      errorContext.setInnerError(readJson(reader));
+    }
+  }
+
+
+  private String readJson(JsonReader reader) throws  IOException {
+    StringBuilder sb = new StringBuilder();
+
+    while(reader.hasNext()) {
+      if(reader.peek() == JsonToken.NAME) {
+        if(sb.length() > 0) {
+          sb.append(",");
+        }
+        String name = reader.nextName();
+        sb.append("\"").append(name).append("\"").append(":");
+      } else if(reader.peek() == JsonToken.BEGIN_OBJECT) {
+        reader.beginObject();
+        sb.append("{");
+        sb.append(readJson(reader));
+        sb.append("}");
+        reader.endObject();
+      } else if(reader.peek() == JsonToken.BEGIN_ARRAY) {
+        reader.beginArray();
+        sb.append("[");
+        sb.append(readJson(reader));
+        sb.append("]");
+        reader.endArray();
+      } else {
+        sb.append("\"");
+        sb.append(reader.nextString());
+        sb.append("\"");
+      }
+    }
+
+    return sb.toString();
   }
 
   private void parseMessage(final JsonReader reader, final ODataErrorContext 
errorContext)

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/6a5fc6ce/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
index d584951..4b6b8ac 100644
--- 
a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
+++ 
b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumer.java
@@ -136,16 +136,43 @@ public class XmlErrorDocumentConsumer {
   }
 
   private boolean notFinished(final XMLStreamReader reader) throws 
XMLStreamException {
-    boolean finished = reader.isEndElement() && 
FormatXml.M_ERROR.equals(reader.getLocalName());
+    return notFinished(reader, FormatXml.M_ERROR);
+  }
+
+  private boolean notFinished(final XMLStreamReader reader, String tagName) 
throws XMLStreamException {
+    boolean finished = reader.isEndElement() && 
tagName.equals(reader.getLocalName());
     return !finished && reader.hasNext();
   }
 
   private void handleInnerError(final XMLStreamReader reader, final 
ODataErrorContext errorContext)
       throws XMLStreamException {
-    String innerError = reader.getElementText();
+    reader.next();
+    String innerError = null;
+    if(reader.isCharacters()) {
+      innerError = reader.getText();
+    } else if(reader.isStartElement()) {
+      innerError = handleComplexInnerError(reader);
+    }
     errorContext.setInnerError(innerError);
   }
 
+  private String handleComplexInnerError(XMLStreamReader reader) throws 
XMLStreamException {
+    StringBuilder sb = new StringBuilder();
+    while(notFinished(reader, FormatXml.M_INNER_ERROR)) {
+      if(reader.hasName()) {
+        sb.append("<");
+        if(reader.isEndElement()) {
+          sb.append("/");
+        }
+        sb.append(reader.getLocalName()).append(">");
+      } else if(reader.isCharacters()) {
+        sb.append(reader.getText());
+      }
+      reader.next();
+    }
+    return sb.toString();
+  }
+
   private void handleMessage(final XMLStreamReader reader, final 
ODataErrorContext errorContext)
       throws XMLStreamException {
     String lang = reader.getAttributeValue(Edm.NAMESPACE_XML_1998, 
FormatXml.XML_LANG);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/6a5fc6ce/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumerTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumerTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumerTest.java
index 204498d..9776289 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumerTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonErrorDocumentConsumerTest.java
@@ -42,6 +42,15 @@ public class JsonErrorDocumentConsumerTest extends 
AbstractConsumerTest {
       "\"message\":{\"lang\":null,\"value\":\"Message\"}}}";
   private static final String JSON_ERROR_DOCUMENT_INNER_ERROR = 
"{\"error\":{\"code\":\"ErrorCode\"," +
       "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, 
\"innererror\":\"Some InnerError\"}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX = 
"{\"error\":{\"code\":\"ErrorCode\"," +
+          "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+          "\"innererror\":{\"moreInner\":\"More Inner Error\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_OBJECT = 
"{\"error\":{\"code\":\"ErrorCode\"," +
+          "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+          "\"innererror\":{\"moreInner\":\"More Inner 
Error\",\"secondInner\":\"Second\"}}}";
+  private static final String JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_ARRAY = 
"{\"error\":{\"code\":\"ErrorCode\"," +
+          "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}, " +
+          "\"innererror\":{\"innerArray\":[\"More Inner 
Error\",\"Second\"]}}}";
   private static final String JSON_ERROR_DOCUMENT_INVALID_JSON = 
"\"error\":{\"code\":\"ErrorCode\"," +
       "\"message\":{\"lang\":\"en-US\",\"value\":\"Message\"}}}";
   /* error document with name 'locale' instead of 'lang' for message object */
@@ -90,6 +99,41 @@ public class JsonErrorDocumentConsumerTest extends 
AbstractConsumerTest {
     assertEquals("Wrong inner error", "Some InnerError", 
error.getInnerError());
   }
 
+  @Test
+  public void innerErrorComplex() throws Exception {
+    InputStream in = 
StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", 
error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "{\"moreInner\":\"More Inner Error\"}", 
error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexObject() throws Exception {
+    InputStream in = 
StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_OBJECT);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", 
error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error",
+            "{\"moreInner\":\"More Inner Error\",\"secondInner\":\"Second\"}", 
error.getInnerError());
+  }
+
+  @Test
+  public void innerErrorComplexArray() throws Exception {
+    InputStream in = 
StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INNER_ERROR_COMPLEX_ARRAY);
+    ODataErrorContext error = jedc.readError(in);
+
+    assertEquals("Wrong content type", "application/json", 
error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error",
+            "{\"innerArray\":[\"More Inner Error\"\"Second\"]}", 
error.getInnerError());
+  }
+
   @Test(expected = EntityProviderException.class)
   public void invalidJson() throws EntityProviderException {
     InputStream in = 
StringHelper.encapsulate(JSON_ERROR_DOCUMENT_INVALID_JSON);

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/6a5fc6ce/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
----------------------------------------------------------------------
diff --git 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
index 55ceb1d..ff3cc4f 100644
--- 
a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
+++ 
b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/XmlErrorDocumentConsumerTest.java
@@ -6,9 +6,9 @@
  * 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
@@ -32,66 +32,75 @@ import 
org.apache.olingo.odata2.testutil.helper.StringHelper;
 import org.junit.Test;
 
 /**
- *  
+ *
  */
 public class XmlErrorDocumentConsumerTest extends AbstractConsumerTest {
 
   private static final String XML_ERROR_DOCUMENT_SIMPLE =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:lang=\"en-US\">Message</message>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_NULL_LOCALE =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:lang=\"\">Message</message>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"\">Message</message>\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_INNER_ERROR =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:lang=\"en-US\">Message</message>\n" +
-          "<innererror>Some InnerError</innererror>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "<innererror>Some InnerError</innererror>\n" +
+                  "</error>";
+  private static final String XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX =
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "<innererror>" +
+                  "<moreInner>More Inner Error</moreInner>" +
+                  "</innererror>\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_INVALID_XML =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</CODE>\n" +
-          "\t<message xml:lang=\"en-US\">Message</message>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</CODE>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "</error>";
   /* error document with name 'locale' instead of 'lang' for message object */
   private static final String XML_ERROR_DOCUMENT_UNKNOWN_CONTENT =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:locale=\"en-US\">Message</message>\n" +
-          "\t<privateMessage>Secret</privateMessage>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:locale=\"en-US\">Message</message>\n" +
+                  "\t<privateMessage>Secret</privateMessage>\n" +
+                  "</error>";
   /* error document without value for message object */
   private static final String XML_ERROR_DOCUMENT_EMPTY_MESSAGE =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:lang=\"en-US\" />\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\" />\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_MISSING_MESSAGE =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_MISSING_CODE =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<message xml:lang=\"en-US\">Message</message>\n" +
-          "</error>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<error 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "</error>";
   private static final String XML_ERROR_DOCUMENT_MISSING_ERROR =
-      "<?xml version='1.0' encoding='UTF-8'?>\n" +
-          "<errorForMe 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
-          "\t<code>ErrorCode</code>\n" +
-          "\t<message xml:lang=\"en-US\">Message</message>\n" +
-          "</errorForMe>";
+          "<?xml version='1.0' encoding='UTF-8'?>\n" +
+                  "<errorForMe 
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\";>\n" +
+                  "\t<code>ErrorCode</code>\n" +
+                  "\t<message xml:lang=\"en-US\">Message</message>\n" +
+                  "</errorForMe>";
   private XmlErrorDocumentConsumer xedc = new XmlErrorDocumentConsumer();
 
   @Test
@@ -139,6 +148,17 @@ public class XmlErrorDocumentConsumerTest extends 
AbstractConsumerTest {
     assertEquals("Wrong inner error", "Some InnerError", 
error.getInnerError());
   }
 
+  @Test
+  public void innerErrorComplex() throws Exception {
+    InputStream in = 
StringHelper.encapsulate(XML_ERROR_DOCUMENT_INNER_ERROR_COMPLEX);
+    ODataErrorContext error = xedc.readError(in);
+
+    assertEquals("Wrong content type", "application/xml", 
error.getContentType());
+    assertEquals("Wrong message", "Message", error.getMessage());
+    assertEquals("Wrong error code", "ErrorCode", error.getErrorCode());
+    assertEquals("Wrong inner error", "<moreInner>More Inner 
Error</moreInner>", error.getInnerError());
+  }
+
   @Test(expected = EntityProviderException.class)
   public void invalidJson() throws EntityProviderException {
     InputStream in = StringHelper.encapsulate(XML_ERROR_DOCUMENT_INVALID_XML);
@@ -159,7 +179,7 @@ public class XmlErrorDocumentConsumerTest extends 
AbstractConsumerTest {
       fail("Expected exception was not thrown");
     } catch (EntityProviderException e) {
       assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
-          EntityProviderException.INVALID_STATE, e.getMessageReference());
+              EntityProviderException.INVALID_STATE, e.getMessageReference());
       throw e;
     }
   }
@@ -195,7 +215,7 @@ public class XmlErrorDocumentConsumerTest extends 
AbstractConsumerTest {
       fail("Expected exception was not thrown");
     } catch (EntityProviderException e) {
       assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
-          EntityProviderException.INVALID_STATE, e.getMessageReference());
+              EntityProviderException.INVALID_STATE, e.getMessageReference());
       throw e;
     }
   }
@@ -208,7 +228,7 @@ public class XmlErrorDocumentConsumerTest extends 
AbstractConsumerTest {
       fail("Expected exception was not thrown");
     } catch (EntityProviderException e) {
       assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
-          EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+              EntityProviderException.MISSING_PROPERTY, 
e.getMessageReference());
       assertTrue(e.getMessage().contains("code"));
       throw e;
     }
@@ -222,7 +242,7 @@ public class XmlErrorDocumentConsumerTest extends 
AbstractConsumerTest {
       fail("Expected exception was not thrown");
     } catch (EntityProviderException e) {
       assertEquals("Got wrong exception: " + e.getMessageReference().getKey(),
-          EntityProviderException.MISSING_PROPERTY, e.getMessageReference());
+              EntityProviderException.MISSING_PROPERTY, 
e.getMessageReference());
       assertTrue(e.getMessage().contains("message"));
       throw e;
     }

Reply via email to