/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.sessions; import java.util.*; import org.eclipse.persistence.internal.queries.ContainerPolicy; /** * Change record used by DirectMapMapping. * Only needs to track unique keys added/removed. */ public class DirectMapChangeRecord extends DeferrableChangeRecord { protected HashMap addObjectsList; protected HashMap removeObjectsList; public DirectMapChangeRecord() { super(); } public DirectMapChangeRecord(ObjectChangeSet owner) { this.owner = owner; } /** * Returns true if the change set has changes. */ public boolean hasChanges() { return (!((this.addObjectsList == null || this.addObjectsList.isEmpty()) && ((this.removeObjectsList == null || this.removeObjectsList.isEmpty())))) || getOwner().isNew(); } /** * This method will be used to merge one record into another. */ public void mergeRecord(ChangeRecord mergeFromRecord, UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) { if (((DeferrableChangeRecord)mergeFromRecord).isDeferred()){ if (this.hasChanges()){ //merging into existing change record need to combine changes ((DeferrableChangeRecord)mergeFromRecord).getMapping().calculateDeferredChanges(mergeFromRecord, mergeToChangeSet.getSession()); }else{ this.isDeferred = true; this.originalCollection = ((DeferrableChangeRecord)mergeFromRecord).originalCollection; this.latestCollection = ((DeferrableChangeRecord)mergeFromRecord).latestCollection; return; } } Iterator addKeys = ((DirectMapChangeRecord)mergeFromRecord).getAddObjects().keySet().iterator(); while (addKeys.hasNext()) { Object key = addKeys.next(); if (!this.getAddObjects().containsKey(key)) { if (this.getRemoveObjects().containsKey(key)) { this.getRemoveObjects().remove(key); } else { this.getAddObjects().put(key, ((DirectMapChangeRecord)mergeFromRecord).getAddObjects().get(key)); } } } Iterator removeKeys = ((DirectMapChangeRecord)mergeFromRecord).getRemoveObjects().keySet().iterator(); while (removeKeys.hasNext()) { Object key = removeKeys.next(); if (!this.getRemoveObjects().containsKey(key)) { if (this.getAddObjects().containsKey(key)) { this.getAddObjects().remove(key); } else { this.getRemoveObjects().put(key, ((DirectMapChangeRecord)mergeFromRecord).getRemoveObjects().get(key)); } } } } /** * Adds the items that were added to the collection. */ public void addAdditionChange(HashMap additions) { if (getAddObjects().size() == 0) { addObjectsList = additions; return; } for (Iterator i = additions.keySet().iterator(); i.hasNext(); ) { Object key = i.next(); if (getAddObjects().containsKey(key)) { getAddObjects().put(key, additions.get(key)); } else if (additions.get(key).equals(getAddObjects().get(key))) { getAddObjects().put(key, additions.get(key)); } } } /** * Adds the items that were removed from the collection. */ public void addRemoveChange(HashMap subtractions) { if (getRemoveObjects().size() == 0) { this.removeObjectsList = subtractions; return; } for (Iterator i = subtractions.keySet().iterator(); i.hasNext(); ) { Object key = i.next(); if (!getRemoveObjects().containsKey(key)) { getRemoveObjects().put(key, subtractions.get(key)); } else if (subtractions.get(key).equals(getRemoveObjects().get(key))) { getRemoveObjects().put(key, subtractions.get(key)); } } } /** * Adds the items that were added to the collection. */ public void addAdditionChange(Object key, Object value) { if ( getRemoveObjects().containsKey(key) ) { if ( value.equals(getRemoveObjects().get(key)) ) { getRemoveObjects().remove(key); }else { getAddObjects().put(key, value); } } else { getAddObjects().put(key, value); } } /** * Adds the items that were removed from the collection. */ public void addRemoveChange(Object key, Object value) { //if an entry already exists in the remove it must remain untill added // as it contains the original removal. if (getAddObjects().containsKey(key)) { getAddObjects().remove(key); } else if (!getRemoveObjects().containsKey(key)) { getRemoveObjects().put(key, value); } } /** * Sets the added items list. */ public void setAddObjects(HashMap addObjects) { this.addObjectsList = addObjects; } /** * Returns the added items list. */ public HashMap getAddObjects() { if (addObjectsList == null) { addObjectsList = new HashMap(); } return addObjectsList; } /** * Sets the removed items list. */ public void setRemoveObjects(HashMap removeObjects) { this.removeObjectsList = removeObjects; } /** * Returns the removed items list. */ public HashMap getRemoveObjects() { if (removeObjectsList == null) { removeObjectsList = new HashMap(); } return removeObjectsList; } /** * This method will be used to update the objectsChangeSets references. */ public void updateReferences(UnitOfWorkChangeSet mergeToChangeSet, UnitOfWorkChangeSet mergeFromChangeSet) { // Nothing for this record type to do as it does not reference any changesets. } /** * Recreates the original state of the collection. */ public void internalRecreateOriginalCollection(Object currentMap, AbstractSession session) { ContainerPolicy cp = this.mapping.getContainerPolicy(); if(this.removeObjectsList != null) { Iterator it = this.removeObjectsList.entrySet().iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); cp.addInto(entry.getKey(), entry.getValue(), currentMap, session); } } if(this.addObjectsList != null) { Iterator it = this.addObjectsList.entrySet().iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); cp.removeFrom(entry.getKey(), entry.getValue(), currentMap, session); } } } /** * Clears info about added / removed objects set by change tracker. */ public void clearChanges() { if(this.removeObjectsList != null) { this.removeObjectsList.clear(); } if(this.addObjectsList != null) { this.addObjectsList.clear(); } } }