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:
016: Contributors:
017: ...
018: **********************************************************************/package org.jpox.store.fieldmanager;
019:
020: import java.util.Collection;
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import org.jpox.ObjectManagerHelper;
026: import org.jpox.StateManager;
027: import org.jpox.FetchPlan.FetchPlanForClass;
028: import org.jpox.api.ApiAdapter;
029: import org.jpox.sco.SCO;
030: import org.jpox.state.FetchPlanState;
031:
032: /**
033: * Field Manager to handle the making transient of fields.
034: *
035: * @version $Revision: 1.7 $
036: */
037: public class MakeTransientFieldManager extends
038: AbstractFetchFieldManager {
039: /**
040: * Constructor for a field manager for make transient process.
041: * @param sm the StateManager of the instance being detached. An instance in Persistent or Transactional state
042: * @param secondClassMutableFields The second class mutable fields for the class of this object
043: * @param fpClass Fetch Plan for the class of this instance
044: * @param state State object to hold any pertinent controls for the fetchplan process
045: */
046: public MakeTransientFieldManager(StateManager sm,
047: boolean[] secondClassMutableFields,
048: FetchPlanForClass fpClass, FetchPlanState state) {
049: super (sm, secondClassMutableFields, fpClass, state);
050: }
051:
052: /**
053: * Utility method to process the passed persistable object.
054: * @param pc The PC object
055: */
056: protected void processPersistable(Object pc) {
057: if (sm.getObjectManager().getApiAdapter().isPersistent(pc)) {
058: // Make transient if still persistent
059: ObjectManagerHelper.getObjectManager(pc)
060: .makeObjectTransient(pc, state);
061: }
062: }
063:
064: /**
065: * Method to fetch an object field whether it is SCO collection, PC, or whatever for the fetchplan process.
066: * @param fieldNumber Number of the field
067: * @return The object
068: */
069: protected Object internalFetchObjectField(int fieldNumber) {
070: SingleValueFieldManager sfv = new SingleValueFieldManager();
071: sm.provideFields(new int[] { fieldNumber }, sfv);
072: Object value = sfv.fetchObjectField(fieldNumber);
073: ApiAdapter api = sm.getObjectManager().getApiAdapter();
074:
075: if (value != null) {
076: if (api.isPersistable(value)) {
077: // Process PC fields
078: processPersistable(value);
079: } else if (value instanceof Collection) {
080: // Process all elements of the Collection that are PC
081: if (!(value instanceof SCO)) {
082: // Replace with SCO
083: value = sm.wrapSCOField(fieldNumber, value, false,
084: false, true);
085: }
086: SCO sco = (SCO) value;
087:
088: Collection coll = (Collection) value;
089: Iterator iter = coll.iterator();
090: while (iter.hasNext()) {
091: Object element = iter.next();
092: if (api.isPersistable(element)) {
093: processPersistable(element);
094: }
095: }
096: sco.unsetOwner();
097: } else if (value instanceof Map) {
098: // Process all keys, values of the Map that are PC
099: if (!(value instanceof SCO)) {
100: // Replace with SCO
101: value = sm.wrapSCOField(fieldNumber, value, false,
102: false, true);
103: }
104: SCO sco = (SCO) value;
105:
106: Map map = (Map) value;
107:
108: // Process any keys that are PersistenceCapable
109: Set keys = map.keySet();
110: Iterator iter = keys.iterator();
111: while (iter.hasNext()) {
112: Object mapKey = iter.next();
113: if (api.isPersistable(mapKey)) {
114: processPersistable(mapKey);
115: }
116: }
117:
118: // Process any values that are PersistenceCapable
119: Collection values = map.values();
120: iter = values.iterator();
121: while (iter.hasNext()) {
122: Object mapValue = iter.next();
123: if (api.isPersistable(mapValue)) {
124: processPersistable(mapValue);
125: }
126: }
127:
128: sco.unsetOwner();
129: } else if (value instanceof Object[]) {
130: Object[] array = (Object[]) value;
131: for (int i = 0; i < array.length; i++) {
132: Object element = array[i];
133: if (api.isPersistable(element)) {
134: processPersistable(element);
135: }
136: }
137: } else if (value instanceof SCO) {
138: // Other SCO field, so unset its owner
139: SCO sco = (SCO) value;
140: sco.unsetOwner();
141: } else {
142: // Primitive, or primitive array, or some unsupported container type
143: }
144: }
145:
146: return value;
147: }
148:
149: /**
150: * Method to throw and EndOfFetchPlanGraphException since we're at the end of a branch in the tree.
151: * @param fieldNumber Number of the field
152: * @return Object to return
153: */
154: protected Object endOfGraphOperation(int fieldNumber) {
155: SingleValueFieldManager sfv = new SingleValueFieldManager();
156: sm.provideFields(new int[] { fieldNumber }, sfv);
157: Object value = sfv.fetchObjectField(fieldNumber);
158:
159: if (value != null && secondClassMutableFields[fieldNumber]) {
160: SCO sco;
161: if (value instanceof SCO) {
162: // SCO field so unset its owner
163: sco = (SCO) value;
164: sco.unsetOwner();
165: }
166: }
167:
168: return value;
169: }
170: }
|