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.common;
012:
013: import com.versant.core.jdo.VersantPersistenceManagerImp;
014: import com.versant.core.jdo.sco.CollectionDiffUtil;
015: import com.versant.core.jdo.sco.VersantSCOCollection;
016: import com.versant.core.jdo.sco.VersantSCOMap;
017: import com.versant.core.jdo.sco.MapDiffUtil;
018: import com.versant.core.jdo.PCStateMan;
019: import com.versant.core.jdo.PMProxy;
020: import com.versant.core.jdo.VersantStateManager;
021: import com.versant.core.metadata.FieldMetaData;
022: import com.versant.core.metadata.MDStatics;
023:
024: import javax.jdo.spi.PersistenceCapable;
025: import javax.jdo.PersistenceManager;
026: import java.util.*;
027:
028: /**
029: * A utility class that is used by State.
030: */
031: public final class StateUtil {
032:
033: public static Date getPValueForSCO(Date date) {
034: return date;
035: }
036:
037: /**
038: * Provide the diff for a Collection.
039: */
040: public static CollectionDiff getPValueForSCO(Collection col,
041: PersistenceContext pm, VersantStateManager sm,
042: FieldMetaData fmd) {
043: if (fmd.isReadOnly)
044: return null;
045: CollectionDiff diff = null;
046: if (col instanceof VersantSCOCollection) {
047: diff = ((VersantSCOCollection) col).getCollectionDiff(pm);
048: } else {
049: diff = CollectionDiffUtil.getNonSCOCollectionDiff(col, pm,
050: fmd);
051: }
052: FieldMetaData inverseFieldMetaData = fmd.inverseFieldMetaData;
053: if (fmd.category == MDStatics.CATEGORY_COLLECTION
054: && inverseFieldMetaData != null
055: && fmd.inverseFieldMetaData.fake) {
056: Object[] values = diff.insertedValues;
057: fixFakeFieldsOnChildren(values, pm, inverseFieldMetaData,
058: sm, false);
059: values = ((UnorderedCollectionDiff) diff).deletedValues;
060: fixFakeFieldsOnChildren(values, pm, inverseFieldMetaData,
061: sm, true);
062: }
063: return diff;
064: }
065:
066: private static void fixFakeFieldsOnChildren(Object[] values,
067: PersistenceContext pm, FieldMetaData inverseFieldMetaData,
068: VersantStateManager sm, boolean remove) {
069: if (values != null) {
070: for (int i = 0; i < values.length; i++) {
071: Object oid = values[i];
072: if (oid == null) {
073: throw BindingSupportImpl
074: .getInstance()
075: .invalidOperation(
076: "One-to-Many collections may not contain null values.");
077: }
078: PersistenceCapable pc = (PersistenceCapable) pm
079: .getObjectById(oid, false);
080: pm.getInternalSM(pc).setFakeMaster(
081: inverseFieldMetaData.stateFieldNo, sm, remove);
082: }
083: }
084: }
085:
086: public static CollectionDiff getPValueForSCO(Map map,
087: PersistenceContext pm, FieldMetaData fmd) {
088: if (map instanceof VersantSCOMap) {
089: return ((VersantSCOMap) map).getMapDiff(pm);
090: } else {
091: MapDiffUtil mapDiffUtil = new MapDiffUtil(fmd);
092: CollectionDiff collectionDiff = mapDiffUtil.getDiff(map,
093: null, pm);
094: collectionDiff.status = CollectionDiff.STATUS_NEW;
095: return collectionDiff;
096: }
097: }
098:
099: public static Object getPValueForRef(PersistenceCapable pc,
100: PersistenceContext pm) {
101: return pm.getInternalOID(pc);
102: }
103:
104: public static void doReachable(Collection col,
105: VersantPersistenceManagerImp sm) {
106: for (Iterator iterator = col.iterator(); iterator.hasNext();) {
107: Object o = iterator.next();
108: if (o != null)
109: sm.makeReachablePersistent(o);
110: }
111: }
112:
113: public static void doReachable(Map map,
114: VersantPersistenceManagerImp sm, FieldMetaData fmd) {
115: boolean keyIsRef = fmd.isMapKeyRef();
116: boolean valueIsRef = fmd.isMapValueRef();
117: final Set entrySet = map.entrySet();
118: for (Iterator iterator = entrySet.iterator(); iterator
119: .hasNext();) {
120: Map.Entry entry = (Map.Entry) iterator.next();
121: if (keyIsRef)
122: sm.makeReachablePersistent(entry.getKey());
123: if (valueIsRef)
124: sm.makeReachablePersistent(entry.getValue());
125: }
126: }
127:
128: public static void doReachable(Object[] array,
129: VersantPersistenceManagerImp sm) {
130: for (int i = 0; i < array.length; i++) {
131: if (array[i] != null)
132: sm.makeReachablePersistent(array[i]);
133: }
134: }
135:
136: public static void doReachable(PersistenceCapable pc,
137: VersantPersistenceManagerImp sm) {
138: sm.makeReachablePersistent(pc);
139: }
140:
141: public static void doReachableEmbeddedReference(
142: PersistenceCapable pc, VersantPersistenceManagerImp pm,
143: PCStateMan sm, FieldMetaData fmd) {
144: PersistenceManager otherPm = pc.jdoGetPersistenceManager();
145: if (otherPm != null) {
146: otherPm = ((PMProxy) otherPm).getRealPM();
147: }
148: if (otherPm != null && otherPm != pm) {
149: throw BindingSupportImpl.getInstance().unsupported(
150: "Sharing of embedded instances is not supported");
151: }
152: PCStateMan tmpSM = pm.getSMIfManaged(pc);
153: if (tmpSM != null) {
154: if (tmpSM == sm) {
155: //already persistent
156: } else {
157: throw BindingSupportImpl
158: .getInstance()
159: .unsupported(
160: "Sharing of embedded instances is not supported");
161: }
162: } else {
163: sm.createEmbeddedSM(pc, fmd);
164: }
165: }
166:
167: public static void retrieve(Map map,
168: VersantPersistenceManagerImp sm, FieldMetaData fmd) {
169: boolean keyIsRef = fmd.isMapKeyRef();
170: boolean valueIsRef = fmd.isMapValueRef();
171: final Set entrySet = map.entrySet();
172: for (Iterator iterator = entrySet.iterator(); iterator
173: .hasNext();) {
174: Map.Entry entry = (Map.Entry) iterator.next();
175: if (keyIsRef)
176: sm.retrieveImp(entry.getKey());
177: if (valueIsRef)
178: sm.retrieveImp(entry.getValue());
179: }
180: }
181:
182: }
|