/* * 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 myservice.mynamespace.data; import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; public class TransactionalEntityManager { private Map<String, List<Entity>> entities = new HashMap<String, List<Entity>>(); private Map<String, List<Entity>> backupEntities = new HashMap<String, List<Entity>>(); private Map<String, IdentityHashMap<Entity, Entity>> copyMap = new HashMap<String, IdentityHashMap<Entity, Entity>>(); private boolean isInTransaction = false; private Edm edm; public TransactionalEntityManager(final Edm edm) { this.edm = edm; } public List<Entity> getEntityCollection(final String entitySetName) { if(!entities.containsKey(entitySetName)) { entities.put(entitySetName, new ArrayList<Entity>()); } return entities.get(entitySetName); } public void beginTransaction() { if(!isInTransaction) { isInTransaction = true; copyCurrentState(); } } public void rollbackTransaction() { if(isInTransaction) { entities = backupEntities; backupEntities = new HashMap<String, List<Entity>>(); isInTransaction = false; } } public void commitTransaction() { if(isInTransaction) { backupEntities.clear(); isInTransaction = false; } } public void clear() { entities.clear(); backupEntities.clear(); } private void copyCurrentState() { copyMap.clear(); backupEntities.clear(); for(final String entitySetName : entities.keySet()) { final List<Entity> entityList = entities.get(entitySetName); backupEntities.put(entitySetName, new ArrayList<Entity>()); final List<Entity> backupEntityList = backupEntities.get(entitySetName); for(final Entity entity : entityList) { final EdmEntitySet entitySet = edm.getEntityContainer().getEntitySet(entitySetName); backupEntityList.add(copyEntityRecursively(entitySet, entity)); } } } private Entity copyEntityRecursively(final EdmEntitySet edmEntitySet, final Entity entity) { // Check if entity is already copied if(containsEntityInCopyMap(edmEntitySet.getName(), entity)) { return getEntityFromCopyMap(edmEntitySet.getName(), entity); } else { final Entity newEntity = copyEntity(entity); addEntityToCopyMap(edmEntitySet.getName(), entity, newEntity); // Create nested entities recursively for(final Link link : entity.getNavigationLinks()) { newEntity.getNavigationLinks().add(copyLink(edmEntitySet, link)); } return newEntity; } } private Link copyLink(final EdmEntitySet edmEntitySet, final Link link) { final Link newLink = new Link(); newLink.setBindingLink(link.getBindingLink()); newLink.setBindingLinks(new ArrayList<String>(link.getBindingLinks())); newLink.setHref(link.getHref()); newLink.setMediaETag(link.getMediaETag()); newLink.setRel(link.getRel()); newLink.setTitle(link.getTitle()); newLink.setType(link.getType()); // Single navigation link if(link.getInlineEntity() != null) { final EdmEntitySet linkedEdmEntitySet = (EdmEntitySet) edmEntitySet.getRelatedBindingTarget(link.getTitle()); newLink.setInlineEntity(copyEntityRecursively(linkedEdmEntitySet, link.getInlineEntity())); } // Collection navigation link if(link.getInlineEntitySet() != null) { final EdmEntitySet linkedEdmEntitySet = (EdmEntitySet) edmEntitySet.getRelatedBindingTarget(link.getTitle()); final EntityCollection inlineEntitySet = link.getInlineEntitySet(); final EntityCollection newInlineEntitySet = new EntityCollection(); newInlineEntitySet.setBaseURI(inlineEntitySet.getBaseURI()); newInlineEntitySet.setCount(inlineEntitySet.getCount()); newInlineEntitySet.setDeltaLink(inlineEntitySet.getDeltaLink()); newInlineEntitySet.setId(inlineEntitySet.getId()); newInlineEntitySet.setNext(inlineEntitySet.getNext()); for(final Entity inlineEntity : inlineEntitySet.getEntities()) { newInlineEntitySet.getEntities().add(copyEntityRecursively(linkedEdmEntitySet, inlineEntity)); } newLink.setInlineEntitySet(newInlineEntitySet); } return newLink; } private Entity copyEntity(final Entity entity) { final Entity newEntity = new Entity(); newEntity.setBaseURI(entity.getBaseURI()); newEntity.setEditLink(entity.getEditLink()); newEntity.setETag(entity.getETag()); newEntity.setId(entity.getId()); newEntity.setMediaContentSource(entity.getMediaContentSource()); newEntity.setMediaContentType(entity.getMediaContentType()); newEntity.setSelfLink(entity.getSelfLink()); newEntity.setMediaETag(entity.getMediaETag()); newEntity.setType(entity.getType()); newEntity.getProperties().addAll(entity.getProperties()); return newEntity; } private void addEntityToCopyMap(final String entitySetName, final Entity srcEntity, final Entity destEntity) { if(!copyMap.containsKey(entitySetName)) { copyMap.put(entitySetName, new IdentityHashMap<Entity, Entity>()); } copyMap.get(entitySetName).put(srcEntity, destEntity); } private boolean containsEntityInCopyMap(final String entitySetName, final Entity srcEntity) { return getEntityFromCopyMap(entitySetName, srcEntity) != null; } private Entity getEntityFromCopyMap(final String entitySetName, final Entity srcEntity) { if(!copyMap.containsKey(entitySetName)) { return null; } return copyMap.get(entitySetName).get(srcEntity); } }