mirror of
https://github.com/apache/olingo-odata4.git
synced 2025-03-08 17:59:41 +00:00
[OLINGO-317] Added complex type handling
This commit is contained in:
parent
839e96045a
commit
71bdaed300
@ -18,36 +18,24 @@
|
||||
*/
|
||||
package org.apache.olingo.server.core.serializer.json;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import org.apache.olingo.commons.api.Constants;
|
||||
import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||
import org.apache.olingo.commons.api.data.ContextURL;
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.EntitySet;
|
||||
import org.apache.olingo.commons.api.data.LinkedComplexValue;
|
||||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||
import org.apache.olingo.commons.api.data.*;
|
||||
import org.apache.olingo.commons.api.edm.*;
|
||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
|
||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.List;
|
||||
|
||||
public class ODataJsonSerializer implements ODataSerializer {
|
||||
|
||||
@ -148,38 +136,14 @@ public class ODataJsonSerializer implements ODataSerializer {
|
||||
}
|
||||
} else {
|
||||
if (edmProperty.isPrimitive()) {
|
||||
if (property.isPrimitive()) {
|
||||
writePrimitiveValue(edmProperty, property.asPrimitive(), json);
|
||||
} else if (property.isGeospatial()) {
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
} else if (property.isEnum()) {
|
||||
json.writeString(property.asEnum().toString());
|
||||
} else {
|
||||
throw new ODataRuntimeException("Inconsistent property type!");
|
||||
}
|
||||
handlePrimitive(edmProperty, property, json);
|
||||
} else if (edmProperty.isCollection()) {
|
||||
json.writeStartArray();
|
||||
for (Object value : property.asCollection()) {
|
||||
switch (property.getValueType()) {
|
||||
case COLLECTION_PRIMITIVE:
|
||||
writePrimitiveValue(edmProperty, value, json);
|
||||
break;
|
||||
case COLLECTION_GEOSPATIAL:
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
case COLLECTION_ENUM:
|
||||
json.writeString(value.toString());
|
||||
break;
|
||||
case COLLECTION_LINKED_COMPLEX:
|
||||
writeLinkedComplexValue(edmProperty, (LinkedComplexValue) value, json);
|
||||
break;
|
||||
default:
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
}
|
||||
}
|
||||
json.writeEndArray();
|
||||
handleCollection(edmProperty, property, json);
|
||||
} else {
|
||||
if (property.isLinkedComplex()) {
|
||||
writeLinkedComplexValue(edmProperty, property.asLinkedComplex(), json);
|
||||
writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), json);
|
||||
} else if(property.isComplex()) {
|
||||
writeComplexValue(edmProperty, property.asComplex(), json);
|
||||
} else {
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
}
|
||||
@ -187,6 +151,42 @@ public class ODataJsonSerializer implements ODataSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCollection(EdmProperty edmProperty, Property property, JsonGenerator json)
|
||||
throws IOException, EdmPrimitiveTypeException {
|
||||
json.writeStartArray();
|
||||
for (Object value : property.asCollection()) {
|
||||
switch (property.getValueType()) {
|
||||
case COLLECTION_PRIMITIVE:
|
||||
writePrimitiveValue(edmProperty, value, json);
|
||||
break;
|
||||
case COLLECTION_GEOSPATIAL:
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
case COLLECTION_ENUM:
|
||||
json.writeString(value.toString());
|
||||
break;
|
||||
case COLLECTION_LINKED_COMPLEX:
|
||||
writeComplexValue(edmProperty, ((LinkedComplexValue) value).getValue(), json);
|
||||
break;
|
||||
default:
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
}
|
||||
}
|
||||
json.writeEndArray();
|
||||
}
|
||||
|
||||
private void handlePrimitive(EdmProperty edmProperty, Property property, JsonGenerator json)
|
||||
throws EdmPrimitiveTypeException, IOException {
|
||||
if (property.isPrimitive()) {
|
||||
writePrimitiveValue(edmProperty, property.asPrimitive(), json);
|
||||
} else if (property.isGeospatial()) {
|
||||
throw new ODataRuntimeException("Property type not yet supported!");
|
||||
} else if (property.isEnum()) {
|
||||
json.writeString(property.asEnum().toString());
|
||||
} else {
|
||||
throw new ODataRuntimeException("Inconsistent property type!");
|
||||
}
|
||||
}
|
||||
|
||||
protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue, JsonGenerator json)
|
||||
throws EdmPrimitiveTypeException, IOException {
|
||||
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
|
||||
@ -209,10 +209,9 @@ public class ODataJsonSerializer implements ODataSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLinkedComplexValue(final EdmProperty edmProperty, final LinkedComplexValue linkedComplexValue,
|
||||
JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
|
||||
private void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
|
||||
JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
|
||||
final EdmComplexType type = (EdmComplexType) edmProperty.getType();
|
||||
final List<Property> properties = linkedComplexValue.getValue();
|
||||
json.writeStartObject();
|
||||
for (final String propertyName : type.getPropertyNames()) {
|
||||
final Property property = findProperty(propertyName, properties);
|
||||
|
@ -18,15 +18,10 @@
|
||||
*/
|
||||
package org.apache.olingo.server.core.serializer.json;
|
||||
|
||||
import org.apache.olingo.commons.api.ODataRuntimeException;
|
||||
import org.apache.olingo.commons.api.data.ContextURL;
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.ValueType;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||
import org.apache.olingo.commons.api.edm.EdmType;
|
||||
import org.apache.olingo.commons.api.edm.*;
|
||||
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
|
||||
import org.apache.olingo.commons.core.data.EntityImpl;
|
||||
import org.apache.olingo.commons.core.data.EntitySetImpl;
|
||||
@ -36,17 +31,11 @@ import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -65,11 +54,14 @@ public class ODataJsonSerializerTest {
|
||||
|
||||
public static class TecComplexProperty implements TechProperty {
|
||||
|
||||
final String name;
|
||||
final String typeName;
|
||||
public TecComplexProperty(String typeName, String name) {
|
||||
this.name = name;
|
||||
final String name;
|
||||
final List<EdmProperty> properties;
|
||||
|
||||
public TecComplexProperty(String typeName, String name, List<EdmProperty> propertyNames) {
|
||||
this.typeName = typeName;
|
||||
this.name = name;
|
||||
this.properties = new ArrayList<EdmProperty>(propertyNames);
|
||||
}
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -83,6 +75,9 @@ public class ODataJsonSerializerTest {
|
||||
public EdmPrimitiveTypeKind getType() {
|
||||
return null;
|
||||
}
|
||||
public List<EdmProperty> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
enum TecSimpleProperty implements TechProperty {
|
||||
@ -181,7 +176,7 @@ public class ODataJsonSerializerTest {
|
||||
Mockito.when(edmETCompAllPrim.getName()).thenReturn(ETCompAllPrim);
|
||||
List<EdmProperty> capProperties = Arrays.asList(
|
||||
mockProperty(TecSimpleProperty.Int16, false),
|
||||
mockProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim), false, true)
|
||||
mockProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim, properties), false)
|
||||
);
|
||||
List<String> capPropertyNames = new ArrayList<String>();
|
||||
|
||||
@ -193,22 +188,27 @@ public class ODataJsonSerializerTest {
|
||||
}
|
||||
|
||||
private EdmProperty mockProperty(TechProperty name) {
|
||||
return mockProperty(name, true, false);
|
||||
return mockProperty(name, true);
|
||||
}
|
||||
|
||||
private EdmProperty mockProperty(TechProperty name, boolean nullable) {
|
||||
return mockProperty(name, nullable, false);
|
||||
}
|
||||
|
||||
private EdmProperty mockProperty(TechProperty tecProperty, boolean nullable, boolean complex) {
|
||||
private EdmProperty mockProperty(TechProperty tecProperty, boolean nullable) {
|
||||
EdmProperty edmElement = Mockito.mock(EdmProperty.class);
|
||||
Mockito.when(edmElement.getName()).thenReturn(tecProperty.getName());
|
||||
if(complex) {
|
||||
if (tecProperty instanceof TecComplexProperty) {
|
||||
TecComplexProperty complexProperty = (TecComplexProperty) tecProperty;
|
||||
Mockito.when(edmElement.isPrimitive()).thenReturn(false);
|
||||
EdmType type = Mockito.mock(EdmType.class);
|
||||
EdmComplexType type = Mockito.mock(EdmComplexType.class);
|
||||
Mockito.when(type.getKind()).thenReturn(EdmTypeKind.COMPLEX);
|
||||
Mockito.when(type.getName()).thenReturn(tecProperty.getTypeName());
|
||||
Mockito.when(edmElement.getType()).thenReturn(type);
|
||||
|
||||
List<String> propertyNames = new ArrayList<String>();
|
||||
List<EdmProperty> properties = complexProperty.getProperties();
|
||||
for (EdmProperty property : properties) {
|
||||
propertyNames.add(property.getName());
|
||||
Mockito.when(type.getProperty(property.getName())).thenReturn(property);
|
||||
}
|
||||
Mockito.when(type.getPropertyNames()).thenReturn(propertyNames);
|
||||
} else {
|
||||
Mockito.when(edmElement.isPrimitive()).thenReturn(true);
|
||||
// TODO: set default values
|
||||
@ -287,20 +287,23 @@ public class ODataJsonSerializerTest {
|
||||
Assert.assertEquals(100, count);
|
||||
}
|
||||
|
||||
@Test(expected = ODataRuntimeException.class)
|
||||
@Test
|
||||
public void entityETCompAllPrim() throws Exception {
|
||||
Entity complexCtAllPrim = createETAllPrim();
|
||||
|
||||
Entity entity = new EntityImpl();
|
||||
entity.addProperty(new PropertyImpl("Edm.Int16", TecSimpleProperty.Int16.name, ValueType.PRIMITIVE, 4711));
|
||||
entity.addProperty(createProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim),
|
||||
ValueType.COMPLEX, complexCtAllPrim));
|
||||
entity.addProperty(createProperty(
|
||||
new TecComplexProperty(CTAllPrim_Type, CTAllPrim, Collections.<EdmProperty>emptyList()),
|
||||
ValueType.COMPLEX, complexCtAllPrim.getProperties()));
|
||||
|
||||
InputStream result = serializer.entity(edmETCompAllPrim, entity, contextUrl);
|
||||
String resultString = streamToString(result);
|
||||
String expectedResult = "{" +
|
||||
"\"@odata.context\":\"http://localhost:8080/test.svc\"," +
|
||||
"\"PropertyInt16\":4711," +
|
||||
"\"CTAllPrim\":{" +
|
||||
"\"PropertyInt16\":4711," +
|
||||
"\"PropertyString\":\"StringValue\"," +
|
||||
"\"PropertyBoolean\":true," +
|
||||
"\"PropertyByte\":19," +
|
||||
@ -316,7 +319,7 @@ public class ODataJsonSerializerTest {
|
||||
"\"PropertyDuration\":\"P16148383DT8H0S\"," +
|
||||
"\"PropertyGuid\":\"0000aaaa-00bb-00cc-00dd-000000ffffff\"," +
|
||||
"\"PropertyTimeOfDay\":\"10:12:00\"" +
|
||||
"}";
|
||||
"}}";
|
||||
Assert.assertEquals(expectedResult, resultString);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.apache.olingo.server.tecsvc.processor;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.olingo.commons.api.data.ContextURL;
|
||||
@ -27,7 +29,10 @@ import org.apache.olingo.commons.api.data.EntitySet;
|
||||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.data.ValueType;
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
|
||||
import org.apache.olingo.commons.api.format.ContentType;
|
||||
import org.apache.olingo.commons.api.format.ODataFormat;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
@ -41,6 +46,7 @@ import org.apache.olingo.server.api.processor.EntityProcessor;
|
||||
import org.apache.olingo.server.api.processor.EntitySetProcessor;
|
||||
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||
import org.apache.olingo.server.api.uri.UriInfo;
|
||||
import org.apache.olingo.server.api.uri.UriResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -60,16 +66,13 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
|
||||
public void readEntitySet(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) {
|
||||
long time = System.nanoTime();
|
||||
|
||||
EntitySet entitySet = createEntitySet();
|
||||
|
||||
LOG.info((System.nanoTime() - time) / 1000 + " microseconds");
|
||||
time = System.nanoTime();
|
||||
ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
|
||||
response.setContent(serializer.entitySet(
|
||||
edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
|
||||
.getEntitySet("ESAllPrim"),
|
||||
entitySet,
|
||||
ContextURL.getInstance(URI.create("dummyContextURL"))));
|
||||
EdmEntitySet edmEntitySet = getEntitySet(uriInfo);
|
||||
EntitySet entitySet = createEntitySet(edmEntitySet.getEntityType());
|
||||
response.setContent(serializer.entitySet(edmEntitySet, entitySet,
|
||||
getContextUrl(request, edmEntitySet.getEntityType())));
|
||||
LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
|
||||
|
||||
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||
@ -79,23 +82,45 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
|
||||
@Override
|
||||
public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) {
|
||||
long time = System.nanoTime();
|
||||
Entity entity = createEntity();
|
||||
|
||||
LOG.info((System.nanoTime() - time) / 1000 + " microseconds");
|
||||
time = System.nanoTime();
|
||||
ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
|
||||
response.setContent(serializer.entity(
|
||||
edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
|
||||
.getEntitySet("ESAllPrim").getEntityType(),
|
||||
entity,
|
||||
ContextURL.getInstance(URI.create("dummyContextURL"))));
|
||||
EdmEntityType entityType = getEntityType(uriInfo);
|
||||
Entity entity = createEntity(entityType);
|
||||
|
||||
response.setContent(serializer.entity(entityType, entity,
|
||||
getContextUrl(request, entityType)));
|
||||
LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
|
||||
|
||||
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||
response.setHeader("Content-Type", ContentType.APPLICATION_JSON.toContentTypeString());
|
||||
}
|
||||
|
||||
protected Entity createEntity() {
|
||||
private ContextURL getContextUrl(ODataRequest request, EdmEntityType entityType) {
|
||||
return ContextURL.getInstance(URI.create(request.getRawBaseUri() + "/" + entityType.getName()));
|
||||
}
|
||||
|
||||
public EdmEntityType getEntityType(UriInfo uriInfo) {
|
||||
return getEntitySet(uriInfo).getEntityType();
|
||||
}
|
||||
|
||||
public EdmEntitySet getEntitySet(UriInfo uriInfo) {
|
||||
List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
|
||||
if(resourcePaths.isEmpty()) {
|
||||
throw new RuntimeException("Invalid resource path.");
|
||||
}
|
||||
String entitySetName = resourcePaths.get(resourcePaths.size()-1).toString();
|
||||
return edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
|
||||
.getEntitySet(entitySetName);
|
||||
}
|
||||
|
||||
protected Entity createEntity(EdmEntityType entityType) {
|
||||
boolean complex = (entityType.getName().contains("Comp"));
|
||||
return createEntity(complex);
|
||||
}
|
||||
|
||||
protected Entity createEntity(boolean complex) {
|
||||
Entity entity = new EntityImpl();
|
||||
Property property = new PropertyImpl();
|
||||
property.setName("PropertyString");
|
||||
@ -109,15 +134,40 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
|
||||
propertyGuid.setName("PropertyGuid");
|
||||
propertyGuid.setValue(ValueType.PRIMITIVE, UUID.randomUUID());
|
||||
entity.getProperties().add(propertyGuid);
|
||||
|
||||
if(complex) {
|
||||
entity.addProperty(createComplexProperty());
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected EntitySet createEntitySet() {
|
||||
protected Property createComplexProperty() {
|
||||
List<Property> properties = new ArrayList<Property>();
|
||||
Property property = new PropertyImpl();
|
||||
property.setName("PropertyString");
|
||||
property.setValue(ValueType.PRIMITIVE, "dummyValue");
|
||||
properties.add(property);
|
||||
Property propertyInt = new PropertyImpl();
|
||||
propertyInt.setName("PropertyInt16");
|
||||
propertyInt.setValue(ValueType.PRIMITIVE, 42);
|
||||
properties.add(propertyInt);
|
||||
Property propertyGuid = new PropertyImpl();
|
||||
propertyGuid.setName("PropertyGuid");
|
||||
propertyGuid.setValue(ValueType.PRIMITIVE, UUID.randomUUID());
|
||||
properties.add(propertyGuid);
|
||||
|
||||
return new PropertyImpl("com.sap.odata.test1.ETCompAllPrim", "PropertyComplex", ValueType.COMPLEX,
|
||||
properties);
|
||||
}
|
||||
|
||||
|
||||
protected EntitySet createEntitySet(EdmEntityType edmEntityType) {
|
||||
EntitySet entitySet = new EntitySetImpl();
|
||||
entitySet.setCount(4242);
|
||||
entitySet.setNext(URI.create("nextLinkURI"));
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
entitySet.getEntities().add(createEntity());
|
||||
entitySet.getEntities().add(createEntity(edmEntityType));
|
||||
}
|
||||
return entitySet;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user