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