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.HashMap;
021: import java.util.Hashtable;
022: import java.util.Iterator;
023: import java.util.Map;
024:
025: import com.versant.core.jdo.VersantPersistenceManagerImp;
026: import com.versant.core.jdo.VersantStateManager;
027:
028: public class SCOHashtable extends Hashtable implements VersantSCOMap,
029: VersantAdvancedSCO {
030:
031: private transient PersistenceCapable owner;
032: private transient VersantStateManager stateManager;
033: private final transient VersantFieldMetaData fmd;
034: private transient MapDiffUtil diffUtil;
035: private transient Map beforeMap = new HashMap();
036:
037: private SCOHashtable(PersistenceCapable owner,
038: VersantFieldMetaData fmd) {
039: this .owner = owner;
040: this .fmd = fmd;
041: diffUtil = new MapDiffUtil(fmd);
042: }
043:
044: public SCOHashtable(PersistenceCapable owner,
045: VersantStateManager stateManager, VersantFieldMetaData fmd,
046: Map beforeMap) {
047: this (owner, fmd);
048: if (!owner.jdoIsNew()) {
049: this .beforeMap.putAll(beforeMap);
050: }
051: putAll(beforeMap);
052: this .stateManager = stateManager;
053: }
054:
055: public SCOHashtable(PersistenceCapable owner,
056: VersantStateManager stateManager, VersantFieldMetaData fmd,
057: MapData mapData) {
058: this (owner, fmd);
059: int n = mapData.entryCount;
060: Object[] keys = mapData.keys;
061: Object[] values = mapData.values;
062: for (int i = 0; i < n; i++) {
063: beforeMap.put(keys[i], values[i]);
064: }
065: putAll(beforeMap);
066: this .stateManager = stateManager;
067: }
068:
069: public Object put(Object key, Object value) {
070: makeDirty();
071: return super .put(key, value);
072: }
073:
074: public Object remove(Object key) {
075: return checkModified(super .remove(key));
076: }
077:
078: public void putAll(Map t) {
079: makeDirty();
080: super .putAll(t);
081: }
082:
083: public void clear() {
084: final int size = size();
085: super .clear();
086: if (size != 0)
087: makeDirty();
088: }
089:
090: public Object getOwner() {
091: return owner;
092: }
093:
094: public void makeTransient() {
095: owner = null;
096: stateManager = null;
097: }
098:
099: public void makeDirty() {
100: if (stateManager != null) {
101: stateManager.makeDirty(owner, fmd.getManagedFieldNo());
102: }
103: }
104:
105: public void reset() {
106: beforeMap.clear();
107: beforeMap.putAll(this );
108: }
109:
110: private Object checkModified(Object obj) {
111: if (obj != null) {
112: makeDirty();
113: }
114: return obj;
115: }
116:
117: public CollectionDiff getMapDiff(PersistenceContext pm) {
118: return diffUtil.getDiff(this , beforeMap, pm);
119: }
120:
121: /**
122: * Put references to all the keys and values into mapData. If the keys
123: * and/or values are PC instances then the instances themselves or their
124: * OIDs may be stored in mapData.
125: */
126: public MapData fillMapData(MapData mapData) {
127: int size = size();
128: mapData.entryCount = size;
129: Object[] newKeys;
130: Object[] oldKeys = mapData.keys;
131: if (oldKeys == null || oldKeys.length < size) {
132: newKeys = new Object[size];
133: } else {
134: newKeys = oldKeys;
135: }
136: Object[] newValues;
137: Object[] oldValues = mapData.values;
138: if (oldValues == null || oldValues.length < size) {
139: newValues = new Object[size];
140: } else {
141: newValues = oldValues;
142: }
143: int i = 0;
144: for (Iterator it = this .entrySet().iterator(); it.hasNext();) {
145: Entry entry = (Entry) it.next();
146: newKeys[i] = entry.getKey();
147: newValues[i++] = entry.getValue();
148: }
149: mapData.keys = newKeys;
150: mapData.values = newValues;
151: return mapData;
152: }
153: }
|