001: /**********************************************************************
002: Copyright (c) 2006 Andy Jefferson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: ...
017: **********************************************************************/package org.jpox.store.fieldmanager;
018:
019: import java.util.Collection;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.Set;
023:
024: import org.jpox.StateManager;
025: import org.jpox.api.ApiAdapter;
026: import org.jpox.metadata.AbstractMemberMetaData;
027: import org.jpox.sco.SCO;
028:
029: /**
030: * Field manager that perists all unpersisted PC objects referenced from the source object.
031: * If any collection/map fields are not currently using SCO wrappers they will be converted to do so.
032: * Effectively provides "persistence-by-reachability" (at persist).
033: *
034: * @version $Revision: 1.30 $
035: **/
036: public class PersistFieldManager extends AbstractFieldManager {
037: /** StateManager for the owning object. */
038: private final StateManager sm;
039:
040: /** Whether this manager will replace any SCO fields with SCO wrappers. */
041: private final boolean replaceSCOsWithWrappers;
042:
043: /**
044: * Constructor.
045: * @param sm The state manager for the object.
046: * @param replaceSCOsWithWrappers Whether to swap any SCO field objects for SCO wrappers
047: **/
048: public PersistFieldManager(StateManager sm,
049: boolean replaceSCOsWithWrappers) {
050: this .sm = sm;
051: this .replaceSCOsWithWrappers = replaceSCOsWithWrappers;
052: }
053:
054: /**
055: * Utility method to process the passed persistable object.
056: * @param pc The PC object
057: * @param ownerFieldNum Field number of owner where this is embedded
058: * @param objectType Type of object (see org.jpox.StateManager)
059: */
060: protected void processPersistable(Object pc, int ownerFieldNum,
061: int objectType) {
062: // TODO Consider adding more of the functionality in SCOUtils.validateObjectForWriting
063: ApiAdapter adapter = sm.getObjectManager().getApiAdapter();
064: if (!adapter.isPersistent(pc)
065: || (adapter.isPersistent(pc) && adapter.isDeleted(pc))) {
066: // Object is TRANSIENT/DETACHED and being persisted, or P_NEW_DELETED and being re-persisted
067: if (objectType != StateManager.PC) {
068: sm.getObjectManager().persistObjectInternal(pc, null,
069: sm, ownerFieldNum, objectType);
070: } else {
071: sm.getObjectManager().persistObjectInternal(pc, null,
072: null, -1, objectType);
073: }
074: }
075: }
076:
077: /**
078: * Method to store an object field.
079: * @param fieldNumber Number of the field (absolute)
080: * @param value Value of the field
081: */
082: public void storeObjectField(int fieldNumber, Object value) {
083: if (value != null) {
084: AbstractMemberMetaData fmd = sm.getClassMetaData()
085: .getMetaDataForManagedMemberAtAbsolutePosition(
086: fieldNumber);
087: boolean persistCascade = fmd.isCascadePersist();
088: ApiAdapter api = sm.getObjectManager().getApiAdapter();
089:
090: if (replaceSCOsWithWrappers) {
091: // Replace any SCO field that isnt already a wrapper, with its wrapper object
092: boolean[] secondClassMutableFieldFlags = sm
093: .getClassMetaData().getSCOMutableMemberFlags();
094: if (secondClassMutableFieldFlags[fieldNumber]
095: && !(value instanceof SCO)) {
096: // Replace the field with a SCO wrapper
097: sm.wrapSCOField(fieldNumber, value, false, true,
098: true);
099: }
100: }
101:
102: if (persistCascade) {
103: if (api.isPersistable(value)) {
104: // Process PC fields
105: if (fmd.isEmbedded() || fmd.isSerialized()) {
106: processPersistable(value, fieldNumber,
107: StateManager.EMBEDDED_PC);
108: } else {
109: processPersistable(value, -1, StateManager.PC);
110: }
111: } else if (value instanceof Collection) {
112: // Process all elements of the Collection that are PC
113: Collection coll = (Collection) value;
114: Iterator iter = coll.iterator();
115: while (iter.hasNext()) {
116: Object element = iter.next();
117: if (api.isPersistable(element)) {
118: if (fmd.getCollection().isEmbeddedElement()
119: || fmd.getCollection()
120: .isSerializedElement()) {
121: processPersistable(
122: element,
123: fieldNumber,
124: StateManager.EMBEDDED_COLLECTION_ELEMENT_PC);
125: } else {
126: processPersistable(element, -1,
127: StateManager.PC);
128: }
129: }
130: }
131: } else if (value instanceof Map) {
132: // Process all keys, values of the Map that are PC
133: Map map = (Map) value;
134:
135: // Process any keys that are PersistenceCapable
136: Set keys = map.keySet();
137: Iterator iter = keys.iterator();
138: while (iter.hasNext()) {
139: Object mapKey = iter.next();
140: if (api.isPersistable(mapKey)) {
141: if (fmd.getMap().isEmbeddedKey()
142: || fmd.getMap().isSerializedKey()) {
143: processPersistable(
144: mapKey,
145: fieldNumber,
146: StateManager.EMBEDDED_MAP_KEY_PC);
147: } else {
148: processPersistable(mapKey, -1,
149: StateManager.PC);
150: }
151: }
152: }
153:
154: // Process any values that are PersistenceCapable
155: Collection values = map.values();
156: iter = values.iterator();
157: while (iter.hasNext()) {
158: Object mapValue = iter.next();
159: if (api.isPersistable(mapValue)) {
160: if (fmd.getMap().isEmbeddedValue()
161: || fmd.getMap().isSerializedValue()) {
162: processPersistable(
163: mapValue,
164: fieldNumber,
165: StateManager.EMBEDDED_MAP_VALUE_PC);
166: } else {
167: processPersistable(mapValue, -1,
168: StateManager.PC);
169: }
170: }
171: }
172: } else if (value instanceof Object[]) {
173: Object[] array = (Object[]) value;
174:
175: for (int i = 0; i < array.length; i++) {
176: Object element = array[i];
177: if (api.isPersistable(element)) {
178: if (fmd.getArray().isEmbeddedElement()
179: || fmd.getArray()
180: .isSerializedElement()) {
181: // TODO This should be ARRAY_ELEMENT_PC but we havent got that yet
182: processPersistable(
183: element,
184: fieldNumber,
185: StateManager.EMBEDDED_COLLECTION_ELEMENT_PC);
186: } else {
187: processPersistable(element, -1,
188: StateManager.PC);
189: }
190: }
191: }
192: } else {
193: // Primitive, or primitive array, or some unsupported container type
194: }
195: }
196: }
197: }
198:
199: /**
200: * Method to store a boolean field.
201: * @param fieldNumber Number of the field (absolute)
202: * @param value Value of the field
203: */
204: public void storeBooleanField(int fieldNumber, boolean value) {
205: // Do nothing
206: }
207:
208: /**
209: * Method to store a byte field.
210: * @param fieldNumber Number of the field (absolute)
211: * @param value Value of the field
212: */
213: public void storeByteField(int fieldNumber, byte value) {
214: // Do nothing
215: }
216:
217: /**
218: * Method to store a char field.
219: * @param fieldNumber Number of the field (absolute)
220: * @param value Value of the field
221: */
222: public void storeCharField(int fieldNumber, char value) {
223: // Do nothing
224: }
225:
226: /**
227: * Method to store a double field.
228: * @param fieldNumber Number of the field (absolute)
229: * @param value Value of the field
230: */
231: public void storeDoubleField(int fieldNumber, double value) {
232: // Do nothing
233: }
234:
235: /**
236: * Method to store a float field.
237: * @param fieldNumber Number of the field (absolute)
238: * @param value Value of the field
239: */
240: public void storeFloatField(int fieldNumber, float value) {
241: // Do nothing
242: }
243:
244: /**
245: * Method to store an int field.
246: * @param fieldNumber Number of the field (absolute)
247: * @param value Value of the field
248: */
249: public void storeIntField(int fieldNumber, int value) {
250: // Do nothing
251: }
252:
253: /**
254: * Method to store a long field.
255: * @param fieldNumber Number of the field (absolute)
256: * @param value Value of the field
257: */
258: public void storeLongField(int fieldNumber, long value) {
259: // Do nothing
260: }
261:
262: /**
263: * Method to store a short field.
264: * @param fieldNumber Number of the field (absolute)
265: * @param value Value of the field
266: */
267: public void storeShortField(int fieldNumber, short value) {
268: // Do nothing
269: }
270:
271: /**
272: * Method to store a string field.
273: * @param fieldNumber Number of the field (absolute)
274: * @param value Value of the field
275: */
276: public void storeStringField(int fieldNumber, String value) {
277: // Do nothing
278: }
279: }
|