[OLINGO-558] Introduce EdmMapping for deserialization
This commit is contained in:
parent
6c74d3fee5
commit
b7d2c5f441
|
@ -24,9 +24,9 @@ package org.apache.olingo.commons.api.edm;
|
|||
public interface EdmMappable {
|
||||
|
||||
/**
|
||||
* Get mapping information applied to an EDM element
|
||||
* Get mapping information applied to an EDM element. May return null if no mapping is defined.
|
||||
*
|
||||
* @return {@link EdmMapping}
|
||||
* @return {@link EdmMapping} or <b>null</b> if no mapping is defined
|
||||
*/
|
||||
EdmMapping getMapping();
|
||||
}
|
||||
|
|
|
@ -24,30 +24,9 @@ package org.apache.olingo.commons.api.edm;
|
|||
public interface EdmMapping {
|
||||
|
||||
/**
|
||||
* Get the mapping value
|
||||
*
|
||||
* @return mapping name as String
|
||||
* The class which is returned here will be used to during deserialization to replace the default java class for a
|
||||
* primitive type.
|
||||
* @return class used during deserialization
|
||||
*/
|
||||
String getInternalName();
|
||||
|
||||
/**
|
||||
* Get the set object for this mapping
|
||||
*
|
||||
* @return {@link Object} object
|
||||
*/
|
||||
Object getObject();
|
||||
|
||||
/**
|
||||
* Gets the key under which the resource source value can be found in the data map.
|
||||
*
|
||||
* @return the key of the media resource source
|
||||
*/
|
||||
String getMediaResourceSourceKey();
|
||||
|
||||
/**
|
||||
* Gets the key under which the resource mime type can be found in the data map.
|
||||
*
|
||||
* @return the key of the media resource type
|
||||
*/
|
||||
String getMediaResourceMimeTypeKey();
|
||||
Class<?> getMappedJavaClass();
|
||||
}
|
||||
|
|
|
@ -19,78 +19,33 @@
|
|||
package org.apache.olingo.server.api.edm.provider;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmMapping;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
|
||||
|
||||
/**
|
||||
* Content of this class does not appear within the CSDL metadata document. This class is used to perform server
|
||||
* internal mapping for edm primitive types to java types.
|
||||
*/
|
||||
public class Mapping implements EdmMapping {
|
||||
|
||||
private String value;
|
||||
|
||||
private Object object;
|
||||
|
||||
private String mediaResourceSourceKey;
|
||||
|
||||
private String mediaResourceMimeTypeKey;
|
||||
|
||||
@Override
|
||||
public String getInternalName() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMediaResourceSourceKey() {
|
||||
return mediaResourceSourceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMediaResourceMimeTypeKey() {
|
||||
return mediaResourceMimeTypeKey;
|
||||
}
|
||||
private Class<?> mappedJavaClass;
|
||||
|
||||
/**
|
||||
* Sets the value for this {@link Mapping}.
|
||||
*
|
||||
* @param value
|
||||
* @return {@link Mapping} for method chaining
|
||||
* Sets the class to be used during deserialization to transofrm an EDM primitive type into this java class. To see
|
||||
* which classes work for which primitive type refer to {@link EdmPrimitiveType}.
|
||||
* @param mappedJavaClass
|
||||
* @return this for method chaining
|
||||
*/
|
||||
public Mapping setInternalName(final String value) {
|
||||
this.value = value;
|
||||
public Mapping setMappedJavaClass(Class<?> mappedJavaClass) {
|
||||
this.mappedJavaClass = mappedJavaClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an object. This method can be used by a provider to set whatever it wants to associate with this.
|
||||
*
|
||||
* @param object
|
||||
* @return {@link Mapping} for method chaining
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.olingo.commons.api.edm.EdmMapping#getMappedJavaClass()
|
||||
*/
|
||||
public Mapping setObject(final Object object) {
|
||||
this.object = object;
|
||||
return this;
|
||||
@Override
|
||||
public Class<?> getMappedJavaClass() {
|
||||
return mappedJavaClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key for the resource source key which is used for the lookup in the data map
|
||||
*
|
||||
* @param mediaResourceSourceKey under which the source can be found in the data map
|
||||
* @return {@link Mapping} for method chaining
|
||||
*/
|
||||
public Mapping setMediaResourceSourceKey(final String mediaResourceSourceKey) {
|
||||
this.mediaResourceSourceKey = mediaResourceSourceKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key for the resource mime type key which is used for the lookup in the data map
|
||||
*
|
||||
* @param mediaResourceMimeTypeKey under which the mime type can be found in the data map
|
||||
* @return {@link Mapping} for method chaining
|
||||
*/
|
||||
public Mapping setMediaResourceMimeTypeKey(final String mediaResourceMimeTypeKey) {
|
||||
this.mediaResourceMimeTypeKey = mediaResourceMimeTypeKey;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,10 +472,11 @@ public class ODataJsonDeserializer implements ODataDeserializer {
|
|||
EdmTypeDefinition edmTypeDefinition = (EdmTypeDefinition) edmProperty.getType();
|
||||
checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmTypeDefinition.getUnderlyingType().getName(),
|
||||
jsonNode);
|
||||
Class<?> javaClass = getJavaClassForPrimitiveType(edmProperty, edmTypeDefinition.getUnderlyingType());
|
||||
return edmTypeDefinition.valueOfString(jsonNode.asText(), edmProperty.isNullable(),
|
||||
edmTypeDefinition.getMaxLength(),
|
||||
edmTypeDefinition.getPrecision(), edmTypeDefinition.getScale(), edmTypeDefinition.isUnicode(),
|
||||
edmTypeDefinition.getDefaultType());
|
||||
javaClass);
|
||||
} catch (EdmPrimitiveTypeException e) {
|
||||
throw new DeserializerException(
|
||||
"Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e,
|
||||
|
@ -504,9 +505,10 @@ public class ODataJsonDeserializer implements ODataDeserializer {
|
|||
try {
|
||||
EdmEnumType edmEnumType = (EdmEnumType) edmProperty.getType();
|
||||
checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmEnumType.getUnderlyingType().getName(), jsonNode);
|
||||
Class<?> javaClass = getJavaClassForPrimitiveType(edmProperty, edmEnumType.getUnderlyingType());
|
||||
return edmEnumType
|
||||
.valueOfString(jsonNode.asText(), edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty
|
||||
.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), edmEnumType.getDefaultType());
|
||||
.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), javaClass);
|
||||
} catch (EdmPrimitiveTypeException e) {
|
||||
throw new DeserializerException(
|
||||
"Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e,
|
||||
|
@ -522,9 +524,10 @@ public class ODataJsonDeserializer implements ODataDeserializer {
|
|||
try {
|
||||
EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmProperty.getType();
|
||||
checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmPrimitiveType.getName(), jsonNode);
|
||||
Class<?> javaClass = getJavaClassForPrimitiveType(edmProperty, edmPrimitiveType);
|
||||
return edmPrimitiveType.valueOfString(jsonNode.asText(), edmProperty.isNullable(),
|
||||
edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(),
|
||||
edmProperty.isUnicode(), edmPrimitiveType.getDefaultType());
|
||||
edmProperty.isUnicode(), javaClass);
|
||||
} catch (EdmPrimitiveTypeException e) {
|
||||
throw new DeserializerException(
|
||||
"Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e,
|
||||
|
@ -532,6 +535,24 @@ public class ODataJsonDeserializer implements ODataDeserializer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method either returns the primitive types default class or the manually mapped class if present.
|
||||
* @param edmProperty
|
||||
* @param edmPrimitiveType
|
||||
* @return the java class to be used during deserialization
|
||||
*/
|
||||
private Class<?> getJavaClassForPrimitiveType(EdmProperty edmProperty, EdmPrimitiveType edmPrimitiveType) {
|
||||
Class<?> javaClass = null;
|
||||
if (edmProperty.getMapping() != null && edmProperty.getMapping().getMappedJavaClass() != null) {
|
||||
javaClass = edmProperty.getMapping().getMappedJavaClass();
|
||||
} else {
|
||||
javaClass = edmPrimitiveType.getDefaultType();
|
||||
}
|
||||
|
||||
edmPrimitiveType.getDefaultType();
|
||||
return javaClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if JsonNode is a value node (<code>jsonNode.isValueNode()</code>) and if not throw
|
||||
* an DeserializerException.
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.edm.provider;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.olingo.commons.api.edm.EdmParameter;
|
||||
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
|
||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||
import org.apache.olingo.server.api.edm.provider.Mapping;
|
||||
import org.apache.olingo.server.api.edm.provider.Parameter;
|
||||
import org.apache.olingo.server.api.edm.provider.Property;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EdmMappingTest {
|
||||
|
||||
@Test
|
||||
public void initialMappingMustBeNull() {
|
||||
Property property = new Property().setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName());
|
||||
EdmProperty edmProperty = new EdmPropertyImpl(null, new FullQualifiedName("namespace.name"), property);
|
||||
|
||||
assertNull(edmProperty.getMapping());
|
||||
|
||||
Parameter parameter = new Parameter().setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName());
|
||||
EdmParameter edmParameter = new EdmParameterImpl(null, parameter);
|
||||
|
||||
assertNull(edmParameter.getMapping());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDataClassForPrimTypeViaMapping() {
|
||||
Mapping mapping = new Mapping().setMappedJavaClass(Date.class);
|
||||
Property property = new Property()
|
||||
.setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName())
|
||||
.setMapping(mapping);
|
||||
EdmProperty edmProperty = new EdmPropertyImpl(null, new FullQualifiedName("namespace.name"), property);
|
||||
|
||||
assertNotNull(edmProperty.getMapping());
|
||||
assertEquals(Date.class, edmProperty.getMapping().getMappedJavaClass());
|
||||
|
||||
Parameter parameter = new Parameter()
|
||||
.setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName())
|
||||
.setMapping(mapping);
|
||||
EdmParameter edmParameter = new EdmParameterImpl(null, parameter);
|
||||
|
||||
assertNotNull(edmParameter.getMapping());
|
||||
assertEquals(Date.class, edmParameter.getMapping().getMappedJavaClass());
|
||||
}
|
||||
}
|
|
@ -24,10 +24,15 @@ import static org.junit.Assert.assertNotNull;
|
|||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
|
@ -35,11 +40,19 @@ import org.apache.olingo.commons.api.data.Link;
|
|||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.data.ValueType;
|
||||
import org.apache.olingo.commons.api.domain.ODataLinkType;
|
||||
import org.apache.olingo.commons.api.edm.Edm;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||
import org.apache.olingo.commons.api.format.ODataFormat;
|
||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
|
||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
|
||||
import org.apache.olingo.server.api.OData;
|
||||
import org.apache.olingo.server.api.deserializer.DeserializerException;
|
||||
import org.apache.olingo.server.api.deserializer.ODataDeserializer;
|
||||
import org.apache.olingo.server.api.edm.provider.Mapping;
|
||||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTest {
|
||||
|
@ -553,6 +566,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
|
|||
assertNull(entity.getProperty("PropertyComp").getValue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void validJsonValueForComplexCollectionNullValue() throws Exception {
|
||||
final String entityString = "{"
|
||||
|
@ -603,6 +617,50 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
|
|||
assertNull(propertyCompMixedEnumDef.asComplex().get(0).getValue());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void mappingTest() throws Exception {
|
||||
Edm localEdm =
|
||||
OData.newInstance().createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
|
||||
.getEdm();
|
||||
|
||||
EdmEntityType entityType = mock(EdmEntityType.class);
|
||||
when(entityType.getFullQualifiedName()).thenReturn(new FullQualifiedName("napespace", "name"));
|
||||
List<String> propertyNames = new ArrayList<String>();
|
||||
propertyNames.add("PropertyDate");
|
||||
propertyNames.add("PropertyDateTimeOffset");
|
||||
when(entityType.getPropertyNames()).thenReturn(propertyNames);
|
||||
Mapping mapping = new Mapping().setMappedJavaClass(Date.class);
|
||||
|
||||
EdmProperty propertyDate = mock(EdmProperty.class);
|
||||
when(propertyDate.getName()).thenReturn("PropertyDate");
|
||||
when(propertyDate.getMapping()).thenReturn(mapping);
|
||||
when(propertyDate.getType()).thenReturn(new EdmDate());
|
||||
when(entityType.getProperty("PropertyDate")).thenReturn(propertyDate);
|
||||
|
||||
EdmProperty propertyDateTimeOffset = mock(EdmProperty.class);
|
||||
when(propertyDateTimeOffset.getName()).thenReturn("PropertyDateTimeOffset");
|
||||
when(propertyDateTimeOffset.getMapping()).thenReturn(mapping);
|
||||
when(propertyDateTimeOffset.getType()).thenReturn(new EdmDateTimeOffset());
|
||||
when(entityType.getProperty("PropertyDateTimeOffset")).thenReturn(propertyDateTimeOffset);
|
||||
|
||||
String entityString =
|
||||
"{\"PropertyDate\":\"2012-12-03\","
|
||||
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"}";
|
||||
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
|
||||
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
|
||||
Entity entity =
|
||||
deserializer.entity(stream, entityType);
|
||||
assertNotNull(entity);
|
||||
List<Property> properties = entity.getProperties();
|
||||
assertNotNull(properties);
|
||||
assertEquals(2, properties.size());
|
||||
|
||||
assertNotNull(entity.getProperty("PropertyDate").getValue());
|
||||
assertEquals(Date.class, entity.getProperty("PropertyDate").getValue().getClass());
|
||||
assertNotNull(entity.getProperty("PropertyDateTimeOffset").getValue());
|
||||
assertEquals(Date.class, entity.getProperty("PropertyDateTimeOffset").getValue().getClass());
|
||||
}
|
||||
|
||||
// ---------------------------------- Negative Tests -----------------------------------------------------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue