001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.kernel;
020:
021: import java.util.BitSet;
022: import java.util.Collection;
023:
024: import org.apache.openjpa.lib.rop.ResultObjectProvider;
025: import org.apache.openjpa.lib.util.Closeable;
026: import org.apache.openjpa.meta.ClassMetaData;
027: import org.apache.openjpa.meta.FieldMetaData;
028: import org.apache.openjpa.meta.ValueStrategies;
029:
030: /**
031: * Interface to be implemented by data store mechanisms to interact with
032: * this runtime.
033: *
034: * @author Abe White
035: */
036: public interface StoreManager extends Closeable {
037:
038: public static final int VERSION_LATER = 1;
039: public static final int VERSION_EARLIER = 2;
040: public static final int VERSION_SAME = 3;
041: public static final int VERSION_DIFFERENT = 4;
042:
043: public static final int FORCE_LOAD_NONE = 0;
044: public static final int FORCE_LOAD_DFG = 1;
045: public static final int FORCE_LOAD_REFRESH = 3;
046: public static final int FORCE_LOAD_ALL = 2;
047:
048: /**
049: * Set a reference to the corresponding context. This method
050: * will be called before the store manager is used. The store manager
051: * is responsible for pulling any necessary configuration data from the
052: * context, including the transaction mode and connection retain mode.
053: */
054: public void setContext(StoreContext ctx);
055:
056: /**
057: * Notification that an optimistic transaction has started. This method
058: * does not replace the {@link #begin} method, which will still be called
059: * when a true data store transaction should begin.
060: */
061: public void beginOptimistic();
062:
063: /**
064: * Notification that an optimistic transaction was rolled back before
065: * a data store transaction ever began.
066: */
067: public void rollbackOptimistic();
068:
069: /**
070: * Begin a data store transaction. After this method is called,
071: * it is assumed that all further operations are operating in a single
072: * transaction that can be committed or rolled back. If optimistic
073: * transactions are in use, this method will only be called when the
074: * system requires a transactionally consistent connection due to a
075: * user request to flush or commit the transaction. In this case, it
076: * is possible that the optimistic transaction does not have the latest
077: * versions of all instances (i.e. another transaction has modified the
078: * same instances and committed since the optimistic transaction started).
079: * On commit, an exception must be thrown on any attempt to overwrite
080: * data for an instance with an older version.
081: *
082: * @since 0.2.5
083: */
084: public void begin();
085:
086: /**
087: * Commit the current data store transaction.
088: */
089: public void commit();
090:
091: /**
092: * Rollback the current data store transaction.
093: */
094: public void rollback();
095:
096: /**
097: * Verify that the given instance exists in the data store; return false
098: * if it does not.
099: */
100: public boolean exists(OpenJPAStateManager sm, Object edata);
101:
102: /**
103: * Update the version information in the given state manager to the
104: * version stored in the data store.
105: *
106: * @param sm the instance to check
107: * @param edata the current execution data, or null if not
108: * given to the calling method of the context
109: * @return true if the instance still exists in the
110: * datastore and is up-to-date, false otherwise
111: */
112: public boolean syncVersion(OpenJPAStateManager sm, Object edata);
113:
114: /**
115: * Initialize the given state manager. The object id of the
116: * state manager will be set, and the state manager's metadata be set to
117: * the class of the instance to load, or possibly one of its superclasses.
118: * Initialization involves first calling the
119: * {@link OpenJPAStateManager#initialize} method with
120: * a new instance of the correct type constructed with the
121: * {@link org.apache.openjpa.enhance.PCRegistry#newInstance(Class,
122: * org.apache.openjpa.enhance.StateManager, boolean)} method
123: * (this will reset the state manager's metadata if the actual type was a
124: * subclass). After instance initialization, load any the fields for the
125: * given fetch configuration that can be efficiently retrieved. If any of
126: * the configured fields are not loaded in this method, they will be
127: * loaded with a subsequent call to {@link #load}. If this method is
128: * called during a data store transaction, the instance's database record
129: * should be locked. Version information can be loaded if desired through
130: * the {@link OpenJPAStateManager#setVersion} method.
131: *
132: * @param sm the instance to initialize
133: * @param state the lifecycle state to initialize the state manager with
134: * @param fetch configuration for how to load the instance
135: * @param edata the current execution data, or null if not
136: * given to the calling method of the broker
137: * @return true if the matching instance exists in the data
138: * store, false otherwise
139: */
140: public boolean initialize(OpenJPAStateManager sm, PCState state,
141: FetchConfiguration fetch, Object edata);
142:
143: /**
144: * Load the given state manager.
145: * Note that any collection or map types loaded into the state manager
146: * will be proxied with the correct type; therefore the store manager
147: * does not have to load the same concrete collection/map types as the
148: * instance declares. However, array types must be consistent with the
149: * array type stored by the persistence capable instance. If this method
150: * is called during a data store transaction, the instance should be
151: * locked. If the given state manager does not have its version set
152: * already, version information can be loaded if desired through the
153: * {@link OpenJPAStateManager#setVersion} method.
154: *
155: * @param sm the instance to load
156: * @param fields set of fields to load; all field indexes in this
157: * set must be loaded; this set is mutable
158: * @param fetch the fetch configuration to use when loading
159: * related objects
160: * @param lockLevel attempt to load simple fields at this lock level;
161: * relations should be loaded at the read lock level
162: * of the fetch configuration
163: * @param edata the current execution data, or null if not
164: * given to the calling method of the broker
165: * @return false if the object no longer exists in the
166: * database, true otherwise
167: */
168: public boolean load(OpenJPAStateManager sm, BitSet fields,
169: FetchConfiguration fetch, int lockLevel, Object edata);
170:
171: /**
172: * Initialize, load, or validate the existance of all of the given
173: * objects. This method is called from various broker methods that act
174: * on multiple objects, such as {@link StoreContext#retrieveAll}. It gives
175: * the store manager an opportunity to efficiently batch-load data for
176: * several objects. Each of the given state managers will be in one of
177: * three states, each requiring a different action:
178: * <ul>
179: * <li><code>stateManager.getO () == null</code>: An
180: * uninitialized state manager. Perform the same actions as in
181: * {@link #initialize}.
182: * <li><code>load != FORCE_LOAD_NONE || stateManager.getPCState ()
183: * == PCState.HOLLOW</code>: A hollow state manager, or one whose
184: * fields must be loaded because this is a refresh or retrieve action.
185: * Peform the same actions as in {@link #load}, choosing the fields
186: * to load based on the fetch configuration, or loading all fields
187: * if <code>load == FORCE_LOAD_ALL</code>. Any required fields left
188: * unloaded will cause a subsequent invocation of {@link #load} on
189: * the individual object in question.</li>
190: * <li><code>load == FORCE_LOAD_NONE &&
191: * stateManager.getPCState () != PCState.HOLLOW</code>: A non-hollow
192: * state manager. Perform the same actions as in {@link #exists},
193: * and load additional state if desired. Non-hollow objects will only
194: * be included outside of refresh invocations if a user calls
195: * <code>findAll</code> with the <code>validate</code>
196: * parameter set to <code>true</code>.</li>
197: * </ul>
198: * Store managers that cannot efficiently batch load can simply test
199: * for these conditions and delegate to the proper methods.
200: *
201: * @param sms the state manager instances to load
202: * @param state the lifecycle state to initialize uninitialized
203: * state managers with; may be null if no uninitialized
204: * instances are included in <code>sms</code>
205: * @param load one of the FORCE_LOAD_* constants describing the
206: * fields to force-load if this is a refresh or retrieve action
207: * @param fetch the current fetch configuration to use when loading
208: * related objects
209: * @param edata the current execution data, or null if not
210: * given to the calling method of the broker
211: * @return a collection of the state manager identities for
212: * which no data store record exists
213: * @see org.apache.openjpa.util.ImplHelper#loadAll
214: */
215: public Collection loadAll(Collection sms, PCState state, int load,
216: FetchConfiguration fetch, Object edata);
217:
218: /**
219: * Notification that the given state manager is about to change its
220: * lifecycle state. The store manager is not required to do anything in
221: * this method, but some back ends may need to.
222: *
223: * @since 0.3.0
224: */
225: public void beforeStateChange(OpenJPAStateManager sm,
226: PCState fromState, PCState toState);
227:
228: /**
229: * Flush the given state manager collection to the datastore, returning
230: * a collection of exceptions encountered during flushing.
231: * The given collection may include states that do not require data
232: * store action, such as persistent-clean instances or persistent-dirty
233: * instances that have not been modified since they were last flushed.
234: * For datastore updates and inserts, the dirty, non-flushed fields of
235: * each state should be flushed. New instances without an assigned object
236: * id should be given one via {@link OpenJPAStateManager#setObjectId}. New
237: * instances with value-strategy fields that have not been assigned yet
238: * should have their fields set. Datastore version information should be
239: * updated during flush, and the state manager's version indicator
240: * updated through the {@link OpenJPAStateManager#setNextVersion} method.
241: * The current version will roll over to this next version upon successful
242: * commit.
243: *
244: * @see org.apache.openjpa.util.ApplicationIds#assign()
245: */
246: public Collection flush(Collection sms);
247:
248: /**
249: * Assign an object id to the given new instance. Return false if the
250: * instance cannot be assigned an identity because a flush is required
251: * (for example, the identity is determined by the datastore on insert).
252: * For application identity instances, the assigned object id should be
253: * based on field state. The implementation is responsible for using the
254: * proper value strategy according to the instance metadata. This method
255: * is called the first time a user requests the oid of a new instance
256: * before flush.
257: *
258: * @param preFlush whether this assignment is being requested by the
259: * system as part of pre-flush activities, and can
260: * be ignored if it is more efficient to assign within {@link #flush}
261: * @see org.apache.openjpa.util.ImplHelper#generateFieldValue
262: * @see org.apache.openjpa.util.ImplHelper#generateIdentityValue
263: * @see org.apache.openjpa.util.ApplicationIds#assign()
264: * @since 0.3.3
265: */
266: public boolean assignObjectId(OpenJPAStateManager sm,
267: boolean preFlush);
268:
269: /**
270: * Assign a value to the given field. Return false if the value cannot
271: * be assigned because a flush is required (for example, the field value
272: * is determined by the datastore on insert). This method is called the
273: * first time a user requests the value of a field with a value-strategy
274: * on a new instance before flush.
275: *
276: * @param preFlush whether this assignment is being requested by the
277: * system as part of pre-flush activities, and can
278: * be ignored if it is more efficient to assign within {@link #flush}
279: * @see org.apache.openjpa.util.ImplHelper#generateFieldValue
280: * @since 0.4.0
281: */
282: public boolean assignField(OpenJPAStateManager sm, int field,
283: boolean preFlush);
284:
285: /**
286: * Return the persistent class for the given data store identity value.
287: * If the given value is not a datastore identity object, return null.
288: *
289: * @since 0.3.0
290: */
291: public Class getManagedType(Object oid);
292:
293: /**
294: * Return the class used by this StoreManager for datastore identity
295: * values. The given metadata may be null, in which case the return
296: * value should the common datastore identity class for all classes, or
297: * null if this store manager does not use a common identity class.
298: */
299: public Class getDataStoreIdType(ClassMetaData meta);
300:
301: /**
302: * Copy the given object id value. Use the described type of the given
303: * metadata, which may be a subclass of the given oid's described type.
304: */
305: public Object copyDataStoreId(Object oid, ClassMetaData meta);
306:
307: /**
308: * Create a new unique datastore identity for the given type from
309: * the given oid value (presumably pk, stringified oid, or oid instance).
310: */
311: public Object newDataStoreId(Object oidVal, ClassMetaData meta);
312:
313: /**
314: * Return a connection to the data store suitable for client use. If
315: * this method is called during a data store transaction, thie connection
316: * must be transactional. If no connection is in use, this method should
317: * create one to return.
318: */
319: public Object getClientConnection();
320:
321: /**
322: * Instruct the store to retain a connection for continued use. This
323: * will be invoked automatically based on the user's configured connection
324: * retain mode.
325: */
326: public void retainConnection();
327:
328: /**
329: * Instruct the store to release a retained connection. This
330: * will be invoked automatically based on the user's configured connection
331: * retain mode.
332: */
333: public void releaseConnection();
334:
335: /**
336: * Cancel all pending data store statements.
337: *
338: * @return true if any statements cancelled, false otherwise
339: * @since 0.3.1
340: */
341: public boolean cancelAll();
342:
343: /**
344: * Return a provider for all instances of the given candidate class,
345: * optionally including subclasses. The given candidate may be an
346: * unmapped type with mapped subclasses. If the provider is iterated
347: * within a data store transaction, returned instances should be locked.
348: */
349: public ResultObjectProvider executeExtent(ClassMetaData meta,
350: boolean subclasses, FetchConfiguration fetch);
351:
352: /**
353: * Return a query implementation suitable for this store. If the query
354: * is iterated within a data store transaction, returned instances should
355: * be locked. Return null if this store does not support native execution
356: * of the given language. OpenJPA can execute JPQL in memory even without
357: * back end support.
358: *
359: * @param language the query language
360: */
361: public StoreQuery newQuery(String language);
362:
363: /**
364: * Return a fetch configuration suitable for this runtime. Typically
365: * will be or extend <code>FetchConfigurationImpl</code>.
366: */
367: public FetchConfiguration newFetchConfiguration();
368:
369: /**
370: * Compare the two version objects.
371: *
372: * @param state the state manager for the object
373: * @param v1 the first version object to compare
374: * @param v2 the second version object to compare
375: * @return <ul>
376: * <li>{@link #VERSION_LATER} if <code>v1</code>
377: * is later than <code>v2</code></li>
378: * <li>{@link #VERSION_EARLIER} if <code>v1</code>
379: * is earlier than <code>v2</code></li>
380: * <li>{@link #VERSION_SAME} if <code>v1</code>
381: * is the same as <code>v2</code></li>
382: * <li>{@link #VERSION_DIFFERENT} if <code>v1</code>
383: * is different from <code>v2</code>, but the time
384: * difference of the versions cannot be determined</li>
385: * </ul>
386: */
387: public int compareVersion(OpenJPAStateManager state, Object v1,
388: Object v2);
389:
390: /**
391: * Return a sequence that generates datastore identity values for the
392: * given class. This method will only be called when the identity strategy
393: * for the class is one of:
394: * <ul>
395: * <li>{@link ValueStrategies#NATIVE}</li>
396: * <li>{@link ValueStrategies#AUTOASSIGN}</li>
397: * <li>{@link ValueStrategies#INCREMENT}</li>
398: * </ul>
399: * If the identity strategy cannot be represented as a sequence, return
400: * null.
401: *
402: * @since 0.4.0
403: */
404: public Seq getDataStoreIdSequence(ClassMetaData forClass);
405:
406: /**
407: * Return a sequence that generates values for the given field. This
408: * method will only be called when the value strategy for the field
409: * is one of:
410: * <ul>
411: * <li>{@link ValueStrategies#NATIVE}</li>
412: * <li>{@link ValueStrategies#AUTOASSIGN}</li>
413: * <li>{@link ValueStrategies#INCREMENT}</li>
414: * </ul> If the value strategy cannot be represented as a sequence, return
415: * null.
416: *
417: * @since 0.4.0
418: */
419: public Seq getValueSequence(FieldMetaData forField);
420:
421: /**
422: * Free any resources this store manager is using.
423: *
424: * @since 0.2.5
425: */
426: public void close();
427: }
|