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:29 UTC
[5/9] git commit: Still 2 IT failing
Still 2 IT failing
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/8a3a1e03
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/8a3a1e03
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/8a3a1e03
Branch: refs/heads/master
Commit: 8a3a1e0358fa6d18fea58cc47c5ad20918fce8d5
Parents: 1abd8e7
Author: Francesco Chicchiriccò <--global>
Authored: Mon May 19 08:19:41 2014 +0200
Committer: Francesco Chicchiriccò <--global>
Committed: Mon May 19 08:19:41 2014 +0200
----------------------------------------------------------------------
.../apache/olingo/ext/proxy/api/Container.java | 32 --
.../ext/proxy/api/PersistenceManager.java | 32 ++
.../commons/AbstractInvocationHandler.java | 2 +-
.../olingo/ext/proxy/commons/ContainerImpl.java | 551 -------------------
.../EntityContainerInvocationHandler.java | 2 +-
.../proxy/commons/PersistenceManagerImpl.java | 551 +++++++++++++++++++
.../src/main/resources/container.vm | 4 +-
.../astoriadefaultservice/DefaultContainer.java | 4 +-
.../opentypesservicev3/DefaultContainer.java | 4 +-
.../primitivekeysservice/TestContext.java | 4 +-
.../astoriadefaultservice/DefaultContainer.java | 4 +-
.../opentypesservicev4/DefaultContainer.java | 4 +-
.../odatawcfservice/InMemoryEntities.java | 4 +-
13 files changed, 599 insertions(+), 599 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
deleted file mode 100644
index b95b341..0000000
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/Container.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.api;
-
-import java.io.Serializable;
-
-/**
- * Interface for container operations.
- */
-public interface Container extends Serializable {
-
- /**
- * Flushes all pending changes to the OData service.
- */
- void flush();
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
new file mode 100644
index 0000000..2d195bd
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/api/PersistenceManager.java
@@ -0,0 +1,32 @@
+/*
+ * 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.api;
+
+import java.io.Serializable;
+
+/**
+ * Interface for container operations.
+ */
+public interface PersistenceManager extends Serializable {
+
+ /**
+ * Flushes all pending changes to the OData service.
+ */
+ void flush();
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/AbstractInvocationHandler.java
----------------------------------------------------------------------
diff --git 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
index cc7eb36..c45b43b 100644
--- 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
@@ -194,7 +194,7 @@ abstract class AbstractInvocationHandler implements InvocationHandler {
// 2. IMPORTANT: flush any pending change *before* invoke if this operation is side effecting
if (annotation.type() == OperationType.ACTION) {
- new ContainerImpl(containerHandler.getFactory()).flush();
+ new PersistenceManagerImpl(containerHandler.getFactory()).flush();
}
// 3. invoke
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
----------------------------------------------------------------------
diff --git 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
deleted file mode 100644
index 0b8b464..0000000
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/ContainerImpl.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * 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.reflect.Proxy;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.olingo.client.api.communication.header.ODataPreferences;
-import org.apache.olingo.client.api.communication.request.ODataRequest;
-import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
-import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
-import org.apache.olingo.client.api.communication.request.batch.CommonODataBatchRequest;
-import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
-import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
-import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
-import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
-import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
-import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
-import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
-import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
-import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
-import org.apache.olingo.client.api.communication.response.ODataResponse;
-import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
-import org.apache.olingo.client.core.uri.URIUtils;
-import org.apache.olingo.commons.api.domain.CommonODataEntity;
-import org.apache.olingo.commons.api.domain.ODataLink;
-import org.apache.olingo.commons.api.domain.ODataLinkType;
-import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
-import org.apache.olingo.commons.api.format.ODataMediaFormat;
-import org.apache.olingo.ext.proxy.EntityContainerFactory;
-import org.apache.olingo.ext.proxy.api.Container;
-import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
-import org.apache.olingo.ext.proxy.context.AttachedEntity;
-import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
-import org.apache.olingo.ext.proxy.context.EntityLinkDesc;
-import org.apache.olingo.ext.proxy.utils.CoreUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class ContainerImpl implements Container {
-
- private static final long serialVersionUID = -3320312269235907501L;
-
- /**
- * Logger.
- */
- private static final Logger LOG = LoggerFactory.getLogger(ContainerImpl.class);
-
- private final EntityContainerFactory<?> factory;
-
- ContainerImpl(final EntityContainerFactory<?> factory) {
- this.factory = factory;
- }
-
- /**
- * Transactional changes commit.
- */
- @Override
- public void flush() {
- final CommonODataBatchRequest request =
- factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
- ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
-
- final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
-
- final ODataChangeset changeset = streamManager.addChangeset();
-
- final TransactionItems items = new TransactionItems();
- final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();
-
- int pos = 0;
-
- for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
- final AttachedEntityStatus status = attachedEntity.getStatus();
- if (((status != AttachedEntityStatus.ATTACHED
- && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
- && !items.contains(attachedEntity.getEntity())) {
- pos++;
- pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
- }
- }
-
- processDelayedUpdates(delayedUpdates, pos, items, changeset);
-
- final ODataBatchResponse response = streamManager.getResponse();
-
- if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
- && response.getStatusCode() != 202)
- || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
- && response.getStatusCode() != 200)) {
-
- throw new IllegalStateException("Operation failed");
- }
-
- if (!items.isEmpty()) {
- final Iterator<ODataBatchResponseItem> iter = response.getBody();
- if (!iter.hasNext()) {
- throw new IllegalStateException("Unexpected operation result");
- }
-
- final ODataBatchResponseItem item = iter.next();
- if (!(item instanceof ODataChangesetResponseItem)) {
- throw new IllegalStateException("Unexpected batch response item " + item.getClass().getSimpleName());
- }
-
- final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;
-
- for (Integer changesetItemId : items.sortedValues()) {
- LOG.debug("Expected changeset item {}", changesetItemId);
- final ODataResponse res = chgres.next();
- if (res.getStatusCode() >= 400) {
- throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
- }
-
- final EntityInvocationHandler handler = items.get(changesetItemId);
-
- if (handler != null) {
- if (res instanceof ODataEntityCreateResponse && res.getStatusCode() == 201) {
- handler.setEntity(((ODataEntityCreateResponse) res).getBody());
- LOG.debug("Upgrade created object '{}'", handler);
- } else if (res instanceof ODataEntityUpdateResponse && res.getStatusCode() == 200) {
- handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
- LOG.debug("Upgrade updated object '{}'", handler);
- }
- }
- }
- }
-
- factory.getContext().detachAll();
- }
-
- private void batch(
- final EntityInvocationHandler handler,
- final CommonODataEntity entity,
- final ODataChangeset changeset) {
-
- switch (factory.getContext().entityContext().getStatus(handler)) {
- case NEW:
- batchCreate(handler, entity, changeset);
- break;
-
- case CHANGED:
- batchUpdate(handler, entity, changeset);
- break;
-
- case DELETED:
- batchDelete(handler, entity, changeset);
- break;
-
- default:
- if (handler.isChanged()) {
- batchUpdate(handler, entity, changeset);
- }
- }
- }
-
- private void batchCreate(
- final EntityInvocationHandler handler,
- final CommonODataEntity entity,
- final ODataChangeset changeset) {
-
- LOG.debug("Create '{}'", handler);
-
- changeset.addRequest(
- factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
- }
-
- private void batchUpdateMediaEntity(
- final EntityInvocationHandler handler,
- final URI uri,
- final InputStream input,
- final ODataChangeset changeset) {
-
- LOG.debug("Update media entity '{}'", uri);
-
- final ODataMediaEntityUpdateRequest<?> req =
- factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
-
- req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
- ? ODataMediaFormat.WILDCARD.toString()
- : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());
-
- if (StringUtils.isNotBlank(handler.getETag())) {
- req.setIfMatch(handler.getETag());
- }
-
- changeset.addRequest(req);
- }
-
- private void batchUpdateMediaResource(
- final EntityInvocationHandler handler,
- final URI uri,
- final InputStream input,
- final ODataChangeset changeset) {
-
- LOG.debug("Update media entity '{}'", uri);
-
- final ODataStreamUpdateRequest req = factory.getClient().
- getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
-
- if (StringUtils.isNotBlank(handler.getETag())) {
- req.setIfMatch(handler.getETag());
- }
-
- changeset.addRequest(req);
- }
-
- private void batchUpdate(
- final EntityInvocationHandler handler,
- final CommonODataEntity changes,
- final ODataChangeset changeset) {
-
- LOG.debug("Update '{}'", handler.getEntityURI());
-
- final ODataEntityUpdateRequest<CommonODataEntity> req =
- factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
- ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(handler.getEntityURI(),
- org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
- : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(handler.getEntityURI(),
- org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
-
- req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
-
- if (StringUtils.isNotBlank(handler.getETag())) {
- req.setIfMatch(handler.getETag());
- }
-
- changeset.addRequest(req);
- }
-
- private void batchUpdate(
- final EntityInvocationHandler handler,
- final URI uri,
- final CommonODataEntity changes,
- final ODataChangeset changeset) {
-
- LOG.debug("Update '{}'", uri);
-
- final ODataEntityUpdateRequest<CommonODataEntity> req =
- 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)
- : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
- getEntityUpdateRequest(uri,
- org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
-
- req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
-
- if (StringUtils.isNotBlank(handler.getETag())) {
- req.setIfMatch(handler.getETag());
- }
-
- changeset.addRequest(req);
- }
-
- private void batchDelete(
- final EntityInvocationHandler handler,
- final CommonODataEntity entity,
- final ODataChangeset changeset) {
-
- final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
- LOG.debug("Delete '{}'", deleteURI);
-
- final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
-
- if (StringUtils.isNotBlank(handler.getETag())) {
- req.setIfMatch(handler.getETag());
- }
-
- changeset.addRequest(req);
- }
-
- private int processEntityContext(
- final EntityInvocationHandler handler,
- int pos,
- final TransactionItems items,
- final List<EntityLinkDesc> delayedUpdates,
- final ODataChangeset changeset) {
-
- LOG.debug("Process '{}'", handler);
-
- items.put(handler, null);
-
- final CommonODataEntity entity = handler.getEntity();
- entity.getNavigationLinks().clear();
-
- final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
-
- if (AttachedEntityStatus.DELETED != currentStatus) {
- entity.getProperties().clear();
- CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
- }
-
- for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
- final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
- ? ODataLinkType.ENTITY_SET_NAVIGATION
- : ODataLinkType.ENTITY_NAVIGATION;
-
- final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
- final String serviceRoot = factory.getClient().getServiceRoot();
-
- 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 = factory.getContext().entityContext().getStatus(target);
-
- final URI editLink = target.getEntity().getEditLink();
-
- if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
- entity.addLink(buildNavigationLink(
- property.getKey().name(),
- URIUtils.getURI(serviceRoot, 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) {
- entity.addLink(buildNavigationLink(
- property.getKey().name(),
- URIUtils.getURI(serviceRoot, 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));
- }
- }
- }
-
- if (!toBeLinked.isEmpty()) {
- delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
- }
- }
-
- // insert into the batch
- LOG.debug("{}: Insert '{}' into the batch", pos, handler);
- batch(handler, entity, changeset);
-
- items.put(handler, pos);
-
- int startingPos = pos;
-
- if (handler.getEntity().isMediaEntity()) {
-
- // update media properties
- if (!handler.getPropertyChanges().isEmpty()) {
- final URI targetURI = currentStatus == AttachedEntityStatus.NEW
- ? URI.create("$" + startingPos)
- : URIUtils.getURI(
- factory.getClient().getServiceRoot(),
- handler.getEntity().getEditLink().toASCIIString());
- batchUpdate(handler, targetURI, entity, changeset);
- pos++;
- items.put(handler, pos);
- }
-
- // update media content
- if (handler.getStreamChanges() != null) {
- final URI targetURI = currentStatus == AttachedEntityStatus.NEW
- ? URI.create("$" + startingPos + "/$value")
- : URIUtils.getURI(
- factory.getClient().getServiceRoot(),
- handler.getEntity().getEditLink().toASCIIString() + "/$value");
-
- batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
-
- // update media info (use null key)
- pos++;
- items.put(null, pos);
- }
- }
-
- for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
- final URI targetURI = currentStatus == AttachedEntityStatus.NEW
- ? URI.create("$" + startingPos) : URIUtils.getURI(
- factory.getClient().getServiceRoot(),
- CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
-
- batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
-
- // update media info (use null key)
- pos++;
- items.put(handler, pos);
- }
-
- return pos;
- }
-
- private ODataLink buildNavigationLink(final String name, final URI uri, final ODataLinkType type) {
- ODataLink result;
-
- switch (type) {
- case ENTITY_NAVIGATION:
- result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
- break;
-
- case ENTITY_SET_NAVIGATION:
- result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
- break;
-
- default:
- throw new IllegalArgumentException("Invalid link type " + type.name());
- }
-
- return result;
- }
-
- private void processDelayedUpdates(
- final List<EntityLinkDesc> delayedUpdates,
- int pos,
- final TransactionItems items,
- final ODataChangeset changeset) {
-
- for (EntityLinkDesc delayedUpdate : delayedUpdates) {
- pos++;
- items.put(delayedUpdate.getSource(), pos);
-
- final CommonODataEntity changes =
- factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
-
- AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
-
- final URI sourceURI;
- if (status == AttachedEntityStatus.CHANGED) {
- sourceURI = URIUtils.getURI(
- factory.getClient().getServiceRoot(),
- delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
- } else {
- int sourcePos = items.get(delayedUpdate.getSource());
- sourceURI = URI.create("$" + sourcePos);
- }
-
- for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
- status = factory.getContext().entityContext().getStatus(target);
-
- final URI targetURI;
- if (status == AttachedEntityStatus.CHANGED) {
- targetURI = URIUtils.getURI(
- factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
- } else {
- int targetPos = items.get(target);
- targetURI = URI.create("$" + targetPos);
- }
-
- changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
- ? factory.getClient().getObjectFactory().
- newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
- : factory.getClient().getObjectFactory().
- newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
-
- LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
- }
-
- batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
- }
- }
-
- private class TransactionItems {
-
- private final List<EntityInvocationHandler> keys = new ArrayList<EntityInvocationHandler>();
-
- private final List<Integer> values = new ArrayList<Integer>();
-
- public EntityInvocationHandler get(final Integer value) {
- if (value != null && values.contains(value)) {
- return keys.get(values.indexOf(value));
- } else {
- return null;
- }
- }
-
- public Integer get(final EntityInvocationHandler key) {
- if (key != null && keys.contains(key)) {
- return values.get(keys.indexOf(key));
- } else {
- return null;
- }
- }
-
- public void remove(final EntityInvocationHandler key) {
- if (keys.contains(key)) {
- values.remove(keys.indexOf(key));
- keys.remove(key);
- }
- }
-
- public void put(final EntityInvocationHandler key, final Integer value) {
- // replace just in case of null current value; otherwise add the new entry
- if (key != null && keys.contains(key) && values.get(keys.indexOf(key)) == null) {
- remove(key);
- }
- keys.add(key);
- values.add(value);
- }
-
- public List<Integer> sortedValues() {
- final List<Integer> sortedValues = new ArrayList<Integer>(values);
- Collections.<Integer>sort(sortedValues);
- return sortedValues;
- }
-
- public boolean contains(final EntityInvocationHandler key) {
- return keys.contains(key);
- }
-
- public int size() {
- return keys.size();
- }
-
- public boolean isEmpty() {
- return keys.isEmpty();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
index 16b9bbf..3bbeae3 100644
--- a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/EntityContainerInvocationHandler.java
@@ -84,7 +84,7 @@ public final class EntityContainerInvocationHandler extends AbstractInvocationHa
if (isSelfMethod(method, args)) {
return invokeSelfMethod(method, args);
} else if ("flush".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
- new ContainerImpl(factory).flush();
+ new PersistenceManagerImpl(factory).flush();
return ClassUtils.returnVoid();
} else if ("operations".equals(method.getName()) && ArrayUtils.isEmpty(args)) {
final Class<?> returnType = method.getReturnType();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
----------------------------------------------------------------------
diff --git a/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
new file mode 100644
index 0000000..9c39c95
--- /dev/null
+++ b/ext/client-proxy/src/main/java/org/apache/olingo/ext/proxy/commons/PersistenceManagerImpl.java
@@ -0,0 +1,551 @@
+/*
+ * 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.reflect.Proxy;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.client.api.communication.header.ODataPreferences;
+import org.apache.olingo.client.api.communication.request.ODataRequest;
+import org.apache.olingo.client.api.communication.request.ODataStreamedRequest;
+import org.apache.olingo.client.api.communication.request.batch.BatchStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.CommonODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.streamed.ODataMediaEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.streamed.ODataStreamUpdateRequest;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
+import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.CommonODataEntity;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.ODataLinkType;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ODataMediaFormat;
+import org.apache.olingo.ext.proxy.EntityContainerFactory;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
+import org.apache.olingo.ext.proxy.api.annotations.NavigationProperty;
+import org.apache.olingo.ext.proxy.context.AttachedEntity;
+import org.apache.olingo.ext.proxy.context.AttachedEntityStatus;
+import org.apache.olingo.ext.proxy.context.EntityLinkDesc;
+import org.apache.olingo.ext.proxy.utils.CoreUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class PersistenceManagerImpl implements PersistenceManager {
+
+ private static final long serialVersionUID = -3320312269235907501L;
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(PersistenceManagerImpl.class);
+
+ private final EntityContainerFactory<?> factory;
+
+ PersistenceManagerImpl(final EntityContainerFactory<?> factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * Transactional changes commit.
+ */
+ @Override
+ public void flush() {
+ final CommonODataBatchRequest request =
+ factory.getClient().getBatchRequestFactory().getBatchRequest(factory.getClient().getServiceRoot());
+ ((ODataRequest) request).setAccept(factory.getClient().getConfiguration().getDefaultBatchAcceptFormat());
+
+ final BatchStreamManager streamManager = (BatchStreamManager) ((ODataStreamedRequest) request).execute();
+
+ final ODataChangeset changeset = streamManager.addChangeset();
+
+ final TransactionItems items = new TransactionItems();
+ final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();
+
+ int pos = 0;
+
+ for (AttachedEntity attachedEntity : factory.getContext().entityContext()) {
+ final AttachedEntityStatus status = attachedEntity.getStatus();
+ if (((status != AttachedEntityStatus.ATTACHED
+ && status != AttachedEntityStatus.LINKED) || attachedEntity.getEntity().isChanged())
+ && !items.contains(attachedEntity.getEntity())) {
+ pos++;
+ pos = processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
+ }
+ }
+
+ processDelayedUpdates(delayedUpdates, pos, items, changeset);
+
+ final ODataBatchResponse response = streamManager.getResponse();
+
+ if ((factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+ && response.getStatusCode() != 202)
+ || (factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) > 0
+ && response.getStatusCode() != 200)) {
+
+ throw new IllegalStateException("Operation failed");
+ }
+
+ if (!items.isEmpty()) {
+ final Iterator<ODataBatchResponseItem> iter = response.getBody();
+ if (!iter.hasNext()) {
+ throw new IllegalStateException("Unexpected operation result");
+ }
+
+ final ODataBatchResponseItem item = iter.next();
+ if (!(item instanceof ODataChangesetResponseItem)) {
+ throw new IllegalStateException("Unexpected batch response item " + item.getClass().getSimpleName());
+ }
+
+ final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;
+
+ for (Integer changesetItemId : items.sortedValues()) {
+ LOG.debug("Expected changeset item {}", changesetItemId);
+ final ODataResponse res = chgres.next();
+ if (res.getStatusCode() >= 400) {
+ throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
+ }
+
+ final EntityInvocationHandler handler = items.get(changesetItemId);
+
+ if (handler != null) {
+ if (res instanceof ODataEntityCreateResponse && res.getStatusCode() == 201) {
+ handler.setEntity(((ODataEntityCreateResponse) res).getBody());
+ LOG.debug("Upgrade created object '{}'", handler);
+ } else if (res instanceof ODataEntityUpdateResponse && res.getStatusCode() == 200) {
+ handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
+ LOG.debug("Upgrade updated object '{}'", handler);
+ }
+ }
+ }
+ }
+
+ factory.getContext().detachAll();
+ }
+
+ private void batch(
+ final EntityInvocationHandler handler,
+ final CommonODataEntity entity,
+ final ODataChangeset changeset) {
+
+ switch (factory.getContext().entityContext().getStatus(handler)) {
+ case NEW:
+ batchCreate(handler, entity, changeset);
+ break;
+
+ case CHANGED:
+ batchUpdate(handler, entity, changeset);
+ break;
+
+ case DELETED:
+ batchDelete(handler, entity, changeset);
+ break;
+
+ default:
+ if (handler.isChanged()) {
+ batchUpdate(handler, entity, changeset);
+ }
+ }
+ }
+
+ private void batchCreate(
+ final EntityInvocationHandler handler,
+ final CommonODataEntity entity,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Create '{}'", handler);
+
+ changeset.addRequest(
+ factory.getClient().getCUDRequestFactory().getEntityCreateRequest(handler.getEntitySetURI(), entity));
+ }
+
+ private void batchUpdateMediaEntity(
+ final EntityInvocationHandler handler,
+ final URI uri,
+ final InputStream input,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Update media entity '{}'", uri);
+
+ final ODataMediaEntityUpdateRequest<?> req =
+ factory.getClient().getStreamedRequestFactory().getMediaEntityUpdateRequest(uri, input);
+
+ req.setContentType(StringUtils.isBlank(handler.getEntity().getMediaContentType())
+ ? ODataMediaFormat.WILDCARD.toString()
+ : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());
+
+ if (StringUtils.isNotBlank(handler.getETag())) {
+ req.setIfMatch(handler.getETag());
+ }
+
+ changeset.addRequest(req);
+ }
+
+ private void batchUpdateMediaResource(
+ final EntityInvocationHandler handler,
+ final URI uri,
+ final InputStream input,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Update media entity '{}'", uri);
+
+ final ODataStreamUpdateRequest req = factory.getClient().
+ getStreamedRequestFactory().getStreamUpdateRequest(uri, input);
+
+ if (StringUtils.isNotBlank(handler.getETag())) {
+ req.setIfMatch(handler.getETag());
+ }
+
+ changeset.addRequest(req);
+ }
+
+ private void batchUpdate(
+ final EntityInvocationHandler handler,
+ final CommonODataEntity changes,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Update '{}'", handler.getEntityURI());
+
+ final ODataEntityUpdateRequest<CommonODataEntity> req =
+ factory.getClient().getServiceVersion().compareTo(ODataServiceVersion.V30) <= 0
+ ? ((org.apache.olingo.client.api.v3.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+ getEntityUpdateRequest(handler.getEntityURI(),
+ org.apache.olingo.client.api.communication.request.cud.v3.UpdateType.PATCH, changes)
+ : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+ getEntityUpdateRequest(handler.getEntityURI(),
+ org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+
+ req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
+
+ if (StringUtils.isNotBlank(handler.getETag())) {
+ req.setIfMatch(handler.getETag());
+ }
+
+ changeset.addRequest(req);
+ }
+
+ private void batchUpdate(
+ final EntityInvocationHandler handler,
+ final URI uri,
+ final CommonODataEntity changes,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Update '{}'", uri);
+
+ final ODataEntityUpdateRequest<CommonODataEntity> req =
+ 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)
+ : ((org.apache.olingo.client.api.v4.EdmEnabledODataClient) factory.getClient()).getCUDRequestFactory().
+ getEntityUpdateRequest(uri,
+ org.apache.olingo.client.api.communication.request.cud.v4.UpdateType.PATCH, changes);
+
+ req.setPrefer(new ODataPreferences(factory.getClient().getServiceVersion()).returnContent());
+
+ if (StringUtils.isNotBlank(handler.getETag())) {
+ req.setIfMatch(handler.getETag());
+ }
+
+ changeset.addRequest(req);
+ }
+
+ private void batchDelete(
+ final EntityInvocationHandler handler,
+ final CommonODataEntity entity,
+ final ODataChangeset changeset) {
+
+ final URI deleteURI = handler.getEntityURI() == null ? entity.getEditLink() : handler.getEntityURI();
+ LOG.debug("Delete '{}'", deleteURI);
+
+ final ODataDeleteRequest req = factory.getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
+
+ if (StringUtils.isNotBlank(handler.getETag())) {
+ req.setIfMatch(handler.getETag());
+ }
+
+ changeset.addRequest(req);
+ }
+
+ private int processEntityContext(
+ final EntityInvocationHandler handler,
+ int pos,
+ final TransactionItems items,
+ final List<EntityLinkDesc> delayedUpdates,
+ final ODataChangeset changeset) {
+
+ LOG.debug("Process '{}'", handler);
+
+ items.put(handler, null);
+
+ final CommonODataEntity entity = handler.getEntity();
+ entity.getNavigationLinks().clear();
+
+ final AttachedEntityStatus currentStatus = factory.getContext().entityContext().getStatus(handler);
+
+ if (AttachedEntityStatus.DELETED != currentStatus) {
+ entity.getProperties().clear();
+ CoreUtils.addProperties(factory.getClient(), handler.getPropertyChanges(), entity);
+ }
+
+ for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
+ final ODataLinkType type = Collection.class.isAssignableFrom(property.getValue().getClass())
+ ? ODataLinkType.ENTITY_SET_NAVIGATION
+ : ODataLinkType.ENTITY_NAVIGATION;
+
+ final Set<EntityInvocationHandler> toBeLinked = new HashSet<EntityInvocationHandler>();
+ final String serviceRoot = factory.getClient().getServiceRoot();
+
+ 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 = factory.getContext().entityContext().getStatus(target);
+
+ final URI editLink = target.getEntity().getEditLink();
+
+ if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED) && !target.isChanged()) {
+ entity.addLink(buildNavigationLink(
+ property.getKey().name(),
+ URIUtils.getURI(serviceRoot, 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) {
+ entity.addLink(buildNavigationLink(
+ property.getKey().name(),
+ URIUtils.getURI(serviceRoot, 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));
+ }
+ }
+ }
+
+ if (!toBeLinked.isEmpty()) {
+ delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
+ }
+ }
+
+ // insert into the batch
+ LOG.debug("{}: Insert '{}' into the batch", pos, handler);
+ batch(handler, entity, changeset);
+
+ items.put(handler, pos);
+
+ int startingPos = pos;
+
+ if (handler.getEntity().isMediaEntity()) {
+
+ // update media properties
+ if (!handler.getPropertyChanges().isEmpty()) {
+ final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+ ? URI.create("$" + startingPos)
+ : URIUtils.getURI(
+ factory.getClient().getServiceRoot(),
+ handler.getEntity().getEditLink().toASCIIString());
+ batchUpdate(handler, targetURI, entity, changeset);
+ pos++;
+ items.put(handler, pos);
+ }
+
+ // update media content
+ if (handler.getStreamChanges() != null) {
+ final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+ ? URI.create("$" + startingPos + "/$value")
+ : URIUtils.getURI(
+ factory.getClient().getServiceRoot(),
+ handler.getEntity().getEditLink().toASCIIString() + "/$value");
+
+ batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);
+
+ // update media info (use null key)
+ pos++;
+ items.put(null, pos);
+ }
+ }
+
+ for (Map.Entry<String, InputStream> streamedChanges : handler.getStreamedPropertyChanges().entrySet()) {
+ final URI targetURI = currentStatus == AttachedEntityStatus.NEW
+ ? URI.create("$" + startingPos) : URIUtils.getURI(
+ factory.getClient().getServiceRoot(),
+ CoreUtils.getMediaEditLink(streamedChanges.getKey(), entity).toASCIIString());
+
+ batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);
+
+ // update media info (use null key)
+ pos++;
+ items.put(handler, pos);
+ }
+
+ return pos;
+ }
+
+ private ODataLink buildNavigationLink(final String name, final URI uri, final ODataLinkType type) {
+ ODataLink result;
+
+ switch (type) {
+ case ENTITY_NAVIGATION:
+ result = factory.getClient().getObjectFactory().newEntityNavigationLink(name, uri);
+ break;
+
+ case ENTITY_SET_NAVIGATION:
+ result = factory.getClient().getObjectFactory().newEntitySetNavigationLink(name, uri);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid link type " + type.name());
+ }
+
+ return result;
+ }
+
+ private void processDelayedUpdates(
+ final List<EntityLinkDesc> delayedUpdates,
+ int pos,
+ final TransactionItems items,
+ final ODataChangeset changeset) {
+
+ for (EntityLinkDesc delayedUpdate : delayedUpdates) {
+ pos++;
+ items.put(delayedUpdate.getSource(), pos);
+
+ final CommonODataEntity changes =
+ factory.getClient().getObjectFactory().newEntity(delayedUpdate.getSource().getEntity().getTypeName());
+
+ AttachedEntityStatus status = factory.getContext().entityContext().getStatus(delayedUpdate.getSource());
+
+ final URI sourceURI;
+ if (status == AttachedEntityStatus.CHANGED) {
+ sourceURI = URIUtils.getURI(
+ factory.getClient().getServiceRoot(),
+ delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
+ } else {
+ int sourcePos = items.get(delayedUpdate.getSource());
+ sourceURI = URI.create("$" + sourcePos);
+ }
+
+ for (EntityInvocationHandler target : delayedUpdate.getTargets()) {
+ status = factory.getContext().entityContext().getStatus(target);
+
+ final URI targetURI;
+ if (status == AttachedEntityStatus.CHANGED) {
+ targetURI = URIUtils.getURI(
+ factory.getClient().getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
+ } else {
+ int targetPos = items.get(target);
+ targetURI = URI.create("$" + targetPos);
+ }
+
+ changes.addLink(delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
+ ? factory.getClient().getObjectFactory().
+ newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
+ : factory.getClient().getObjectFactory().
+ newEntitySetNavigationLink(delayedUpdate.getSourceName(), targetURI));
+
+ LOG.debug("'{}' from {} to {}", delayedUpdate.getType().name(), sourceURI, targetURI);
+ }
+
+ batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
+ }
+ }
+
+ private class TransactionItems {
+
+ private final List<EntityInvocationHandler> keys = new ArrayList<EntityInvocationHandler>();
+
+ private final List<Integer> values = new ArrayList<Integer>();
+
+ public EntityInvocationHandler get(final Integer value) {
+ if (value != null && values.contains(value)) {
+ return keys.get(values.indexOf(value));
+ } else {
+ return null;
+ }
+ }
+
+ public Integer get(final EntityInvocationHandler key) {
+ if (key != null && keys.contains(key)) {
+ return values.get(keys.indexOf(key));
+ } else {
+ return null;
+ }
+ }
+
+ public void remove(final EntityInvocationHandler key) {
+ if (keys.contains(key)) {
+ values.remove(keys.indexOf(key));
+ keys.remove(key);
+ }
+ }
+
+ public void put(final EntityInvocationHandler key, final Integer value) {
+ // replace just in case of null current value; otherwise add the new entry
+ if (key != null && keys.contains(key) && values.get(keys.indexOf(key)) == null) {
+ remove(key);
+ }
+ keys.add(key);
+ values.add(value);
+ }
+
+ public List<Integer> sortedValues() {
+ final List<Integer> sortedValues = new ArrayList<Integer>(values);
+ Collections.<Integer>sort(sortedValues);
+ return sortedValues;
+ }
+
+ public boolean contains(final EntityInvocationHandler key) {
+ return keys.contains(key);
+ }
+
+ public int size() {
+ return keys.size();
+ }
+
+ public boolean isEmpty() {
+ return keys.isEmpty();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/ext/pojogen-maven-plugin/src/main/resources/container.vm
----------------------------------------------------------------------
diff --git a/ext/pojogen-maven-plugin/src/main/resources/container.vm b/ext/pojogen-maven-plugin/src/main/resources/container.vm
index 362018d..d31024b 100644
--- a/ext/pojogen-maven-plugin/src/main/resources/container.vm
+++ b/ext/pojogen-maven-plugin/src/main/resources/container.vm
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
#foreach($ns in $namespaces)
import ${basePackage}.${ns}.*;
@@ -52,7 +52,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "$container.Name",
namespace = "$namespace",
isDefaultEntityContainer = $container.Default)
-public interface $utility.capitalize($container.Name) extends Container {
+public interface $utility.capitalize($container.Name) extends PersistenceManager {
#foreach($entitySet in $container.EntitySets)
$utility.capitalize($entitySet.Name) get$utility.capitalize($entitySet.Name)();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
index a89563e..784a96f 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/actionoverloading/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v3.actionoverloading.microsoft.test.odata.services.astoriadefaultservice.*;
import org.apache.olingo.fit.proxy.v3.actionoverloading.microsoft.test.odata.services.astoriadefaultservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "DefaultContainer",
namespace = "Microsoft.Test.OData.Services.AstoriaDefaultService",
isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
Customer getCustomer();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
index 513c854..95186f1 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/opentype/microsoft/test/odata/services/opentypesservicev3/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v3.opentype.microsoft.test.odata.services.opentypesservicev3.*;
import org.apache.olingo.fit.proxy.v3.opentype.microsoft.test.odata.services.opentypesservicev3.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "DefaultContainer",
namespace = "Microsoft.Test.OData.Services.OpenTypesServiceV3",
isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
Row getRow();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
index 5e9ef59..aa4f588 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/primitivekeys/microsoft/test/odata/services/primitivekeysservice/TestContext.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v3.primitivekeys.microsoft.test.odata.services.primitivekeysservice.*;
import org.apache.olingo.fit.proxy.v3.primitivekeys.microsoft.test.odata.services.primitivekeysservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "TestContext",
namespace = "Microsoft.Test.OData.Services.PrimitiveKeysService",
isDefaultEntityContainer = true)
-public interface TestContext extends Container {
+public interface TestContext extends PersistenceManager {
EdmTimeSet getEdmTimeSet();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
index 77b6759..894fd90 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v3/staticservice/microsoft/test/odata/services/astoriadefaultservice/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.*;
import org.apache.olingo.fit.proxy.v3.staticservice.microsoft.test.odata.services.astoriadefaultservice.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "DefaultContainer",
namespace = "Microsoft.Test.OData.Services.AstoriaDefaultService",
isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
Customer getCustomer();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
index 18df189..11d485e 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/opentype/microsoft/test/odata/services/opentypesservicev4/DefaultContainer.java
@@ -25,7 +25,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v4.opentype.microsoft.test.odata.services.opentypesservicev4.*;
import org.apache.olingo.fit.proxy.v4.opentype.microsoft.test.odata.services.opentypesservicev4.types.*;
@@ -50,7 +50,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "DefaultContainer",
namespace = "Microsoft.Test.OData.Services.OpenTypesServiceV4",
isDefaultEntityContainer = true)
-public interface DefaultContainer extends Container {
+public interface DefaultContainer extends PersistenceManager {
Row getRow();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8a3a1e03/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
index e2256f1..5ce328d 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/staticservice/microsoft/test/odata/services/odatawcfservice/InMemoryEntities.java
@@ -24,7 +24,7 @@ import org.apache.olingo.ext.proxy.api.annotations.EntityContainer;
import org.apache.olingo.ext.proxy.api.annotations.Operation;
import org.apache.olingo.ext.proxy.api.annotations.Parameter;
import org.apache.olingo.ext.proxy.api.annotations.Property;
-import org.apache.olingo.ext.proxy.api.Container;
+import org.apache.olingo.ext.proxy.api.PersistenceManager;
import org.apache.olingo.ext.proxy.api.OperationType;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.*;
import org.apache.olingo.fit.proxy.v4.staticservice.microsoft.test.odata.services.odatawcfservice.types.*;
@@ -49,7 +49,7 @@ import javax.xml.datatype.Duration;
@EntityContainer(name = "InMemoryEntities",
namespace = "Microsoft.Test.OData.Services.ODataWCFService",
isDefaultEntityContainer = true)
-public interface InMemoryEntities extends Container {
+public interface InMemoryEntities extends PersistenceManager {
Accounts getAccounts();
StoredPIs getStoredPIs();