[OLINGO-260] derived types tests

This commit is contained in:
Francesco Chicchiriccò 2014-05-16 12:08:22 +02:00 committed by Stephan Klevenz
parent 9c3e506d5e
commit 6d76674afb
10 changed files with 55 additions and 96 deletions

View File

@ -35,7 +35,6 @@ import org.apache.olingo.commons.api.domain.ODataInlineEntity;
import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
import org.apache.olingo.commons.api.domain.ODataLink;
import org.apache.olingo.commons.api.domain.ODataLinked;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.ext.proxy.EntityContainerFactory;
import org.apache.olingo.ext.proxy.api.AbstractEntityCollection;
import org.apache.olingo.ext.proxy.api.annotations.EntityType;
@ -96,8 +95,6 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
this.entityHandler = entityHandler;
}
public abstract FullQualifiedName getName();
public Class<?> getTypeRef() {
return typeRef;
}
@ -119,7 +116,7 @@ public abstract class AbstractTypeInvocationHandler extends AbstractInvocationHa
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {returnType},
FactoryInvocationHandler.getInstance(entityHandler, this));
ComplexFactoryInvocationHandler.getInstance(entityHandler, this));
} else if (method.getName().startsWith("get")) {
// Assumption: for each getter will always exist a setter and viceversa.
// get method annotation and check if it exists as expected

View File

@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.OperationExecutor;
import org.apache.olingo.ext.proxy.api.annotations.Property;
import org.apache.olingo.ext.proxy.utils.ClassUtils;
class FactoryInvocationHandler extends AbstractInvocationHandler implements OperationExecutor {
class ComplexFactoryInvocationHandler extends AbstractInvocationHandler implements OperationExecutor {
private static final long serialVersionUID = 2629912294765040027L;
@ -33,20 +33,19 @@ class FactoryInvocationHandler extends AbstractInvocationHandler implements Oper
private final AbstractTypeInvocationHandler invokerHandler;
@SuppressWarnings({"rawtypes", "unchecked"})
static FactoryInvocationHandler getInstance(
static ComplexFactoryInvocationHandler getInstance(
final CommonEdmEnabledODataClient<?> client,
final EntityContainerInvocationHandler containerHandler,
final EntityTypeInvocationHandler entityHandler,
final AbstractTypeInvocationHandler targetHandler) {
return new FactoryInvocationHandler(client, containerHandler, entityHandler, targetHandler);
return new ComplexFactoryInvocationHandler(client, containerHandler, entityHandler, targetHandler);
}
@SuppressWarnings({"rawtypes", "unchecked"})
static FactoryInvocationHandler getInstance(
static ComplexFactoryInvocationHandler getInstance(
final EntityTypeInvocationHandler entityHandler,
final AbstractTypeInvocationHandler targetHandler) {
return new FactoryInvocationHandler(
return new ComplexFactoryInvocationHandler(
entityHandler == null ? null : entityHandler.containerHandler.client,
targetHandler == null
? entityHandler == null ? null : entityHandler.containerHandler : targetHandler.containerHandler,
@ -54,11 +53,12 @@ class FactoryInvocationHandler extends AbstractInvocationHandler implements Oper
targetHandler);
}
private FactoryInvocationHandler(
private ComplexFactoryInvocationHandler(
final CommonEdmEnabledODataClient<?> client,
final EntityContainerInvocationHandler containerHandler,
final EntityTypeInvocationHandler entityHandler,
final AbstractTypeInvocationHandler targetHandler) {
super(client, containerHandler);
this.invokerHandler = targetHandler;
this.entityHandler = entityHandler;

View File

@ -91,15 +91,6 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
super(client, typeRef, complex, handler);
}
public void setComplex(final ODataComplexValue<?> complex) {
this.internal = complex;
}
@Override
public FullQualifiedName getName() {
return new FullQualifiedName(((ODataComplexValue<?>) this.internal).getTypeName());
}
@SuppressWarnings("unchecked")
public ODataComplexValue<CommonODataProperty> getComplex() {
return (ODataComplexValue<CommonODataProperty>) this.internal;
@ -126,7 +117,7 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
}
}
for (Iterator<? extends CommonODataProperty> itor = getComplex().iterator(); itor.hasNext();) {
for (final Iterator<? extends CommonODataProperty> itor = getComplex().iterator(); itor.hasNext();) {
final CommonODataProperty property = itor.next();
if (!propertyNames.contains(property.getName())) {
res.add(property.getName());
@ -159,12 +150,10 @@ public class ComplexTypeInvocationHandler extends AbstractTypeInvocationHandler
toBeAdded = value;
}
final EdmTypeInfo type = new EdmTypeInfo.Builder().
setEdm(client.getCachedEdm()).setTypeExpression(
edmProperty.isCollection() ? "Collection(" + property.type() + ")" : property.type()).build();
final EdmTypeInfo type = new EdmTypeInfo.Builder().setEdm(client.getCachedEdm()).setTypeExpression(
edmProperty.isCollection() ? "Collection(" + property.type() + ")" : property.type()).build();
client.getBinder().add(
getComplex(), CoreUtils.getODataProperty(client, property.name(), type, toBeAdded));
client.getBinder().add(getComplex(), CoreUtils.getODataProperty(client, property.name(), type, toBeAdded));
if (entityHandler != null && !entityContext.isAttached(entityHandler)) {
entityContext.attach(entityHandler, AttachedEntityStatus.CHANGED);

View File

@ -102,7 +102,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {returnType},
FactoryInvocationHandler.getInstance(getClient(), this, null, null));
ComplexFactoryInvocationHandler.getInstance(getClient(), this, null, null));
} else {
final Class<?> returnType = method.getReturnType();

View File

@ -39,7 +39,6 @@ import org.apache.olingo.commons.api.domain.CommonODataEntity;
import org.apache.olingo.commons.api.domain.CommonODataProperty;
import org.apache.olingo.commons.api.domain.ODataLinked;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ODataMediaFormat;
import org.apache.olingo.ext.proxy.api.annotations.EntityType;
import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
@ -126,11 +125,6 @@ public class EntityTypeInvocationHandler extends AbstractTypeInvocationHandler {
return uuid;
}
@Override
public FullQualifiedName getName() {
return getEntity().getTypeName();
}
public String getEntityContainerName() {
return uuid.getContainerName();
}

View File

@ -258,7 +258,7 @@ class EntitySetInvocationHandler<
final CommonODataEntity entity = res.getBody();
if (entity == null || !key.equals(CoreUtils.getKey(client, typeRef, entity))) {
throw new IllegalArgumentException("Invalid singleton " + typeRef.getSimpleName() + "(" + key + ")");
throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
}
handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
@ -268,7 +268,7 @@ class EntitySetInvocationHandler<
}
} else if (isDeleted(handler)) {
// object deleted
LOG.debug("Object '{}({})' has been delete", typeRef.getSimpleName(), uuid);
LOG.debug("Object '{}({})' has been deleted", typeRef.getSimpleName(), uuid);
handler = null;
}

View File

@ -19,7 +19,6 @@
package org.apache.olingo.ext.proxy.utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -35,6 +34,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
import org.apache.olingo.client.api.v3.UnsupportedInV3Exception;
import org.apache.olingo.commons.api.Constants;
@ -44,6 +44,7 @@ import org.apache.olingo.commons.api.domain.ODataLink;
import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
import org.apache.olingo.commons.api.domain.ODataValue;
import org.apache.olingo.commons.api.domain.v4.ODataEnumValue;
import org.apache.olingo.commons.api.domain.v4.ODataObjectFactory;
import org.apache.olingo.commons.api.domain.v4.ODataProperty;
import org.apache.olingo.commons.api.edm.EdmElement;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
@ -101,42 +102,35 @@ public final class CoreUtils {
}
} else {
throw new UnsupportedOperationException("Usupported object type " + intType.getFullQualifiedName());
throw new UnsupportedOperationException("Unsupported object type " + intType.getFullQualifiedName());
}
}
} else if (type.isComplexType()) {
value = client.getObjectFactory().newComplexValue(type.getFullQualifiedName().toString());
final Object oo;
Object objHandler;
if (obj instanceof Proxy) {
oo = Proxy.getInvocationHandler(obj);
objHandler = Proxy.getInvocationHandler(obj);
} else {
oo = obj;
objHandler = obj;
}
if (objHandler instanceof ComplexTypeInvocationHandler) {
value = ((ComplexTypeInvocationHandler) objHandler).getComplex();
if (oo instanceof ComplexTypeInvocationHandler) {
final Class<?> typeRef = ((ComplexTypeInvocationHandler) oo).getTypeRef();
final Object complex = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {typeRef},
(ComplexTypeInvocationHandler) oo);
final Class<?> typeRef = ((ComplexTypeInvocationHandler) objHandler).getTypeRef();
for (Method method : typeRef.getMethods()) {
final Property complexPropertyAnn = method.getAnnotation(Property.class);
try {
if (complexPropertyAnn != null) {
final Property propAnn = method.getAnnotation(Property.class);
if (propAnn != null) {
try {
value.asComplex().add(getODataComplexProperty(
client, type.getFullQualifiedName(), complexPropertyAnn.name(), method.invoke(complex)));
client, type.getFullQualifiedName(), propAnn.name(), method.invoke(objHandler)));
} catch (Exception ignore) {
// ignore value
LOG.warn("Error attaching complex {} for field '{}.{}'",
type.getFullQualifiedName(), typeRef.getName(), propAnn.name(), ignore);
}
} catch (Exception ignore) {
// ignore value
LOG.warn("Error attaching complex {} for field '{}.{}'",
type.getFullQualifiedName(), typeRef.getName(), complexPropertyAnn.name(), ignore);
}
}
} else {
throw new IllegalArgumentException(
"Object '" + oo.getClass().getSimpleName() + "' is not a complex value");
throw new IllegalArgumentException(objHandler.getClass().getName() + "' is not a complex value");
}
} else if (type.isEnumType()) {
if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
@ -227,8 +221,7 @@ public final class CoreUtils {
if (client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0) {
throw new UnsupportedInV3Exception();
} else {
oprop = ((org.apache.olingo.commons.api.domain.v4.ODataObjectFactory) client.getObjectFactory()).
newEnumProperty(name,
oprop = ((ODataObjectFactory) client.getObjectFactory()).newEnumProperty(name,
((org.apache.olingo.commons.api.domain.v4.ODataValue) getODataValue(client, valueType, obj)).
asEnum());
}
@ -256,18 +249,17 @@ public final class CoreUtils {
final String ns = typeRef.getAnnotation(Namespace.class).value();
final String name = typeRef.getAnnotation(ComplexType.class).name();
return edmTypeInfo.setTypeExpression(new FullQualifiedName(ns, name).toString()).build();
} else if(obj.getClass().getAnnotation(EnumType.class)!=null){
} else if (obj.getClass().getAnnotation(EnumType.class) != null) {
final Class<?> typeRef = obj.getClass();
final String ns = typeRef.getAnnotation(Namespace.class).value();
final String name = typeRef.getAnnotation(EnumType.class).name();
return edmTypeInfo.setTypeExpression(new FullQualifiedName(ns, name).toString()).build();
}else{
} else {
return guessPrimitiveType(client, obj.getClass());
}
}
private static EdmTypeInfo guessPrimitiveType(
final CommonEdmEnabledODataClient<?> client, final Class<?> clazz) {
private static EdmTypeInfo guessPrimitiveType(final CommonEdmEnabledODataClient<?> client, final Class<?> clazz) {
EdmPrimitiveTypeKind bckCandidate = null;
for (EdmPrimitiveTypeKind kind : EdmPrimitiveTypeKind.values()) {
@ -346,9 +338,9 @@ public final class CoreUtils {
private static Class<?> getPropertyClass(final Class<?> entityClass, final String propertyName) {
Class<?> propertyClass = null;
try {
final Field field = entityClass.getField(propertyName);
if (field != null) {
propertyClass = field.getType();
final Method getter = entityClass.getMethod("get" + StringUtils.capitalize(propertyName));
if (getter != null) {
propertyClass = getter.getReturnType();
}
} catch (Exception e) {
LOG.error("Could not determine the Java type of {}", propertyName, e);
@ -434,7 +426,7 @@ public final class CoreUtils {
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {getter.getReturnType()},
ComplexTypeInvocationHandler.getInstance(
client, property.getName(), getter.getReturnType(), null));
client, property.getName(), getter.getReturnType(), null));
populate(client, complex, Property.class, property.getValue().asComplex().iterator());
setPropertyValue(bean, getter, complex);
@ -459,7 +451,7 @@ public final class CoreUtils {
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {collItemClass},
ComplexTypeInvocationHandler.getInstance(
client, property.getName(), collItemClass, null));
client, property.getName(), collItemClass, null));
populate(client, collItem, Property.class, value.asComplex().iterator());
collection.add(collItem);
@ -498,17 +490,13 @@ public final class CoreUtils {
if (property == null || property.hasNullValue()) {
res = null;
} else if (property.hasComplexValue()) {
if (typeRef == null) {
internalRef = getComplexTypeRef(property);
}
// complex types supports inheritance in V4, best to re-read actual type
internalRef = getComplexTypeRef(property);
res = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {internalRef},
ComplexTypeInvocationHandler.getInstance(
client, property.getValue().asComplex(), internalRef, entityHandler));
client, property.getValue().asComplex(), internalRef, entityHandler));
} else if (property.hasCollectionValue()) {
final ArrayList<Object> collection = new ArrayList<Object>();
@ -518,11 +506,12 @@ public final class CoreUtils {
if (value.isPrimitive()) {
collection.add(CoreUtils.primitiveValueToObject(value.asPrimitive(), internalRef));
} else if (value.isComplex()) {
internalRef = getComplexTypeRef(property);
final Object collItem = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {internalRef},
ComplexTypeInvocationHandler.getInstance(
client, value.asComplex(), internalRef, entityHandler));
client, value.asComplex(), internalRef, entityHandler));
collection.add(collItem);
}
@ -553,6 +542,7 @@ public final class CoreUtils {
final CommonODataProperty property,
final String proxyClassListFile,
final Class<? extends Annotation> annType) {
if (!annType.isAssignableFrom(EnumType.class) && !annType.isAssignableFrom(ComplexType.class)) {
throw new IllegalArgumentException("Invalid annotation type " + annType);
}
@ -568,10 +558,10 @@ public final class CoreUtils {
final Namespace ns = clazz.getAnnotation(Namespace.class);
if (ns != null && ann != null) {
if (property.getValue().getTypeName().equals(
if (property.getValue().getTypeName().replaceAll("^Collection\\(", "").replaceAll("\\)$", "").equals(
new FullQualifiedName(ns.value(), annType.isAssignableFrom(EnumType.class)
? EnumType.class.cast(ann).name()
: ComplexType.class.cast(ann).name()).toString())) {
? EnumType.class.cast(ann).name()
: ComplexType.class.cast(ann).name()).toString())) {
return clazz;
}
}

View File

@ -26,10 +26,6 @@ import java.util.Calendar;
import java.util.Collections;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Address;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.CompanyAddress;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.
CreditCardPI;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.
CreditCardPICollection;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.Customer;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.
CustomerCollection;
@ -40,19 +36,12 @@ public class DerivedTypeTestITCase extends AbstractTestITCase {
@Test
public void read() {
final CustomerCollection customers = container.getPeople().getAll(CustomerCollection.class);
CustomerCollection customers = container.getPeople().getAll(CustomerCollection.class);
assertNotNull(customers);
for (Customer customer : customers) {
assertTrue(customer instanceof Customer);
}
final CreditCardPICollection creditCards = container.getAccounts().get(101).
getMyPaymentInstruments().getAll(CreditCardPICollection.class);
assertNotNull(creditCards);
for (CreditCardPI creditCard : creditCards) {
assertTrue(creditCard instanceof CreditCardPI);
}
}
@Test

View File

@ -283,7 +283,7 @@ public class ODataBinderImpl extends AbstractODataBinder implements ODataBinder
@Override
public ODataProperty getODataProperty(final ResWrap<Property> resource) {
final EdmTypeInfo typeInfo = buildTypeInfo(resource.getContextURL(), resource.getMetadataETag(),
resource.getPayload().getName(), resource.getPayload().getType());
resource.getPayload().getName(), resource.getPayload().getType());
final ODataProperty property = new ODataPropertyImpl(resource.getPayload().getName(),
getODataValue(typeInfo == null

View File

@ -359,7 +359,7 @@ public class EntityTest extends AbstractTest {
}
private void derived(final ODataClient client, final ODataPubFormat format) {
final InputStream input = getClass().getResourceAsStream("Customer." + getSuffix(format));
final InputStream input = getClass().getResourceAsStream("Customer." + getSuffix(format));
final ODataEntity entity = client.getBinder().getODataEntity(client.getDeserializer().toEntity(input, format));
assertNotNull(entity);