[OLINGO-260] derived types tests
This commit is contained in:
parent
9c3e506d5e
commit
6d76674afb
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue