[OLINGO-317] Minor bugfixes

This commit is contained in:
Michael Bolz 2014-06-28 14:55:33 +02:00
parent a2874142c5
commit 8221545085
9 changed files with 239 additions and 62 deletions

View File

@ -108,6 +108,14 @@ public interface Entity extends Linked, Annotatable {
*/
List<ODataOperation> getOperations();
/**
* Add property to this Entity.
*
* @param property property which is added
* @return this Entity for fluid/flow adding
*/
Entity addProperty(Property property);
/**
* Gets properties.
*

View File

@ -50,7 +50,7 @@ public class AcceptType {
private static final String PARAMETER_Q = "q";
private static final Pattern Q_PARAMETER_VALUE_PATTERN = Pattern.compile("1|0|1\\.0{1,3}|0\\.\\d{1,3}");
public static final AcceptType WILDCARD = create(MEDIA_TYPE_WILDCARD, MEDIA_TYPE_WILDCARD, null, 1F);
public static final AcceptType WILDCARD = create(MEDIA_TYPE_WILDCARD, MEDIA_TYPE_WILDCARD, createParameterMap(), 1F);
private final String type;
private final String subtype;
@ -66,7 +66,7 @@ public class AcceptType {
this.quality = quality;
}
private TreeMap<String, String> createParameterMap() {
private static TreeMap<String, String> createParameterMap() {
return new TreeMap<String, String>(new Comparator<String>() {
@Override
public int compare(final String o1, final String o2) {

View File

@ -131,6 +131,12 @@ public class EntityImpl extends AbstractODataObject implements Entity {
return operations;
}
@Override
public Entity addProperty(Property property) {
properties.add(property);
return this;
}
@Override
public List<Property> getProperties() {
return properties;

View File

@ -19,12 +19,26 @@
package org.apache.olingo.commons.core.data;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
public class PropertyImpl extends AbstractValuable implements Property {
private String name;
private String type;
public PropertyImpl() {
}
public PropertyImpl(String type, String name) {
this.name = name;
this.type = type;
}
public PropertyImpl(String type, String name, ValueType valueType, Object value) {
this(name, type);
setValue(valueType, value);
}
@Override
public String getName() {
return name;

View File

@ -95,7 +95,7 @@ public final class EdmDateTime extends SingletonPrimitiveType {
if (!decimals.isEmpty()) {
final int nanos = Integer.parseInt(decimals.length() > 9 ? decimals.substring(0, 9) :
decimals + "000000000".substring(decimals.length()));
decimals + "000000000".substring(decimals.length()));
timestamp.setNanos(nanos);
}
}
@ -115,32 +115,22 @@ public final class EdmDateTime extends SingletonPrimitiveType {
final Boolean isNullable, final Integer maxLength, final Integer precision,
final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
Date date = null;
Integer fractionalSecs = null;
if (value instanceof Calendar) {
final Calendar calendar = (Calendar) value;
date = calendar.getTime();
fractionalSecs = calendar.get(Calendar.MILLISECOND);
}
if (value instanceof Timestamp) {
Date date = calendar.getTime();
Integer fractionalSecs = calendar.get(Calendar.MILLISECOND);
final StringBuilder result = new StringBuilder().append(DATE_FORMAT.get().format(date));
EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
return result.toString();
} else if (value instanceof Timestamp) {
final Timestamp timestamp = (Timestamp) value;
date = new Date(timestamp.getTime());
fractionalSecs = timestamp.getNanos();
Date date = new Date(timestamp.getTime());
Integer fractionalSecs = timestamp.getNanos();
final StringBuilder result = new StringBuilder().append(DATE_FORMAT.get().format(date));
EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
return result.toString();
} else {
throw new EdmPrimitiveTypeException("EdmDateTime only supports conversion from Calendar and Timestamp");
}
final StringBuilder result = new StringBuilder().append(DATE_FORMAT.get().format(date));
try {
if (value instanceof Timestamp) {
EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
} else {
EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
}
} catch (final IllegalArgumentException e) {
throw new EdmPrimitiveTypeException(
"EdmPrimitiveTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets)", e);
}
return result.toString();
}
}

View File

@ -26,7 +26,7 @@ import org.apache.olingo.server.api.ODataHttpHandler;
import org.apache.olingo.server.api.edm.provider.EdmProvider;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.core.edm.provider.EdmProviderImpl;
import org.apache.olingo.server.core.serializer.ODataJsonSerializer;
import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
import org.apache.olingo.server.core.serializer.ODataXmlSerializerImpl;
public class ODataImpl extends OData {

View File

@ -16,20 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.server.core.serializer;
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 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;
@ -38,7 +41,6 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.core.serializer.json.ServiceDocumentJsonSerializer;
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -128,44 +130,106 @@ public class ODataJsonSerializer implements ODataSerializer {
json.writeStringField("@odata.mediaContentType", entity.getMediaContentType());
}
for (final String propertyName : entityType.getPropertyNames()) {
json.writeFieldName(propertyName);
final EdmProperty edmProperty = (EdmProperty) entityType.getProperty(propertyName);
final Property property = entity.getProperty(propertyName);
if (property == null) {
if (edmProperty.isNullable() == Boolean.FALSE) {
throw new ODataRuntimeException("Non-nullable property not present!");
} else {
json.writeNull();
}
writeProperty(edmProperty, property, json);
}
json.writeEndObject();
}
protected void writeProperty(final EdmProperty edmProperty, final Property property, JsonGenerator json)
throws IOException, EdmPrimitiveTypeException {
json.writeFieldName(edmProperty.getName());
if (property == null || property.isNull()) {
if (edmProperty.isNullable() == Boolean.FALSE) {
throw new ODataRuntimeException("Non-nullable property not present!");
} else {
if (edmProperty.isPrimitive()) {
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
final String value = type.valueToString(property.asPrimitive(),
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(),
edmProperty.isUnicode());
if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
json.writeBoolean(Boolean.parseBoolean(value));
} else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int16)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.SByte)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Single)) {
json.writeNumber(value);
} else {
json.writeString(value);
}
json.writeNull();
}
} 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("Non-primitive properties not yet supported!");
throw new ODataRuntimeException("Inconsistent property type!");
}
} 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();
} else {
if (property.isLinkedComplex()) {
writeLinkedComplexValue(edmProperty, property.asLinkedComplex(), json);
} else {
throw new ODataRuntimeException("Property type not yet supported!");
}
}
}
}
protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue, JsonGenerator json)
throws EdmPrimitiveTypeException, IOException {
final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
final String value = type.valueToString(primitiveValue,
edmProperty.isNullable(), edmProperty.getMaxLength(),
edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode());
if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
json.writeBoolean(Boolean.parseBoolean(value));
} else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int16)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.SByte)
|| type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Single)) {
json.writeNumber(value);
} else {
json.writeString(value);
}
}
private void writeLinkedComplexValue(final EdmProperty edmProperty, final LinkedComplexValue linkedComplexValue,
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);
writeProperty((EdmProperty) type.getProperty(propertyName), property, json);
}
json.writeEndObject();
}
private Property findProperty(String propertyName, List<Property> properties) {
for (final Property property : properties) {
if (propertyName.equals(property.getName())) {
return property;
}
}
return null;
}
@Override
public InputStream entitySet(final EdmEntitySet edmEntitySet, final EntitySet entitySet,
final ContextURL contextURL) {

View File

@ -0,0 +1,97 @@
/*
* 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.serializer.json;
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.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.core.data.EntityImpl;
import org.apache.olingo.commons.core.data.PropertyImpl;
import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
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.Arrays;
import java.util.List;
public class ODataJsonSerializerTest {
public static final String PROPERTY_1 = "Property1";
private ContextURL contextUrl;
private EdmEntityType edmEntityType;
private final Logger LOG = LoggerFactory.getLogger(ODataJsonSerializerTest.class);
private ODataJsonSerializer serializer = new ODataJsonSerializer();
@Before
public void prepare() throws Exception {
contextUrl = ContextURL.getInstance(new URI("http://localhost:8080/test.svc"));
edmEntityType = Mockito.mock(EdmEntityType.class);
List<String> propertyNames = Arrays.asList(PROPERTY_1);
Mockito.when(edmEntityType.getPropertyNames()).thenReturn(propertyNames);
EdmProperty edmElement = Mockito.mock(EdmProperty.class);
Mockito.when(edmElement.getName()).thenReturn(PROPERTY_1);
Mockito.when(edmElement.isPrimitive()).thenReturn(true);
Mockito.when(edmElement.getMaxLength()).thenReturn(20);
Mockito.when(edmElement.getType()).thenReturn(EdmString.getInstance());
Mockito.when(edmEntityType.getProperty(PROPERTY_1)).thenReturn(edmElement);
}
@Test
public void entitySimple() throws Exception {
// Entity entity = new EntityImpl();
// entity.addProperty(new PropertyImpl("Edm.String", PROPERTY_1, ValueType.PRIMITIVE, "Value_1"));
Entity entity = new EntityImpl();
PropertyImpl property = new PropertyImpl("Edm.String", PROPERTY_1);
property.setValue(ValueType.PRIMITIVE, "Value_1");
entity.addProperty(property);
InputStream result = serializer.entity(edmEntityType, entity, contextUrl);
String resultString = streamToString(result);
// System.out.println(resultString);
Assert.assertEquals("{\"@odata.context\":\"http://localhost:8080/test.svc\",\"Property1\":\"Value_1\"}",
resultString);
}
private String streamToString(InputStream result) throws IOException {
byte[] buffer = new byte[8192];
StringBuilder sb = new StringBuilder();
int count = result.read(buffer);
while (count >= 0) {
sb.append(new String(buffer, 0, count, "UTF-8"));
count = result.read(buffer);
}
return sb.toString();
}
}

View File

@ -30,6 +30,7 @@ import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.commons.core.data.EntityImpl;
import org.apache.olingo.commons.core.data.EntitySetImpl;
import org.apache.olingo.commons.core.data.PropertyImpl;
@ -71,7 +72,7 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
ContextURL.getInstance(URI.create("dummyContextURL"))));
LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
response.setStatusCode(200);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader("Content-Type", ContentType.APPLICATION_JSON.toContentTypeString());
}
@ -90,7 +91,7 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
ContextURL.getInstance(URI.create("dummyContextURL"))));
LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
response.setStatusCode(200);
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
response.setHeader("Content-Type", ContentType.APPLICATION_JSON.toContentTypeString());
}
@ -98,17 +99,14 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
Entity entity = new EntityImpl();
Property property = new PropertyImpl();
property.setName("PropertyString");
property.setType("String"); //"dummyType");
property.setValue(ValueType.PRIMITIVE, "dummyValue");
entity.getProperties().add(property);
Property propertyInt = new PropertyImpl();
propertyInt.setName("PropertyInt16");
// propertyInt.setType("Edm.Int32");
propertyInt.setValue(ValueType.PRIMITIVE, 42);
entity.getProperties().add(propertyInt);
Property propertyGuid = new PropertyImpl();
propertyGuid.setName("PropertyGuid");
propertyGuid.setType("Edm.Guid");
propertyGuid.setValue(ValueType.PRIMITIVE, UUID.randomUUID());
entity.getProperties().add(propertyGuid);
return entity;