001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo.sco;
012:
013: import com.versant.core.jdo.VersantPersistenceManagerImp;
014: import com.versant.core.jdo.VersantStateManager;
015: import com.versant.core.common.CollectionDiff;
016: import com.versant.core.common.VersantFieldMetaData;
017: import com.versant.core.common.PersistenceContext;
018:
019: import javax.jdo.spi.PersistenceCapable;
020: import java.util.*;
021:
022: public class SCOHashMap extends java.util.HashMap implements
023: VersantSCOMap, VersantAdvancedSCO {
024:
025: private transient PersistenceCapable owner;
026: private transient VersantStateManager stateManager;
027: private final transient VersantFieldMetaData fmd;
028: private transient MapDiffUtil diffUtil;
029: private transient Map beforeMap = new HashMap();
030:
031: private SCOHashMap(PersistenceCapable owner,
032: VersantFieldMetaData fmd) {
033: this .owner = owner;
034: this .fmd = fmd;
035: diffUtil = new MapDiffUtil(fmd);
036: }
037:
038: public SCOHashMap(PersistenceCapable owner,
039: VersantStateManager stateManager, VersantFieldMetaData fmd,
040: Map beforeMap) {
041: this (owner, fmd);
042: if (!owner.jdoIsNew()) {
043: this .beforeMap.putAll(beforeMap);
044: }
045: putAll(beforeMap);
046: this .stateManager = stateManager;
047: }
048:
049: public SCOHashMap(PersistenceCapable owner,
050: VersantStateManager stateManager, VersantFieldMetaData fmd,
051: MapData mapData) {
052: this (owner, fmd);
053: int n = mapData.entryCount;
054: Object[] keys = mapData.keys;
055: Object[] values = mapData.values;
056: for (int i = 0; i < n; i++) {
057: beforeMap.put(keys[i], values[i]);
058: }
059: putAll(beforeMap);
060: this .stateManager = stateManager;
061: }
062:
063: public Set keySet() {
064: final Set kSet = super .keySet();
065: final class TmpKeySet extends AbstractSet {
066:
067: Set delegateSet = kSet;
068:
069: public Iterator iterator() {
070: return delegateSet.iterator();
071: }
072:
073: public int size() {
074: return delegateSet.size();
075: }
076:
077: public boolean contains(Object o) {
078: return containsKey(o);
079: }
080:
081: public void clear() {
082: delegateSet.clear();
083: }
084:
085: public boolean remove(Object o) {
086: Object removed = SCOHashMap.this .remove(o);
087: return removed != null;
088: }
089: }
090: return new TmpKeySet();
091: }
092:
093: public Object remove(Object key) {
094: makeDirty();
095: return super .remove(key);
096: }
097:
098: public Object put(Object key, Object value) {
099: makeDirty();
100: return super .put(key, value);
101: }
102:
103: public void putAll(Map t) {
104: makeDirty();
105: super .putAll(t);
106: }
107:
108: public void clear() {
109: final int size = size();
110: super .clear();
111: if (size != 0)
112: makeDirty();
113: }
114:
115: public Object getOwner() {
116: return owner;
117: }
118:
119: public void makeTransient() {
120: owner = null;
121: stateManager = null;
122: }
123:
124: public void makeDirty() {
125: if (stateManager != null) {
126: stateManager.makeDirty(owner, fmd.getManagedFieldNo());
127: }
128: }
129:
130: public void reset() {
131: beforeMap.clear();
132: beforeMap.putAll(this );
133: }
134:
135: public CollectionDiff getMapDiff(PersistenceContext pm) {
136: return diffUtil.getDiff(this , beforeMap, pm);
137: }
138:
139: /**
140: * Put references to all the keys and values into mapData. If the keys
141: * and/or values are PC instances then the instances themselves or their
142: * OIDs may be stored in mapData.
143: */
144: public MapData fillMapData(MapData mapData) {
145: int size = size();
146: mapData.entryCount = size;
147: Object[] newKeys;
148: Object[] oldKeys = mapData.keys;
149: if (oldKeys == null || oldKeys.length < size) {
150: newKeys = new Object[size];
151: } else {
152: newKeys = oldKeys;
153: }
154: Object[] newValues;
155: Object[] oldValues = mapData.values;
156: if (oldValues == null || oldValues.length < size) {
157: newValues = new Object[size];
158: } else {
159: newValues = oldValues;
160: }
161: int i = 0;
162: for (Iterator it = this .entrySet().iterator(); it.hasNext();) {
163: Entry entry = (Entry) it.next();
164: newKeys[i] = entry.getKey();
165: newValues[i++] = entry.getValue();
166: }
167: mapData.keys = newKeys;
168: mapData.values = newValues;
169: return mapData;
170: }
171: }
|