You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2014/07/28 22:06:17 UTC
git commit: [OLINGO-365] fix for link update via reference ID
Repository: olingo-odata4
Updated Branches:
refs/heads/master 67cc0c440 -> a5e983c9b
[OLINGO-365] fix for link update via reference ID
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/a5e983c9
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/a5e983c9
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/a5e983c9
Branch: refs/heads/master
Commit: a5e983c9b884be030f6bb548da3c512b44912206
Parents: 67cc0c4
Author: fmartelli <fa...@gmail.com>
Authored: Mon Jul 28 22:06:03 2014 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Mon Jul 28 22:06:03 2014 +0200
----------------------------------------------------------------------
.../AbstractCollectionInvocationHandler.java | 14 ++
.../commons/AbstractPersistenceManager.java | 133 +++++++++++++------
.../proxy/commons/EntityInvocationHandler.java | 16 ++-
.../fit/proxy/v4/APIBasicDesignTestITCase.java | 7 +
4 files changed, 128 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a5e983c9/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
index f1b9eb5..b06b594 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractCollectionInvocationHandler.java
@@ -56,6 +56,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
protected Collection<String> referenceItems;
+ protected Collection<T> newest;
+
protected final URI baseURI;
protected CommonURIBuilder<?> uri;
@@ -67,6 +69,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
private final Map<Class<? extends AbstractTerm>, Object> annotationsByTerm =
new HashMap<Class<? extends AbstractTerm>, Object>();
+ private boolean changed = false;
+
public AbstractCollectionInvocationHandler(
final AbstractService<?> service,
final Collection<T> items,
@@ -78,6 +82,7 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
this.itemRef = itemRef;
this.items = items;
this.referenceItems = new ArrayList<String>();
+ this.newest = new ArrayList<T>();
this.uri = uri;
this.baseURI = this.uri == null ? null : this.uri.build();
}
@@ -176,6 +181,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
service.getContext().entityContext().attachNew(handler);
}
}
+ changed = true;
+ newest.add(element);
return items.add(element);
}
@@ -191,6 +198,7 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
return false;
}
+ changed = true;
return referenceItems.add(id.toASCIIString());
}
@@ -249,6 +257,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
@Override
public boolean addAll(final Collection<? extends T> collection) {
+ changed = true;
+ newest.addAll(collection);
return items.addAll(collection);
}
@@ -325,4 +335,8 @@ public abstract class AbstractCollectionInvocationHandler<T extends Serializable
this.uri = this.baseURI == null ? null : getClient().newURIBuilder(baseURI.toASCIIString());
this.nextPageURI = null;
}
+
+ public boolean isChanged() {
+ return changed;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a5e983c9/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractPersistenceManager.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractPersistenceManager.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractPersistenceManager.java
index 62b701a..03d9072 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractPersistenceManager.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractPersistenceManager.java
@@ -174,51 +174,13 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
: ODataLinkType.ENTITY_NAVIGATION;
final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
-
for (Object proxy : type == ODataLinkType.ENTITY_SET_NAVIGATION
? (Collection<?>) property.getValue() : Collections.singleton(property.getValue())) {
final EntityInvocationHandler target = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
- final AttachedEntityStatus status;
- if (!service.getContext().entityContext().isAttached(target)) {
- status = resolveNavigationLink(property.getKey(), target);
- } else {
- status = service.getContext().entityContext().getStatus(target);
- }
-
- LOG.debug("Found link to '{}({})'", target, status);
-
- final URI editLink = target.getEntity().getEditLink();
-
- if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
- LOG.debug("Add link to '{}'", target);
- entity.addLink(buildNavigationLink(
- property.getKey().name(),
- URIUtils.getURI(service.getClient().getServiceRoot(), editLink.toASCIIString()), type));
- } else {
- if (!items.contains(target)) {
- pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
- pos++;
- }
-
- final Integer targetPos = items.get(target);
- if (targetPos == null) {
- // schedule update for the current object
- LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), handler, target);
- toBeLinked.add(target);
- } else if (status == AttachedEntityStatus.CHANGED) {
- LOG.debug("Changed: '{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
- entity.addLink(buildNavigationLink(
- property.getKey().name(),
- URIUtils.getURI(service.getClient().getServiceRoot(), editLink.toASCIIString()), type));
- } else {
- // create the link for the current object
- LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);
-
- entity.addLink(buildNavigationLink(property.getKey().name(), URI.create("$" + targetPos), type));
- }
- }
+ toBeLinked.addAll(processLinkChanges(
+ handler, target, property.getKey(), type, pos, items, delayedUpdates, changeset));
}
if (!toBeLinked.isEmpty()) {
@@ -236,6 +198,41 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
}
}
+ // Required by linking provided on existent object. Say:
+ // container.getCustomers().getByKey(1).getOrders().add(order)
+ // Required by linking provided via entity reference ID. Say:
+ // container.getCustomers().getByKey(1).getOrders().addRef(order)
+ for (Map.Entry<NavigationProperty, Object> property : handler.linkCache.entrySet()) {
+ if (property.getValue() instanceof Proxy) {
+ final InvocationHandler target = Proxy.getInvocationHandler(property.getValue());
+
+ if (target instanceof EntityCollectionInvocationHandler
+ && ((EntityCollectionInvocationHandler) target).isChanged()) {
+
+ final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
+ ? ODataLinkType.ENTITY_SET_NAVIGATION
+ : ODataLinkType.ENTITY_NAVIGATION;
+
+ final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
+
+ for (Object proxy : ((EntityCollectionInvocationHandler) target).newest) {
+ final EntityInvocationHandler targetEntity = (EntityInvocationHandler) Proxy.getInvocationHandler(proxy);
+
+ toBeLinked.addAll(processLinkChanges(
+ handler, targetEntity, property.getKey(), type, pos, items, delayedUpdates, changeset));
+ }
+
+ if (!toBeLinked.isEmpty()) {
+ delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
+ }
+
+ for (String ref : ((EntityCollectionInvocationHandler<?>) target).referenceItems) {
+ delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, ref));
+ }
+ }
+ }
+ }
+
if (entity instanceof ODataEntity) {
for (Map.Entry<String, AnnotatableInvocationHandler> entry : handler.getNavPropAnnotatableHandlers().entrySet()) {
@@ -305,6 +302,62 @@ abstract class AbstractPersistenceManager implements PersistenceManager {
return pos;
}
+ protected Set<EntityInvocationHandler> processLinkChanges(
+ final EntityInvocationHandler source,
+ final EntityInvocationHandler target,
+ final NavigationProperty property,
+ final ODataLinkType type,
+ int pos,
+ final TransactionItems items,
+ final List<EntityLinkDesc> delayedUpdates,
+ final PersistenceChanges changeset) {
+
+ final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
+
+ final AttachedEntityStatus status;
+ if (!service.getContext().entityContext().isAttached(target)) {
+ status = resolveNavigationLink(property, target);
+ } else {
+ status = service.getContext().entityContext().getStatus(target);
+ }
+
+ LOG.debug("Found link to '{}({})'", target, status);
+
+ final URI editLink = target.getEntity().getEditLink();
+
+ if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
+ LOG.debug("Add link to '{}'", target);
+ source.getEntity().addLink(buildNavigationLink(
+ property.name(),
+ URIUtils.getURI(service.getClient().getServiceRoot(), editLink.toASCIIString()), type));
+ } else {
+ if (!items.contains(target)) {
+ pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
+ pos++;
+ }
+
+ final Integer targetPos = items.get(target);
+ if (targetPos == null) {
+ // schedule update for the current object
+ LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), source, target);
+ toBeLinked.add(target);
+ } else if (status == AttachedEntityStatus.CHANGED) {
+ LOG.debug("Changed: '{}' from '{}' to (${}) '{}'", type.name(), source, targetPos, target);
+ source.getEntity().addLink(buildNavigationLink(
+ property.name(),
+ URIUtils.getURI(service.getClient().getServiceRoot(), editLink.toASCIIString()), type));
+ } else {
+ // create the link for the current object
+ LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), source, targetPos, target);
+
+ source.getEntity().addLink(
+ buildNavigationLink(property.name(), URI.create("$" + targetPos), type));
+ }
+ }
+
+ return toBeLinked;
+ }
+
protected void processDelayedUpdates(
final List<EntityLinkDesc> delayedUpdates,
int pos,
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a5e983c9/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index 054604b..51d62ad 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
@@ -294,10 +294,21 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
return isChanged(true);
}
- public boolean isChanged(final boolean includeMedia) {
+ public boolean isChanged(final boolean deep) {
+ boolean linkedChanges = false;
+ for (Map.Entry<NavigationProperty, Object> link : linkCache.entrySet()) {
+ final InvocationHandler handler = Proxy.getInvocationHandler(link.getValue());
+ if (handler instanceof EntityInvocationHandler) {
+ linkedChanges = linkedChanges || ((EntityInvocationHandler) handler).isChanged();
+ } else if (handler instanceof EntityCollectionInvocationHandler) {
+ linkedChanges = linkedChanges || ((EntityCollectionInvocationHandler) handler).isChanged();
+ }
+ }
+
return this.linkChanges.hashCode() != this.linksTag
|| this.propertyChanges.hashCode() != this.propertiesTag
- || (includeMedia && (this.stream != null
+ || (deep && (linkedChanges
+ || this.stream != null
|| !this.streamedPropertyChanges.isEmpty()));
}
@@ -355,6 +366,7 @@ public class EntityInvocationHandler extends AbstractStructuredInvocationHandler
if (navPropValue != null) {
cacheLink(property, navPropValue);
+ attach();
}
return navPropValue;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a5e983c9/fit/src/test/java/org/apache/olingo/fit/proxy/v4/APIBasicDesignTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/APIBasicDesignTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/APIBasicDesignTestITCase.java
index 15076d0..6db0317 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/APIBasicDesignTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/APIBasicDesignTestITCase.java
@@ -115,6 +115,13 @@ public class APIBasicDesignTestITCase extends AbstractTestITCase {
container.getCustomers().getByKey(1).setOrders(orders);
container.flush();
}
+
+ @Test
+ public void addViaReference2() {
+ final Order order = container.getOrders().getByKey(8).load();
+ container.getCustomers().getByKey(1).getOrders().addRef(order);
+ container.flush();
+ }
@Test
public void readAndCheckForPrimitive() {