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 org.jpox.StateManager;
020: import org.jpox.FetchPlan.FetchPlanForClass;
021: import org.jpox.metadata.AbstractMemberMetaData;
022: import org.jpox.metadata.MetaDataUtils;
023: import org.jpox.state.FetchPlanState;
024:
025: /**
026: * Base field manager for handling the fetching of fields.
027: * Supports a FetchPlan to navigate down an object graph.
028: * This is extended by specific managers for the detachment and makeTransient processes.
029: *
030: * @version $Revision: 1.4 $
031: **/
032: public abstract class AbstractFetchFieldManager extends
033: AbstractFieldManager {
034: /** StateManager of the instance being fetched (detached or made transient). **/
035: protected final StateManager sm;
036:
037: /** Second class mutable fields for the class of this object. */
038: protected final boolean[] secondClassMutableFields;
039:
040: /** Fetch Plan for the class of this object. */
041: protected FetchPlanForClass fpClass;
042:
043: /** State for the fetch process. */
044: protected final FetchPlanState state;
045:
046: /**
047: * Exception thrown when we reach the end of the fetch depth in a branch of the object graph
048: * @version $Revision: 1.4 $
049: */
050: public static class EndOfFetchPlanGraphException extends
051: RuntimeException {
052: }
053:
054: /**
055: * Constructor for a field manager for fetch plan processing.
056: * @param sm the StateManager of the instance being processed.
057: * @param secondClassMutableFields
058: * @param fpClass Fetch Plan for the class of this instance
059: * @param state Object containing the state of the fetch process
060: */
061: public AbstractFetchFieldManager(StateManager sm,
062: boolean[] secondClassMutableFields,
063: FetchPlanForClass fpClass, FetchPlanState state) {
064: this .sm = sm;
065: this .secondClassMutableFields = secondClassMutableFields;
066: this .fpClass = fpClass;
067: this .state = state;
068: }
069:
070: /**
071: * Method to fetch an object field whether it is SCO collection, PC, or whatever.
072: * @param fieldNumber Number of the field
073: * @return The object
074: */
075: public Object fetchObjectField(int fieldNumber)
076: throws EndOfFetchPlanGraphException {
077: AbstractMemberMetaData fmd = fpClass.getAbstractClassMetaData()
078: .getMetaDataForManagedMemberAtAbsolutePosition(
079: fieldNumber);
080: final boolean requiresFCOFetching = MetaDataUtils.getInstance()
081: .storesFCO(fmd,
082: sm.getObjectManager().getClassLoaderResolver());
083: final int maxFetchDepth = fpClass.getFetchPlan()
084: .getMaxFetchDepth();
085: final int currentFetchDepth = state.getCurrentFetchDepth();
086:
087: // Retrieve the max recurse depth for this field type
088:
089: if (requiresFCOFetching) {
090: if (currentFetchDepth > 0 && maxFetchDepth > 0
091: && currentFetchDepth == maxFetchDepth) {
092: // Reached the overall max fetch depth so jump out
093: return endOfGraphOperation(fieldNumber);
094: }
095:
096: final int maxRecursiveDepth = fpClass
097: .getMaxRecursionDepthForFieldInCurrentFetchPlan(fieldNumber);
098: if (maxRecursiveDepth > 0) {
099: // We have a limit on recursing so check if the recursive depth is reached for this type
100: if (state.getObjectDepthForType(fmd.getFullFieldName()) >= maxRecursiveDepth) {
101: return endOfGraphOperation(fieldNumber);
102: }
103: }
104:
105: // Add this field to the object graph, and set the current depth
106: state.addFieldName(fmd.getFullFieldName());
107:
108: // Process the field
109: Object result = internalFetchObjectField(fieldNumber);
110:
111: // Returned from a search down this branch so remove the field and update the current depth
112: state.removeLatestFieldName();
113:
114: return result;
115: } else {
116: // Perform the fetch of this field
117: return internalFetchObjectField(fieldNumber);
118: }
119: }
120:
121: /**
122: * Method to fetch an object field whether it is SCO collection, PC, or whatever.
123: * @param fieldNumber Number of the field
124: * @return The object
125: */
126: protected abstract Object internalFetchObjectField(int fieldNumber);
127:
128: /**
129: * Method called when an end of graph is encountered.
130: * @param fieldNumber Number of the field
131: * @return Object to return
132: */
133: protected abstract Object endOfGraphOperation(int fieldNumber);
134:
135: /* (non-Javadoc)
136: * @see FieldSupplier#fetchBooleanField(int)
137: */
138: public boolean fetchBooleanField(int fieldNumber) {
139: SingleValueFieldManager sfv = new SingleValueFieldManager();
140: sm.provideFields(new int[] { fieldNumber }, sfv);
141: return sfv.fetchBooleanField(fieldNumber);
142: }
143:
144: /* (non-Javadoc)
145: * @see FieldSupplier#fetchByteField(int)
146: */
147: public byte fetchByteField(int fieldNumber) {
148: SingleValueFieldManager sfv = new SingleValueFieldManager();
149: sm.provideFields(new int[] { fieldNumber }, sfv);
150: return sfv.fetchByteField(fieldNumber);
151: }
152:
153: /* (non-Javadoc)
154: * @see FieldSupplier#fetchCharField(int)
155: */
156: public char fetchCharField(int fieldNumber) {
157: SingleValueFieldManager sfv = new SingleValueFieldManager();
158: sm.provideFields(new int[] { fieldNumber }, sfv);
159: return sfv.fetchCharField(fieldNumber);
160: }
161:
162: /* (non-Javadoc)
163: * @see FieldSupplier#fetchDoubleField(int)
164: */
165: public double fetchDoubleField(int fieldNumber) {
166: SingleValueFieldManager sfv = new SingleValueFieldManager();
167: sm.provideFields(new int[] { fieldNumber }, sfv);
168: return sfv.fetchDoubleField(fieldNumber);
169: }
170:
171: /* (non-Javadoc)
172: * @see FieldSupplier#fetchFloatField(int)
173: */
174: public float fetchFloatField(int fieldNumber) {
175: SingleValueFieldManager sfv = new SingleValueFieldManager();
176: sm.provideFields(new int[] { fieldNumber }, sfv);
177: return sfv.fetchFloatField(fieldNumber);
178: }
179:
180: /* (non-Javadoc)
181: * @see FieldSupplier#fetchIntField(int)
182: */
183: public int fetchIntField(int fieldNumber) {
184: SingleValueFieldManager sfv = new SingleValueFieldManager();
185: sm.provideFields(new int[] { fieldNumber }, sfv);
186: return sfv.fetchIntField(fieldNumber);
187: }
188:
189: /* (non-Javadoc)
190: * @see FieldSupplier#fetchLongField(int)
191: */
192: public long fetchLongField(int fieldNumber) {
193: SingleValueFieldManager sfv = new SingleValueFieldManager();
194: sm.provideFields(new int[] { fieldNumber }, sfv);
195: return sfv.fetchLongField(fieldNumber);
196: }
197:
198: /* (non-Javadoc)
199: * @see FieldSupplier#fetchShortField(int)
200: */
201: public short fetchShortField(int fieldNumber) {
202: SingleValueFieldManager sfv = new SingleValueFieldManager();
203: sm.provideFields(new int[] { fieldNumber }, sfv);
204: return sfv.fetchShortField(fieldNumber);
205: }
206:
207: /* (non-Javadoc)
208: * @see FieldSupplier#fetchStringField(int)
209: */
210: public String fetchStringField(int fieldNumber) {
211: SingleValueFieldManager sfv = new SingleValueFieldManager();
212: sm.provideFields(new int[] { fieldNumber }, sfv);
213: return sfv.fetchStringField(fieldNumber);
214: }
215: }
|