You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/05/22 13:22:28 UTC
[4/9] git commit: [OLINGO-260] Merge from master
[OLINGO-260] Merge from master
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/1abd8e7e
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/1abd8e7e
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/1abd8e7e
Branch: refs/heads/master
Commit: 1abd8e7e30460ac3fb46762c95bf10d968a28502
Parents: e897cf2 f228204
Author: Francesco Chicchiriccò <--global>
Authored: Sun May 18 09:01:59 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Sun May 18 09:01:59 2014 +0200
----------------------------------------------------------------------
.../ext/proxy/api/annotations/EntitySet.java | 5 +-
.../api/annotations/NavigationProperty.java | 2 +
.../commons/AbstractInvocationHandler.java | 37 +-
.../AbstractStructuredInvocationHandler.java | 304 ++++++++++++++++
.../commons/AbstractTypeInvocationHandler.java | 297 ---------------
.../ComplexFactoryInvocationHandler.java | 18 +-
.../proxy/commons/ComplexInvocationHandler.java | 162 +++++++++
.../commons/ComplexTypeInvocationHandler.java | 162 ---------
.../olingo/ext/proxy/commons/ContainerImpl.java | 75 ++--
.../EntityContainerInvocationHandler.java | 4 +-
.../proxy/commons/EntityInvocationHandler.java | 358 +++++++++++++++++++
.../commons/EntitySetInvocationHandler.java | 72 ++--
.../commons/EntityTypeInvocationHandler.java | 348 ------------------
.../commons/OperationInvocationHandler.java | 8 +-
.../commons/SingletonInvocationHandler.java | 12 +-
.../ext/proxy/context/AttachedEntity.java | 8 +-
.../olingo/ext/proxy/context/EntityContext.java | 28 +-
.../ext/proxy/context/EntityLinkDesc.java | 20 +-
.../olingo/ext/proxy/context/EntityUUID.java | 15 +-
.../olingo/ext/proxy/utils/CoreUtils.java | 32 +-
.../olingo/ext/pojogen/AbstractPOJOGenMojo.java | 29 ++
.../olingo/ext/pojogen/AbstractUtility.java | 39 +-
.../ext/pojogen/NavPropertyContainsTarget.java | 16 +-
.../src/main/resources/containedEntitySet.vm | 65 ++++
.../src/main/resources/container.vm | 1 -
.../src/main/resources/entitySet.vm | 2 +-
.../src/main/resources/entityType.vm | 18 +-
.../src/main/resources/entityTypeKey.vm | 2 +-
.../src/main/resources/v30/complexType.vm | 2 +-
.../src/main/resources/v30/entitySet.vm | 19 -
.../src/main/resources/v40/complexType.vm | 4 +-
.../src/main/resources/v40/entitySet.vm | 19 -
.../org/apache/olingo/fit/AbstractServices.java | 1 -
.../MyPaymentInstruments(101902).full.json | 16 +
.../101/links/MyPaymentInstruments(101902).xml | 40 +++
.../olingo/fit/proxy/v3/ContextTestITCase.java | 90 ++---
.../fit/proxy/v3/EntityRetrieveTestITCase.java | 4 +-
.../fit/proxy/v3/EntityUpdateTestITCase.java | 4 +-
.../olingo/fit/proxy/v4/AsyncTestITCase.java | 2 +-
.../fit/proxy/v4/DerivedTypeTestITCase.java | 13 +-
.../fit/proxy/v4/EntityCreateTestITCase.java | 70 ++++
.../fit/proxy/v4/EntityRetrieveTestITCase.java | 14 +-
.../fit/proxy/v4/EntityUpdateTestITCase.java | 20 +-
.../odata/services/opentypesservicev4/Row.java | 2 +-
.../services/opentypesservicev4/RowIndex.java | 2 +-
.../services/odatawcfservice/Accounts.java | 4 +-
.../odatawcfservice/ActiveSubscriptions.java | 51 +++
.../odata/services/odatawcfservice/Assets.java | 51 +++
.../odatawcfservice/BillingStatements.java | 51 +++
.../odata/services/odatawcfservice/Boss.java | 1 -
.../odata/services/odatawcfservice/Club.java | 51 +++
.../odata/services/odatawcfservice/Company.java | 1 -
.../services/odatawcfservice/CreditRecords.java | 51 +++
.../services/odatawcfservice/Customers.java | 4 +-
.../odatawcfservice/DefaultStoredPI.java | 1 -
.../services/odatawcfservice/Departments.java | 4 +-
.../services/odatawcfservice/Employees.java | 4 +-
.../odatawcfservice/InMemoryEntities.java | 13 -
.../services/odatawcfservice/LabourUnion.java | 1 -
.../services/odatawcfservice/MyGiftCard.java | 51 +++
.../odatawcfservice/MyPaymentInstruments.java | 53 +++
.../services/odatawcfservice/OrderDetails.java | 4 +-
.../odata/services/odatawcfservice/Orders.java | 4 +-
.../odata/services/odatawcfservice/People.java | 4 +-
.../odatawcfservice/ProductDetails.java | 4 +-
.../odatawcfservice/ProductReviews.java | 4 +-
.../services/odatawcfservice/Products.java | 4 +-
.../services/odatawcfservice/PublicCompany.java | 1 -
.../services/odatawcfservice/StoredPIs.java | 4 +-
.../odatawcfservice/SubscriptionTemplates.java | 4 +-
.../services/odatawcfservice/VipCustomer.java | 1 -
.../services/odatawcfservice/package-info.java | 1 -
.../odatawcfservice/types/AccessLevel.java | 1 -
.../services/odatawcfservice/types/Account.java | 43 ++-
.../types/AccountCollection.java | 1 -
.../odatawcfservice/types/AccountInfo.java | 5 +-
.../services/odatawcfservice/types/Address.java | 7 +-
.../services/odatawcfservice/types/Asset.java | 7 +-
.../odatawcfservice/types/AssetCollection.java | 1 -
.../services/odatawcfservice/types/Club.java | 5 +-
.../odatawcfservice/types/ClubCollection.java | 1 -
.../services/odatawcfservice/types/Color.java | 1 -
.../services/odatawcfservice/types/Company.java | 43 ++-
.../odatawcfservice/types/CompanyAddress.java | 9 +-
.../odatawcfservice/types/CompanyCategory.java | 1 -
.../types/CompanyCollection.java | 1 -
.../odatawcfservice/types/CreditCardPI.java | 53 ++-
.../types/CreditCardPICollection.java | 1 -
.../odatawcfservice/types/CreditRecord.java | 9 +-
.../types/CreditRecordCollection.java | 1 -
.../odatawcfservice/types/Customer.java | 47 ++-
.../types/CustomerCollection.java | 1 -
.../odatawcfservice/types/Department.java | 15 +-
.../types/DepartmentCollection.java | 1 -
.../odatawcfservice/types/Employee.java | 37 +-
.../types/EmployeeCollection.java | 1 -
.../odatawcfservice/types/GiftCard.java | 11 +-
.../types/GiftCardCollection.java | 1 -
.../odatawcfservice/types/HomeAddress.java | 9 +-
.../odatawcfservice/types/LabourUnion.java | 5 +-
.../types/LabourUnionCollection.java | 1 -
.../services/odatawcfservice/types/Order.java | 33 +-
.../odatawcfservice/types/OrderCollection.java | 1 -
.../odatawcfservice/types/OrderDetail.java | 27 +-
.../types/OrderDetailCollection.java | 1 -
.../odatawcfservice/types/OrderDetailKey.java | 5 +-
.../types/PaymentInstrument.java | 33 +-
.../types/PaymentInstrumentCollection.java | 1 -
.../services/odatawcfservice/types/Person.java | 25 +-
.../odatawcfservice/types/PersonCollection.java | 1 -
.../services/odatawcfservice/types/Product.java | 27 +-
.../types/ProductCollection.java | 1 -
.../odatawcfservice/types/ProductDetail.java | 25 +-
.../types/ProductDetailCollection.java | 1 -
.../odatawcfservice/types/ProductDetailKey.java | 5 +-
.../odatawcfservice/types/ProductReview.java | 13 +-
.../types/ProductReviewCollection.java | 1 -
.../odatawcfservice/types/ProductReviewKey.java | 9 +-
.../odatawcfservice/types/PublicCompany.java | 71 ++--
.../types/PublicCompanyCollection.java | 1 -
.../odatawcfservice/types/Statement.java | 9 +-
.../types/StatementCollection.java | 1 -
.../odatawcfservice/types/StoredPI.java | 9 +-
.../types/StoredPICollection.java | 1 -
.../odatawcfservice/types/Subscription.java | 11 +-
.../types/SubscriptionCollection.java | 1 -
.../odatawcfservice/types/package-info.java | 1 -
.../apache/olingo/fit/v4/AsyncTestITCase.java | 2 +-
.../olingo/fit/v4/EntityRetrieveTestITCase.java | 4 +-
.../core/edm/primitivetype/EdmDuration.java | 1 -
130 files changed, 2029 insertions(+), 1499 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
index e16c96e,e3a2bc9..cc7eb36
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
@@@ -140,11 -146,11 +152,11 @@@ abstract class AbstractInvocationHandle
handler.setETag(eTag);
}
- if (checkInTheContext && EntityContainerFactory.getContext().entityContext().isAttached(handler)) {
- handler = EntityContainerFactory.getContext().entityContext().getEntity(handler.getUUID());
+ if (checkInTheContext && getContext().entityContext().isAttached(handler)) {
+ handler = getContext().entityContext().getEntity(handler.getUUID());
}
- return (T) Proxy.newProxyInstance(
+ return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {type},
handler);
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
index 0000000,2e6103e..8a1155a
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractStructuredInvocationHandler.java
@@@ -1,0 -1,313 +1,304 @@@
+ /*
+ * 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.ext.proxy.commons;
+
+ import java.lang.reflect.InvocationHandler;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.ParameterizedType;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.net.URI;
-import java.util.Collection;
+ import java.util.Collections;
+ import org.apache.commons.lang3.ArrayUtils;
-import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+ import org.apache.olingo.client.core.uri.URIUtils;
+ import org.apache.olingo.commons.api.domain.CommonODataEntity;
+ 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.ext.proxy.EntityContainerFactory;
+ import org.apache.olingo.ext.proxy.api.AbstractEntityCollection;
+ import org.apache.olingo.ext.proxy.api.AbstractEntitySet;
+ import org.apache.olingo.ext.proxy.api.annotations.EntityType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
-import org.apache.olingo.ext.proxy.context.EntityContext;
+ import org.apache.olingo.ext.proxy.utils.ClassUtils;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+
+ public abstract class AbstractStructuredInvocationHandler extends AbstractInvocationHandler {
+
+ private static final long serialVersionUID = 2629912294765040037L;
+
+ /**
+ * Logger.
+ */
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractStructuredInvocationHandler.class);
+
+ protected final Class<?> typeRef;
+
- protected final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
-
+ protected EntityInvocationHandler entityHandler;
+
+ protected Object internal;
+
+ protected AbstractStructuredInvocationHandler(
- final CommonEdmEnabledODataClient<?> client,
+ final Class<?> typeRef,
+ final Object internal,
+ final EntityContainerInvocationHandler containerHandler) {
+
- super(client, containerHandler);
++ super(containerHandler);
+ this.internal = internal;
+ this.typeRef = typeRef;
+ this.entityHandler = EntityInvocationHandler.class.cast(this);
+ }
+
+ protected AbstractStructuredInvocationHandler(
- final CommonEdmEnabledODataClient<?> client,
+ final Class<?> typeRef,
+ final Object internal,
+ final EntityInvocationHandler entityHandler) {
+
- super(client, entityHandler == null ? null : entityHandler.containerHandler);
++ super(entityHandler == null ? null : entityHandler.containerHandler);
+ this.internal = internal;
+ this.typeRef = typeRef;
+ this.entityHandler = entityHandler;
+ }
+
+ public EntityInvocationHandler getEntityHandler() {
+ return entityHandler;
+ }
+
- public void setEntityHandler(EntityInvocationHandler entityHandler) {
++ public void setEntityHandler(final EntityInvocationHandler entityHandler) {
+ this.entityHandler = entityHandler;
+ }
+
+ public Class<?> getTypeRef() {
+ return typeRef;
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if (isSelfMethod(method, args)) {
+ return invokeSelfMethod(method, args);
+ } else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
+ final Class<?> returnType = method.getReturnType();
+
+ return Proxy.newProxyInstance(
+ Thread.currentThread().getContextClassLoader(),
+ new Class<?>[] {returnType},
+ OperationInvocationHandler.getInstance(entityHandler));
+ } else if ("factory".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
+ final Class<?> returnType = method.getReturnType();
+
+ return Proxy.newProxyInstance(
+ Thread.currentThread().getContextClassLoader(),
+ new Class<?>[] {returnType},
+ 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
+ final Object res;
+ final Method getter = typeRef.getMethod(method.getName());
+
+ final Property property = ClassUtils.getAnnotation(Property.class, getter);
+ if (property == null) {
+ final NavigationProperty navProp = ClassUtils.getAnnotation(NavigationProperty.class, getter);
+ if (navProp == null) {
+ throw new UnsupportedOperationException("Unsupported method " + method.getName());
+ } else {
+ // if the getter refers to a navigation property ... navigate and follow link if necessary
+ res = getNavigationPropertyValue(navProp, getter);
+ }
+ } else {
+ // if the getter refers to a property .... get property from wrapped entity
+ res = getPropertyValue(property, getter.getGenericReturnType());
+ }
+
+ // attach the current handler
+ attach();
+
+ return res;
+ } else if (method.getName().startsWith("set")) {
+ // get the corresponding getter method (see assumption above)
+ final String getterName = method.getName().replaceFirst("set", "get");
+ final Method getter = typeRef.getMethod(getterName);
+
+ final Property property = ClassUtils.getAnnotation(Property.class, getter);
+ if (property == null) {
+ final NavigationProperty navProp = ClassUtils.getAnnotation(NavigationProperty.class, getter);
+ if (navProp == null) {
+ throw new UnsupportedOperationException("Unsupported method " + method.getName());
+ } else {
+ // if the getter refers to a navigation property ...
+ if (ArrayUtils.isEmpty(args) || args.length != 1) {
+ throw new IllegalArgumentException("Invalid argument");
+ }
+
+ setNavigationPropertyValue(navProp, args[0]);
+ }
+ } else {
+ setPropertyValue(property, args[0]);
+ }
+
+ return ClassUtils.returnVoid();
+ } else {
+ throw new NoSuchMethodException(method.getName());
+ }
+ }
+
+ protected void attach() {
- if (entityHandler != null && !entityContext.isAttached(entityHandler)) {
- entityContext.attach(entityHandler, AttachedEntityStatus.ATTACHED);
++ if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
++ getContext().entityContext().attach(entityHandler, AttachedEntityStatus.ATTACHED);
+ }
+ }
+
+ protected void attach(final AttachedEntityStatus status) {
+ attach(status, true);
+ }
+
+ protected void attach(final AttachedEntityStatus status, final boolean override) {
- if (entityContext.isAttached(entityHandler)) {
++ if (getContext().entityContext().isAttached(entityHandler)) {
+ if (override) {
- entityContext.setStatus(entityHandler, status);
++ getContext().entityContext().setStatus(entityHandler, status);
+ }
+ } else {
- entityContext.attach(entityHandler, status);
++ getContext().entityContext().attach(entityHandler, status);
+ }
+ }
+
+ protected abstract Object getNavigationPropertyValue(final NavigationProperty property, final Method getter);
+
+ protected Object retrieveNavigationProperty(
+ final NavigationProperty property, final Method getter, final String serviceRoot) {
+
+ final Class<?> type = getter.getReturnType();
+ final Class<?> collItemType;
+ if (AbstractEntityCollection.class.isAssignableFrom(type)) {
+ final Type[] entityCollectionParams =
+ ((ParameterizedType) type.getGenericInterfaces()[0]).getActualTypeArguments();
+ collItemType = (Class<?>) entityCollectionParams[0];
+ } else {
+ collItemType = type;
+ }
+
+ final Object navPropValue;
+
+ final ODataLink link = ((ODataLinked) internal).getNavigationLink(property.name());
+ if (link instanceof ODataInlineEntity) {
+ // return entity
+ navPropValue = getEntityProxy(
+ null,
+ ((ODataInlineEntity) link).getEntity(),
+ property.targetContainer(),
- client.getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++ getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+ type,
+ false);
+ } else if (link instanceof ODataInlineEntitySet) {
+ // return entity set
+ navPropValue = getEntityCollectionProxy(
+ collItemType,
+ type,
+ property.targetContainer(),
+ ((ODataInlineEntitySet) link).getEntitySet(),
+ link.getLink(),
+ false);
+ } else {
+ // navigate
- final URI uri = URIUtils.getURI(containerHandler.getFactory().getServiceRoot(), link.getLink().toASCIIString());
++ final URI uri = URIUtils.getURI(getClient().getServiceRoot(), link.getLink().toASCIIString());
++
+ if (AbstractEntityCollection.class.isAssignableFrom(type)) {
+ navPropValue = getEntityCollectionProxy(
+ collItemType,
+ type,
+ property.targetContainer(),
- client.getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
++ getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody(),
+ uri,
+ true);
+ } else if (AbstractEntitySet.class.isAssignableFrom(type)) {
+ navPropValue = getEntitySetProxy(type, uri);
+ } else {
+ final ODataRetrieveResponse<CommonODataEntity> res =
- client.getRetrieveRequestFactory().getEntityRequest(uri).execute();
++ getClient().getRetrieveRequestFactory().getEntityRequest(uri).execute();
+
+ navPropValue = getEntityProxy(
+ uri,
+ res.getBody(),
+ property.targetContainer(),
- client.getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
++ getClient().getURIBuilder(serviceRoot).appendEntitySetSegment(property.targetEntitySet()).build(),
+ type,
+ res.getETag(),
+ true);
+ }
+ }
+
+ return navPropValue;
+ }
+
+ protected abstract Object getPropertyValue(final String name, final Type type);
+
+ private Object getPropertyValue(final Property property, final Type type) {
+ return getPropertyValue(property.name(), type);
+ }
+
+ public void addAdditionalProperty(final String name, final Object value) {
+ addPropertyChanges(name, value);
+ attach(AttachedEntityStatus.CHANGED);
+ }
+
+ public Object getAdditionalProperty(final String name) {
+ return getPropertyValue(name, null);
+ }
+
- public abstract Collection<String> getAdditionalPropertyNames();
-
+ private void setNavigationPropertyValue(final NavigationProperty property, final Object value) {
+ // 1) attach source entity
- if (!entityContext.isAttached(entityHandler)) {
- entityContext.attach(entityHandler, AttachedEntityStatus.CHANGED);
++ if (!getContext().entityContext().isAttached(entityHandler)) {
++ getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
+ }
+
+ // 2) attach the target entity handlers
+ for (Object link : AbstractEntityCollection.class.isAssignableFrom(value.getClass())
+ ? (AbstractEntityCollection) value : Collections.singleton(value)) {
+
+ final InvocationHandler etih = Proxy.getInvocationHandler(link);
+ if (!(etih instanceof EntityInvocationHandler)) {
+ throw new IllegalArgumentException("Invalid argument type");
+ }
+
+ final EntityInvocationHandler linkedHandler = (EntityInvocationHandler) etih;
+ if (!linkedHandler.getTypeRef().isAnnotationPresent(EntityType.class)) {
+ throw new IllegalArgumentException("Invalid argument type " + linkedHandler.getTypeRef().getSimpleName());
+ }
+
- if (!entityContext.isAttached(linkedHandler)) {
- entityContext.attach(linkedHandler, AttachedEntityStatus.LINKED);
++ if (!getContext().entityContext().isAttached(linkedHandler)) {
++ getContext().entityContext().attach(linkedHandler, AttachedEntityStatus.LINKED);
+ }
+ }
+
+ // 3) add links
+ addLinkChanges(property, value);
+ }
+
+ protected abstract void setPropertyValue(final Property property, final Object value);
+
+ protected abstract void addPropertyChanges(final String name, final Object value);
+
+ protected abstract void addLinkChanges(final NavigationProperty navProp, final Object value);
+
+ public abstract boolean isChanged();
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
index c20e476,74ea465..b9aacbf
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexFactoryInvocationHandler.java
@@@ -28,38 -29,37 +28,38 @@@ class ComplexFactoryInvocationHandler e
private static final long serialVersionUID = 2629912294765040027L;
- private final EntityTypeInvocationHandler entityHandler;
+ private final EntityInvocationHandler entityHandler;
- private final AbstractTypeInvocationHandler invokerHandler;
+ private final AbstractStructuredInvocationHandler invokerHandler;
static ComplexFactoryInvocationHandler getInstance(
- final CommonEdmEnabledODataClient<?> client,
final EntityContainerInvocationHandler containerHandler,
- final EntityTypeInvocationHandler entityHandler,
- final AbstractTypeInvocationHandler targetHandler) {
+ final EntityInvocationHandler entityHandler,
+ final AbstractStructuredInvocationHandler targetHandler) {
- return new ComplexFactoryInvocationHandler(client, containerHandler, entityHandler, targetHandler);
+ return new ComplexFactoryInvocationHandler(containerHandler, entityHandler, targetHandler);
}
static ComplexFactoryInvocationHandler getInstance(
- final EntityTypeInvocationHandler entityHandler,
- final AbstractTypeInvocationHandler targetHandler) {
+ final EntityInvocationHandler entityHandler,
+ final AbstractStructuredInvocationHandler targetHandler) {
+
return new ComplexFactoryInvocationHandler(
- entityHandler == null ? null : entityHandler.containerHandler.client,
targetHandler == null
- ? entityHandler == null ? null : entityHandler.containerHandler : targetHandler.containerHandler,
+ ? entityHandler == null
+ ? null
+ : entityHandler.containerHandler
+ : targetHandler.containerHandler,
entityHandler,
targetHandler);
}
private ComplexFactoryInvocationHandler(
- final CommonEdmEnabledODataClient<?> client,
final EntityContainerInvocationHandler containerHandler,
- final EntityTypeInvocationHandler entityHandler,
- final AbstractTypeInvocationHandler targetHandler) {
+ final EntityInvocationHandler entityHandler,
+ final AbstractStructuredInvocationHandler targetHandler) {
- super(client, containerHandler);
+ super(containerHandler);
this.invokerHandler = targetHandler;
this.entityHandler = entityHandler;
}
@@@ -78,8 -78,7 +78,8 @@@
return Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {method.getReturnType()},
- ComplexTypeInvocationHandler.getInstance(
- ComplexInvocationHandler.getInstance(client, property.name(), method.getReturnType(), entityHandler));
++ ComplexInvocationHandler.getInstance(
+ getClient(), property.name(), method.getReturnType(), entityHandler));
} else {
throw new NoSuchMethodException(method.getName());
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
index 0000000,72d42e8..32b82d4
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ComplexInvocationHandler.java
@@@ -1,0 -1,186 +1,162 @@@
+ /*
+ * 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.ext.proxy.commons;
+
-import java.lang.annotation.Annotation;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.util.ArrayList;
+ import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+ import org.apache.olingo.client.api.CommonEdmEnabledODataClient;
+ import org.apache.olingo.commons.api.domain.CommonODataProperty;
+ import org.apache.olingo.commons.api.domain.ODataComplexValue;
+ import org.apache.olingo.commons.api.domain.ODataLinked;
+ import org.apache.olingo.commons.api.edm.EdmElement;
+ import org.apache.olingo.commons.api.edm.FullQualifiedName;
+ import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+ import org.apache.olingo.ext.proxy.api.annotations.ComplexType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+ import org.apache.olingo.ext.proxy.utils.ClassUtils;
+ import org.apache.olingo.ext.proxy.utils.CoreUtils;
+
+ public class ComplexInvocationHandler extends AbstractStructuredInvocationHandler {
+
+ private static final long serialVersionUID = 2629912294765040037L;
+
+ public static ComplexInvocationHandler getInstance(
+ final CommonEdmEnabledODataClient<?> client,
+ final String propertyName,
+ final Class<?> reference,
+ final EntityInvocationHandler handler) {
+
+ final Class<?> complexTypeRef;
+ if (Collection.class.isAssignableFrom(reference)) {
+ complexTypeRef = ClassUtils.extractTypeArg(reference);
+ } else {
+ complexTypeRef = reference;
+ }
+
+ final ComplexType annotation = complexTypeRef.getAnnotation(ComplexType.class);
+ if (annotation == null) {
+ throw new IllegalArgumentException("Invalid complex type " + complexTypeRef);
+ }
+
+ final FullQualifiedName typeName =
+ new FullQualifiedName(ClassUtils.getNamespace(complexTypeRef), annotation.name());
+
+ final ODataComplexValue<? extends CommonODataProperty> complex =
+ client.getObjectFactory().newComplexValue(typeName.toString());
+
- return (ComplexInvocationHandler) ComplexInvocationHandler.getInstance(
- client, complex, complexTypeRef, handler);
++ return new ComplexInvocationHandler(client, complex, complexTypeRef, handler);
+ }
+
+ public static ComplexInvocationHandler getInstance(
+ final CommonEdmEnabledODataClient<?> client,
+ final ODataComplexValue<?> complex,
+ final Class<?> typeRef,
+ final EntityInvocationHandler handler) {
+
+ return new ComplexInvocationHandler(client, complex, typeRef, handler);
+ }
++
++ private final CommonEdmEnabledODataClient<?> client;
+
+ public ComplexInvocationHandler(
+ final CommonEdmEnabledODataClient<?> client,
+ final ODataComplexValue<?> complex,
+ final Class<?> typeRef,
+ final EntityInvocationHandler handler) {
+
- super(client, typeRef, complex, handler);
++ super(typeRef, complex, handler);
++ this.client = client;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ODataComplexValue<CommonODataProperty> getComplex() {
+ return (ODataComplexValue<CommonODataProperty>) this.internal;
+ }
+
+ @Override
+ protected Object getPropertyValue(final String name, final Type type) {
+ try {
+ return CoreUtils.getValueFromProperty(client, getComplex().get(name), type, entityHandler);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
+ }
+ }
+
+ @Override
- public Collection<String> getAdditionalPropertyNames() {
- final Set<String> res = new HashSet<String>();
- final Set<String> propertyNames = new HashSet<String>();
- for (Method method : typeRef.getMethods()) {
- final Annotation ann = method.getAnnotation(Property.class);
- if (ann != null) {
- final String property = ((Property) ann).name();
- propertyNames.add(property);
- }
- }
-
- for (final Iterator<? extends CommonODataProperty> itor = getComplex().iterator(); itor.hasNext();) {
- final CommonODataProperty property = itor.next();
- if (!propertyNames.contains(property.getName())) {
- res.add(property.getName());
- }
- }
-
- return res;
- }
-
- @Override
+ @SuppressWarnings("unchecked")
+ protected void setPropertyValue(final Property property, final Object value) {
+ final FullQualifiedName fqn =
+ new FullQualifiedName(ClassUtils.getNamespace(typeRef), typeRef.getAnnotation(ComplexType.class).name());
+
+ final EdmElement edmProperty = client.getCachedEdm().getComplexType(fqn).getProperty(property.name());
+
+ final Object toBeAdded;
+
+ if (value == null) {
+ toBeAdded = null;
+ } else if (Collection.class.isAssignableFrom(value.getClass())) {
+ toBeAdded = new ArrayList<Object>();
+ for (Object obj : (Collection) value) {
+ ((Collection) toBeAdded).add(obj instanceof Proxy ? Proxy.getInvocationHandler(obj) : obj);
+ }
+ } else if (value instanceof Proxy) {
+ toBeAdded = Proxy.getInvocationHandler(value);
+ } else {
+ toBeAdded = value;
+ }
+
+ 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));
+
- if (entityHandler != null && !entityContext.isAttached(entityHandler)) {
- entityContext.attach(entityHandler, AttachedEntityStatus.CHANGED);
++ if (entityHandler != null && !getContext().entityContext().isAttached(entityHandler)) {
++ getContext().entityContext().attach(entityHandler, AttachedEntityStatus.CHANGED);
+ }
+ }
+
+ @Override
+ protected Object getNavigationPropertyValue(final NavigationProperty property, final Method getter) {
+ if (!(internal instanceof ODataLinked)) {
+ throw new UnsupportedOperationException("Internal object is not navigable");
+ }
+
- return retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
++ return retrieveNavigationProperty(property, getter, containerHandler.getFactory().getClient().getServiceRoot());
+ }
+
+ @Override
+ protected void addPropertyChanges(final String name, final Object value) {
+ // do nothing ....
+ }
+
+ @Override
+ protected void addLinkChanges(final NavigationProperty navProp, final Object value) {
+ // do nothing ....
+ }
+
+ @Override
+ public boolean isChanged() {
+ return entityHandler == null ? false : entityHandler.isChanged();
+ }
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
index 2879f5f,90a4d75..0b8b464
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
@@@ -187,9 -186,7 +186,8 @@@ class ContainerImpl implements Containe
LOG.debug("Create '{}'", handler);
- final CommonURIBuilder<?> uriBuilder = factory.getClient().getURIBuilder(factory.getClient().getServiceRoot()).
- appendEntitySetSegment(handler.getEntitySetName());
- changeset.addRequest(factory.getClient().getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), entity));
- changeset.addRequest(client.getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
++ changeset.addRequest(
++ factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
}
private void batchUpdateMediaEntity(
@@@ -237,16 -233,18 +235,18 @@@
final CommonODataEntity changes,
final ODataChangeset changeset) {
- LOG.debug("Update '{}'", changes.getEditLink());
+ LOG.debug("Update '{}'", handler.getEntityURI());
final ODataEntityUpdateRequest<CommonODataEntity> req =
- client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
- ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) client).getCUDRequestFactory().
+ factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+ ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+ getEntityUpdateRequest(handler.getEntityURI(),
+ org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
- : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) client).getCUDRequestFactory().
+ : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+ getEntityUpdateRequest(handler.getEntityURI(),
+ org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
- req.setPrefer(new ODataPreferences(client.getServiceVersion()).returnContent());
+ req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
if (StringUtils.isNotBlank(handler.getETag())) {
req.setIfMatch(handler.getETag());
@@@ -264,15 -262,15 +264,15 @@@
LOG.debug("Update '{}'", uri);
final ODataEntityUpdateRequest<CommonODataEntity> req =
- client.getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
- ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) client).getCUDRequestFactory().
+ factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+ ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(
- uri, org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+ getEntityUpdateRequest(uri,
+ org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
- : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) client).getCUDRequestFactory().
+ : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(
- uri, org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+ getEntityUpdateRequest(uri,
+ org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
- req.setPrefer(new ODataPreferences(client.getServiceVersion()).returnContent());
+ req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
if (StringUtils.isNotBlank(handler.getETag())) {
req.setIfMatch(handler.getETag());
@@@ -286,10 -284,10 +286,10 @@@
final CommonODataEntity entity,
final ODataChangeset changeset) {
- LOG.debug("Delete '{}'", entity.getEditLink());
+ final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
+ LOG.debug("Delete '{}'", deleteURI);
- final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(
- URIUtils.getURI(factory.getClient().getServiceRoot(), entity.getEditLink().toASCIIString()));
- final ODataDeleteRequest req = client.getCUDRequestFactory().getDeleteRequest(deleteURI);
++ final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
if (StringUtils.isNotBlank(handler.getETag())) {
req.setIfMatch(handler.getETag());
@@@ -324,16 -322,17 +324,15 @@@
? ODataLinkType.ENTITY_SET_NAVIGATION
: ODataLinkType.ENTITY_NAVIGATION;
- final Set<EntityTypeInvocationHandler> toBeLinked = new HashSet<EntityTypeInvocationHandler>();
+ final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
- final String serviceRoot = factory.getServiceRoot();
+ final String serviceRoot = factory.getClient().getServiceRoot();
for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
? (Collection) property.getValue() : Collections.singleton(property.getValue())) {
- final EntityTypeInvocationHandler target =
- (EntityTypeInvocationHandler) Proxy.getInvocationHandler(proxy);
- final EntityInvocationHandler target =
- (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
++ final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
- final AttachedEntityStatus status =
- EntityContainerFactory.getContext().entityContext().getStatus(target);
+ final AttachedEntityStatus status = factory.getContext().entityContext().getStatus(target);
final URI editLink = target.getEntity().getEditLink();
@@@ -411,9 -406,8 +409,8 @@@
for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
final URI targetURI = currentStatus == AttachedEntityStatus.NEW
- ? URI.create("$" + startingPos)
- : URIUtils.getURI(
+ ? URI.create("$" + startingPos) : URIUtils.getURI(
- factory.getServiceRoot(),
+ factory.getClient().getServiceRoot(),
CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
@@@ -470,8 -465,8 +467,8 @@@
sourceURI = URI.create("$" + sourcePos);
}
- for (EntityTypeInvocationHandler target : delayedUpdate.getTargets()) {
+ for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
- status = EntityContainerFactory.getContext().entityContext().getStatus(target);
+ status = factory.getContext().entityContext().getStatus(target);
final URI targetURI;
if (status == AttachedEntityStatus.CHANGED) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
index 0000000,361c140..c884f45
mode 000000,100644..100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
@@@ -1,0 -1,385 +1,358 @@@
+ /*
+ * 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.ext.proxy.commons;
+
+ import java.io.InputStream;
-import java.lang.annotation.Annotation;
+ import java.lang.reflect.InvocationHandler;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.Proxy;
+ import java.lang.reflect.Type;
+ import java.net.URI;
+ import java.util.Collection;
+ import java.util.Collections;
+ import java.util.HashMap;
-import java.util.HashSet;
+ import java.util.Map;
-import java.util.Set;
+ import org.apache.commons.io.IOUtils;
+ import org.apache.commons.lang3.StringUtils;
+ import org.apache.olingo.client.api.communication.request.retrieve.ODataMediaRequest;
+ import org.apache.olingo.client.core.uri.URIUtils;
+ 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.format.ODataMediaFormat;
+ import org.apache.olingo.ext.proxy.api.annotations.EntityType;
+ import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+ import org.apache.olingo.ext.proxy.api.annotations.Property;
+ import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+ import org.apache.olingo.ext.proxy.context.EntityUUID;
+ import org.apache.olingo.ext.proxy.utils.CoreUtils;
+
+ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler {
+
+ private static final long serialVersionUID = 2629912294765040037L;
+
+ private final URI entityURI;
+
+ protected Map<String, Object> propertyChanges = new HashMap<String, Object>();
+
+ protected Map<NavigationProperty, Object> linkChanges = new HashMap<NavigationProperty, Object>();
+
+ protected int propertiesTag = 0;
+
+ protected int linksTag = 0;
+
+ private Map<String, InputStream> streamedPropertyChanges = new HashMap<String, InputStream>();
+
+ private InputStream stream;
+
+ private EntityUUID uuid;
+
+ static EntityInvocationHandler getInstance(
+ final URI entityURI,
+ final CommonODataEntity entity,
+ final EntitySetInvocationHandler<?, ?, ?> entitySet,
+ final Class<?> typeRef) {
+
+ return getInstance(
+ entityURI,
+ entity,
+ entitySet.getEntitySetURI(),
+ typeRef,
+ entitySet.containerHandler);
+ }
+
+ static EntityInvocationHandler getInstance(
+ final URI entityURI,
+ final CommonODataEntity entity,
+ final URI entitySetURI,
+ final Class<?> typeRef,
+ final EntityContainerInvocationHandler containerHandler) {
+
+ return new EntityInvocationHandler(entityURI, entity, entitySetURI, typeRef, containerHandler);
+ }
+
+ private EntityInvocationHandler(
+ final URI entityURI,
+ final CommonODataEntity entity,
+ final URI entitySetURI,
+ final Class<?> typeRef,
+ final EntityContainerInvocationHandler containerHandler) {
+
- super(containerHandler.getClient(), typeRef, (ODataLinked) entity, containerHandler);
++ super(typeRef, (ODataLinked) entity, containerHandler);
+
+ this.entityURI = entityURI;
+ this.internal = entity;
+ getEntity().setMediaEntity(typeRef.getAnnotation(EntityType.class).hasStream());
+
+ this.uuid = new EntityUUID(
+ containerHandler.getEntityContainerName(),
+ entitySetURI,
+ typeRef,
- CoreUtils.getKey(client, typeRef, entity));
++ CoreUtils.getKey(getClient(), this, typeRef, entity));
+ }
+
+ public void setEntity(final CommonODataEntity entity) {
+ this.internal = entity;
+ getEntity().setMediaEntity(typeRef.getAnnotation(EntityType.class).hasStream());
+
+ this.uuid = new EntityUUID(
+ getUUID().getContainerName(),
+ getUUID().getEntitySetURI(),
+ getUUID().getType(),
- CoreUtils.getKey(client, typeRef, entity));
++ CoreUtils.getKey(getClient(), this, typeRef, entity));
+
+ this.propertyChanges.clear();
+ this.linkChanges.clear();
+ this.streamedPropertyChanges.clear();
+ this.propertiesTag = 0;
+ this.linksTag = 0;
+ }
+
+ public EntityUUID getUUID() {
+ return uuid;
+ }
+
+ public String getEntityContainerName() {
+ return uuid.getContainerName();
+ }
+
+ public URI getEntitySetURI() {
+ return uuid.getEntitySetURI();
+ }
+
+ public final CommonODataEntity getEntity() {
+ return (CommonODataEntity) internal;
+ }
+
+ public URI getEntityURI() {
+ return entityURI;
+ }
+
+ /**
+ * Gets the current ETag defined into the wrapped entity.
+ *
+ * @return
+ */
+ public String getETag() {
+ return getEntity().getETag();
+ }
+
+ /**
+ * Overrides ETag value defined into the wrapped entity.
+ *
+ * @param eTag ETag.
+ */
+ public void setETag(final String eTag) {
+ getEntity().setETag(eTag);
+ }
+
+ public Map<String, Object> getPropertyChanges() {
+ return propertyChanges;
+ }
+
+ public Map<NavigationProperty, Object> getLinkChanges() {
+ return linkChanges;
+ }
+
+ private void updatePropertiesTag(final int checkpoint) {
+ if (checkpoint == propertiesTag) {
+ propertiesTag = propertyChanges.hashCode();
+ }
+ }
+
+ private void updateLinksTag(final int checkpoint) {
+ if (checkpoint == linksTag) {
+ linksTag = linkChanges.hashCode();
+ }
+ }
+
+ @Override
+ protected Object getPropertyValue(final String name, final Type type) {
+ try {
+ final CommonODataProperty property = getEntity().getProperty(name);
+
+ Object res;
+ if (propertyChanges.containsKey(name)) {
+ res = propertyChanges.get(name);
+ } else {
- res = CoreUtils.getValueFromProperty(client, property, type, this);
-
++ res = CoreUtils.getValueFromProperty(getClient(), property, type, this);
+ if (res != null) {
+ addPropertyChanges(name, res);
+ }
+ }
+
+ return res;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error getting value for property '" + name + "'", e);
+ }
+ }
+
+ @Override
- public Collection<String> getAdditionalPropertyNames() {
- final Set<String> res = new HashSet<String>(propertyChanges.keySet());
- final Set<String> propertyNames = new HashSet<String>();
- for (Method method : typeRef.getMethods()) {
- final Annotation ann = method.getAnnotation(Property.class);
- if (ann != null) {
- final String property = ((Property) ann).name();
- propertyNames.add(property);
-
- // maybe someone could add a normal attribute to the additional set
- res.remove(property);
- }
- }
-
- for (CommonODataProperty property : getEntity().getProperties()) {
- if (!propertyNames.contains(property.getName())) {
- res.add(property.getName());
- }
- }
-
- return res;
- }
-
- @Override
+ @SuppressWarnings("unchecked")
+ protected void setPropertyValue(final Property property, final Object value) {
+ if (property.type().equalsIgnoreCase(EdmPrimitiveTypeKind.Stream.toString())) {
+ setStreamedProperty(property, (InputStream) value);
+ } else {
+ addPropertyChanges(property.name(), value);
+
+ if (value != null) {
- final Collection<?> coll;
++ Collection<?> coll;
+ if (Collection.class.isAssignableFrom(value.getClass())) {
+ coll = Collection.class.cast(value);
+ } else {
+ coll = Collections.singleton(value);
+ }
+
+ for (Object item : coll) {
+ if (item instanceof Proxy) {
+ final InvocationHandler handler = Proxy.getInvocationHandler(item);
+ if ((handler instanceof ComplexInvocationHandler)
+ && ((ComplexInvocationHandler) handler).getEntityHandler() == null) {
+ ((ComplexInvocationHandler) handler).setEntityHandler(this);
+ }
+ }
+ }
+ }
+ }
+
+ attach(AttachedEntityStatus.CHANGED);
+ }
+
+ @Override
+ public boolean isChanged() {
+ return this.linkChanges.hashCode() != this.linksTag
+ || this.propertyChanges.hashCode() != this.propertiesTag
+ || this.stream != null
+ || !this.streamedPropertyChanges.isEmpty();
+ }
+
+ public void setStream(final InputStream stream) {
+ if (typeRef.getAnnotation(EntityType.class).hasStream()) {
+ IOUtils.closeQuietly(this.stream);
+ this.stream = stream;
+ attach(AttachedEntityStatus.CHANGED);
+ }
+ }
+
+ public InputStream getStreamChanges() {
+ return this.stream;
+ }
+
+ public Map<String, InputStream> getStreamedPropertyChanges() {
+ return streamedPropertyChanges;
+ }
+
+ public InputStream getStream() {
+ final URI contentSource = getEntity().getMediaContentSource();
+
+ if (this.stream == null
+ && typeRef.getAnnotation(EntityType.class).hasStream()
+ && contentSource != null) {
+
+ final String contentType =
+ StringUtils.isBlank(getEntity().getMediaContentType()) ? "*/*" : getEntity().getMediaContentType();
+
- final ODataMediaRequest retrieveReq = client.getRetrieveRequestFactory().getMediaRequest(contentSource);
++ final ODataMediaRequest retrieveReq = getClient().getRetrieveRequestFactory().getMediaRequest(contentSource);
+ retrieveReq.setFormat(ODataMediaFormat.fromFormat(contentType));
+
+ this.stream = retrieveReq.execute().getBody();
+ }
+
+ return this.stream;
+ }
+
+ public Object getStreamedProperty(final Property property) {
+ InputStream res = streamedPropertyChanges.get(property.name());
+
+ try {
+ if (res == null) {
+ final URI link = URIUtils.getURI(
- containerHandler.getFactory().getServiceRoot(),
++ getClient().getServiceRoot(),
+ CoreUtils.getMediaEditLink(property.name(), getEntity()).toASCIIString());
+
- final ODataMediaRequest req = client.getRetrieveRequestFactory().getMediaRequest(link);
++ final ODataMediaRequest req = getClient().getRetrieveRequestFactory().getMediaRequest(link);
+ res = req.execute().getBody();
+
+ }
+ } catch (Exception e) {
+ res = null;
+ }
+
+ return res;
+
+ }
+
+ private void setStreamedProperty(final Property property, final InputStream input) {
+ final Object obj = propertyChanges.get(property.name());
+ if (obj instanceof InputStream) {
+ IOUtils.closeQuietly((InputStream) obj);
+ }
+
+ streamedPropertyChanges.put(property.name(), input);
+ }
+
+ @Override
+ protected Object getNavigationPropertyValue(final NavigationProperty property, final Method getter) {
+ final Object navPropValue;
+
+ if (linkChanges.containsKey(property)) {
+ navPropValue = linkChanges.get(property);
+ } else {
- navPropValue = retrieveNavigationProperty(property, getter, containerHandler.getFactory().getServiceRoot());
++ navPropValue = retrieveNavigationProperty(
++ property, getter, containerHandler.getFactory().getClient().getServiceRoot());
+ }
+
+ if (navPropValue != null) {
+ addLinkChanges(property, navPropValue);
+ }
+
+ return navPropValue;
+ }
+
+ @Override
+ protected void addPropertyChanges(final String name, final Object value) {
+ final int checkpoint = propertyChanges.hashCode();
+ propertyChanges.put(name, value);
+ updatePropertiesTag(checkpoint);
+ }
+
+ @Override
+ protected void addLinkChanges(final NavigationProperty navProp, final Object value) {
+ final int checkpoint = linkChanges.hashCode();
+ linkChanges.put(navProp, value);
+ updateLinksTag(checkpoint);
+ }
+
+ @Override
+ public String toString() {
+ return uuid.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return uuid.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return obj instanceof EntityInvocationHandler
+ && ((EntityInvocationHandler) obj).getUUID().equals(uuid);
+ }
+ }
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
index bcb0fb9,6e70a0e..00861c5
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntitySetInvocationHandler.java
@@@ -84,20 -83,38 +82,38 @@@ class EntitySetInvocationHandler
@SuppressWarnings({"rawtypes", "unchecked"})
static EntitySetInvocationHandler getInstance(
- final Class<?> ref, final EntityContainerInvocationHandler containerHandler) {
+ final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final String entitySetName) {
+
+ final CommonURIBuilder<?> uriBuilder = containerHandler.getClient().
- getURIBuilder(containerHandler.getFactory().getServiceRoot());
++ getURIBuilder(containerHandler.getFactory().getClient().getServiceRoot());
- return new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(EntitySet.class)).name());
+ final StringBuilder entitySetSegment = new StringBuilder();
+ if (!containerHandler.isDefaultEntityContainer()) {
+ entitySetSegment.append(containerHandler.getEntityContainerName()).append('.');
+ }
+ entitySetSegment.append(entitySetName);
+
+ uriBuilder.appendEntitySetSegment(entitySetSegment.toString());
+
+ return new EntitySetInvocationHandler(ref, containerHandler, entitySetName, uriBuilder.build());
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ static EntitySetInvocationHandler getInstance(
+ final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final URI uri) {
+
+ return new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(EntitySet.class)).name(), uri);
}
@SuppressWarnings("unchecked")
protected EntitySetInvocationHandler(
final Class<?> ref,
final EntityContainerInvocationHandler containerHandler,
- final String entitySetName) {
+ final String entitySetName,
+ final URI uri) {
- super(containerHandler.getClient(), containerHandler);
+ super(containerHandler);
- this.entitySetName = entitySetName;
this.isSingleton = AbstractSingleton.class.isAssignableFrom(ref);
final Type[] entitySetParams = ((ParameterizedType) ref.getGenericInterfaces()[0]).getActualTypeArguments();
@@@ -151,12 -155,12 +154,12 @@@
@SuppressWarnings("unchecked")
private <NE> NE newEntity(final Class<NE> reference) {
- final CommonODataEntity entity = client.getObjectFactory().newEntity(
+ final CommonODataEntity entity = getClient().getObjectFactory().newEntity(
new FullQualifiedName(containerHandler.getSchemaName(), ClassUtils.getEntityTypeName(reference)));
- final EntityTypeInvocationHandler handler =
- EntityTypeInvocationHandler.getInstance(entity, entitySetName, reference, containerHandler);
+ final EntityInvocationHandler handler =
+ EntityInvocationHandler.getInstance(null, entity, uri, reference, containerHandler);
- EntityContainerFactory.getContext().entityContext().attachNew(handler);
+ getContext().entityContext().attachNew(handler);
return (NE) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
@@@ -229,10 -233,10 +232,10 @@@
throw new IllegalArgumentException("Null key");
}
- final EntityUUID uuid = new EntityUUID(containerHandler.getEntityContainerName(), entitySetName, typeRef, key);
+ final EntityUUID uuid = new EntityUUID(containerHandler.getEntityContainerName(), uri, typeRef, key);
LOG.debug("Ask for '{}({})'", typeRef.getSimpleName(), key);
- EntityTypeInvocationHandler handler = getContext().entityContext().getEntity(uuid);
- EntityInvocationHandler handler = EntityContainerFactory.getContext().entityContext().getEntity(uuid);
++ EntityInvocationHandler handler = getContext().entityContext().getEntity(uuid);
if (handler == null) {
// not yet attached: search against the service
@@@ -259,12 -264,8 +262,12 @@@
throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
}
- handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
+ handler = EntityInvocationHandler.getInstance(uriBuilder.build(), entity, this, typeRef);
handler.setETag(etag);
+
+ if (!key.equals(CoreUtils.getKey(getClient(), handler, typeRef, entity))) {
+ throw new IllegalArgumentException("Invalid " + typeRef.getSimpleName() + "(" + key + ")");
+ }
} catch (Exception e) {
LOG.info("Entity '" + uuid + "' not found", e);
}
@@@ -303,9 -304,11 +306,10 @@@
final List<S> items = new ArrayList<S>(entities.size());
for (CommonODataEntity entity : entities) {
- final EntityTypeInvocationHandler handler = EntityTypeInvocationHandler.getInstance(entity, this, typeRef);
+ final EntityInvocationHandler handler =
+ EntityInvocationHandler.getInstance(entity.getEditLink(), entity, this, typeRef);
- final EntityTypeInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
- final EntityInvocationHandler handlerInTheContext =
- EntityContainerFactory.getContext().entityContext().getEntity(handler.getUUID());
++ final EntityInvocationHandler handlerInTheContext = getContext().entityContext().getEntity(handler.getUUID());
items.add((S) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
@@@ -394,11 -398,11 +398,11 @@@
@Override
public void delete(final KEY key) throws IllegalArgumentException {
- final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
+ final EntityContext entityContext = getContext().entityContext();
- EntityTypeInvocationHandler entity = entityContext.getEntity(new EntityUUID(
+ EntityInvocationHandler entity = entityContext.getEntity(new EntityUUID(
containerHandler.getEntityContainerName(),
- entitySetName,
+ uri,
typeRef,
key));
@@@ -414,10 -418,10 +418,10 @@@
@Override
public <S extends T> void delete(final Iterable<S> entities) {
- final EntityContext entityContext = EntityContainerFactory.getContext().entityContext();
+ final EntityContext entityContext = getContext().entityContext();
for (T en : entities) {
- final EntityTypeInvocationHandler entity = (EntityTypeInvocationHandler) Proxy.getInvocationHandler(en);
+ final EntityInvocationHandler entity = (EntityInvocationHandler) Proxy.getInvocationHandler(en);
if (entityContext.isAttached(entity)) {
entityContext.setStatus(entity, AttachedEntityStatus.DELETED);
} else {
@@@ -426,8 -430,8 +430,8 @@@
}
}
- private boolean isDeleted(final EntityTypeInvocationHandler handler) {
+ private boolean isDeleted(final EntityInvocationHandler handler) {
- return EntityContainerFactory.getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
+ return getContext().entityContext().getStatus(handler) == AttachedEntityStatus.DELETED;
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
index e2362eb,69e1f9b..5aaa0e6
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/OperationInvocationHandler.java
@@@ -62,14 -64,18 +62,14 @@@ class OperationInvocationHandler extend
}
private OperationInvocationHandler(final EntityContainerInvocationHandler containerHandler) {
- super(containerHandler.getClient(), containerHandler);
+ super(containerHandler);
this.target = containerHandler;
-
- this.targetFQN =
- new FullQualifiedName(containerHandler.getSchemaName(), containerHandler.getEntityContainerName());
-
- this.serviceRoot = containerHandler.getFactory().getServiceRoot();
+ this.targetFQN = new FullQualifiedName(containerHandler.getSchemaName(), containerHandler.getEntityContainerName());
}
- private OperationInvocationHandler(final EntityTypeInvocationHandler entityHandler) {
+ private OperationInvocationHandler(final EntityInvocationHandler entityHandler) {
- super(entityHandler.getClient(), entityHandler.containerHandler);
+ super(entityHandler.containerHandler);
this.target = entityHandler;
this.targetFQN = entityHandler.getEntity().getTypeName();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
index 664e894,57b1b39..bbae0c8
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/SingletonInvocationHandler.java
@@@ -41,10 -40,11 +40,11 @@@ public class SingletonInvocationHandler
private final EntitySetInvocationHandler<?, ?, ?> entitySetHandler;
@SuppressWarnings({"rawtypes", "unchecked"})
- private SingletonInvocationHandler(final Class<?> ref, final EntityContainerInvocationHandler containerHandler) {
+ private SingletonInvocationHandler(
+ final Class<?> ref, final EntityContainerInvocationHandler containerHandler, final String singletonName) {
+
- super(containerHandler.getClient(), containerHandler);
+ super(containerHandler);
- this.entitySetHandler =
- new EntitySetInvocationHandler(ref, containerHandler, (ref.getAnnotation(Singleton.class)).name());
+ this.entitySetHandler = EntitySetInvocationHandler.getInstance(ref, containerHandler, singletonName);
}
@Override
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/1abd8e7e/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
----------------------------------------------------------------------
diff --cc ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
index bd7a537,38dd4cc..822e8ea
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/utils/CoreUtils.java
@@@ -349,10 -349,7 +349,10 @@@ public final class CoreUtils
}
public static Object getKey(
- final CommonEdmEnabledODataClient<?> client, final Class<?> entityTypeRef, final CommonODataEntity entity) {
+ final CommonEdmEnabledODataClient<?> client,
- final EntityTypeInvocationHandler typeHandler,
++ final EntityInvocationHandler typeHandler,
+ final Class<?> entityTypeRef,
+ final CommonODataEntity entity) {
Object res = null;
@@@ -378,9 -375,8 +378,9 @@@
return res;
}
- public static void populate(
+ private static void populate(
final CommonEdmEnabledODataClient<?> client,
- final EntityTypeInvocationHandler typeHandler,
++ final EntityInvocationHandler typeHandler,
final Object bean,
final Class<? extends Annotation> getterAnn,
final Iterator<? extends CommonODataProperty> propItor) {
@@@ -402,11 -398,10 +402,11 @@@
}
@SuppressWarnings({"unchecked"})
- public static void populate(
+ private static void populate(
final CommonEdmEnabledODataClient<?> client,
- final EntityTypeInvocationHandler typeHandler,
++ final EntityInvocationHandler typeHandler,
final Object bean,
- final Class<?> reference,
+ final Class<?> typeRef,
final Class<? extends Annotation> getterAnn,
final Iterator<? extends CommonODataProperty> propItor) {
@@@ -430,10 -425,10 +430,10 @@@
final Object complex = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {getter.getReturnType()},
- ComplexTypeInvocationHandler.getInstance(
+ ComplexInvocationHandler.getInstance(
- client, property.getName(), getter.getReturnType(), null));
+ client, property.getName(), getter.getReturnType(), typeHandler));
- populate(client, complex, Property.class, property.getValue().asComplex().iterator());
+ populate(client, typeHandler, complex, Property.class, property.getValue().asComplex().iterator());
setPropertyValue(bean, getter, complex);
} else if (property.hasCollectionValue()) {
final ParameterizedType collType = (ParameterizedType) getter.getGenericReturnType();
@@@ -455,10 -450,10 +455,10 @@@
final Object collItem = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] {collItemClass},
- ComplexTypeInvocationHandler.getInstance(
+ ComplexInvocationHandler.getInstance(
- client, property.getName(), collItemClass, null));
+ client, property.getName(), collItemClass, typeHandler));
- populate(client, collItem, Property.class, value.asComplex().iterator());
+ populate(client, typeHandler, collItem, Property.class, value.asComplex().iterator());
collection.add(collItem);
}
}