Skip to content

Package: UnitOfWork

UnitOfWork

Coverage

1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.sessions;
19:
20: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
21: import cz.cvut.kbss.jopa.model.EntityState;
22: import cz.cvut.kbss.jopa.model.LoadState;
23: import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
24: import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
25: import cz.cvut.kbss.jopa.model.query.criteria.CriteriaBuilder;
26: import cz.cvut.kbss.jopa.query.sparql.SparqlQueryFactory;
27: import cz.cvut.kbss.jopa.sessions.util.CloneRegistrationDescriptor;
28: import cz.cvut.kbss.jopa.sessions.util.LoadStateDescriptorRegistry;
29: import cz.cvut.kbss.jopa.utils.Wrapper;
30:
31: import java.lang.reflect.Field;
32: import java.net.URI;
33: import java.util.List;
34:
35: /**
36: * Represents a persistence context.
37: * <p>
38: * All interactions with objects managed in a persistence context are tracked by its corresponding UoW and on commit,
39: * the UoW propagates them into the repository.
40: */
41: public interface UnitOfWork extends ConfigurationHolder, MetamodelProvider, Wrapper {
42:
43: /**
44: * Clears this Unit of Work.
45: */
46: void clear();
47:
48: /**
49: * Notifies this Unit of Work that a transaction has begun.
50: */
51: void begin();
52:
53: /**
54: * Commit changes to the repository.
55: */
56: void commit();
57:
58: /**
59: * Rolls back changes done since last commit.
60: *
61: * @see #commit()
62: */
63: void rollback();
64:
65: /**
66: * Checks whether the specified entity is managed in this Unit of Work.
67: *
68: * @param entity Entity to check
69: * @return {@literal true} if entity is managed, {@literal false} otherwise
70: */
71: boolean contains(Object entity);
72:
73: /**
74: * Is this Unit of Work active?
75: *
76: * @return boolean
77: */
78: boolean isActive();
79:
80: /**
81: * Returns true if this {@code UnitOfWork} represents the persistence context of a currently running transaction.
82: *
83: * @return True if in an active transaction
84: */
85: boolean isInTransaction();
86:
87: /**
88: * Returns true if this Unit of Work is currently flushing changes to the repository.
89: *
90: * @return {@code true} if the UoW is flushing changes, {@code false} otherwise
91: */
92: boolean isFlushingChanges();
93:
94: /**
95: * Return true if the given entity is managed.
96: * <p>
97: * This means it is tracked by this persistence context either as a new object or an existing object loaded from the
98: * repository.
99: *
100: * @param entity Object to check
101: * @return {@code true} when the entity is managed, {@code false} otherwise
102: */
103: boolean isObjectManaged(Object entity);
104:
105: /**
106: * Checks whether the specified entity has been registered in this Unit of Work as a new object for persist.
107: *
108: * @param entity Object to check
109: * @return {@code true} when entity is managed and new, {@code false} otherwise
110: * @see #isObjectManaged(Object)
111: */
112: boolean isObjectNew(Object entity);
113:
114: /**
115: * Checks whether the specified repository context is consistent.
116: *
117: * @param context Context URI, {@code null} indicates the whole repository should be checked
118: * @return {@code true} if the context is consistent, {@code false} otherwise
119: * @throws OWLPersistenceException If an ontology access error occurs
120: */
121: boolean isConsistent(URI context);
122:
123: /**
124: * Loads value of the specified field for the specified entity.
125: * <p>
126: * The value is set on the entity.
127: *
128: * @param entity The entity to load field for
129: * @param fieldSpec Metamodel element representing the field to load
130: * @return The loaded field value
131: * @throws NullPointerException If {@code entity} or {@code field} is {@code null}
132: * @throws OWLPersistenceException If an error occurs, this may be e.g. that the field is not present on the entity,
133: * an ontology access error occurred etc.
134: */
135: <T> Object loadEntityField(T entity, FieldSpecification<? super T, ?> fieldSpec);
136:
137: /**
138: * Merges the state of the given entity into the current persistence context.
139: * <p>
140: * The {@code descriptor} argument specified the ontology contexts into which the detached entity and its fields
141: * belong and should be merged.
142: *
143: * @param entity entity instance
144: * @param descriptor Entity descriptor, specifies repository context
145: * @return the managed instance that the state was merged to
146: * @throws NullPointerException If {@code entity} or {@code repository} is {@code null}
147: */
148: <T> T mergeDetached(T entity, Descriptor descriptor);
149:
150: /**
151: * Retrieves object with the specified identifier.
152: * <p>
153: * The object as well as its fields are looked for in contexts specified by the descriptor. The result is then cast
154: * to the specified type.
155: *
156: * @param cls The type of the returned object
157: * @param identifier Instance identifier
158: * @param descriptor Entity descriptor
159: * @return The retrieved object or {@code null} if there is no object with the specified identifier in the specified
160: * repository
161: * @throws NullPointerException If {@code cls}, {@code identifier} or {@code repository} is {@code null}
162: * @throws OWLPersistenceException If an error occurs during object loading
163: */
164: <T> T readObject(Class<T> cls, Object identifier, Descriptor descriptor);
165:
166: /**
167: * Reads an object but does not register it with this persistence context.
168: * <p>
169: * Useful when the caller knows the object will be registered eventually by another routine.
170: *
171: * @param cls Expected result class
172: * @param identifier Object identifier
173: * @param descriptor Entity descriptor
174: * @return The retrieved object or {@code null} if there is no object with the specified identifier in the specified
175: * repository
176: */
177: <T> T readObjectWithoutRegistration(Class<T> cls, Object identifier, Descriptor descriptor);
178:
179: /**
180: * Retrieves a reference to an object with the specified identifier.
181: * <p>
182: * A reference is permitted to have its state fetched lazily.
183: *
184: * @param cls The type of the returned object
185: * @param identifier Instance identifier
186: * @param descriptor Entity descriptor
187: * @param <T> Entity type
188: * @return The retrieved object or {@code null} if none can be found
189: * @throws OWLPersistenceException If an error occurs during object loading
190: */
191: <T> T getReference(Class<T> cls, Object identifier, Descriptor descriptor);
192:
193: /**
194: * Register an existing object in this Unit of Work.
195: * <p>
196: * This is a shortcut for {@link #registerExistingObject(Object, CloneRegistrationDescriptor)}.
197: *
198: * @param object Object
199: * @param descriptor Entity descriptor identifying repository contexts
200: * @return Registered clone of the specified object
201: * @see #registerExistingObject(Object, CloneRegistrationDescriptor)
202: */
203: Object registerExistingObject(Object object, Descriptor descriptor);
204:
205: /**
206: * Register an existing object in this Unit of Work.
207: * <p>
208: * Creates a working clone of the specified object according to the configuration and puts the given object into
209: * this Unit of Work cache.
210: *
211: * @param object Object
212: * @param registrationDescriptor Configuration of the registration
213: * @return Registered clone of the specified object
214: */
215: Object registerExistingObject(Object object, CloneRegistrationDescriptor registrationDescriptor);
216:
217: /**
218: * Registers the specified new object in this Unit of Work.
219: * <p>
220: * The object will be persisted into the context specified by {@code descriptor}.
221: *
222: * @param object The object to register
223: * @param descriptor Entity descriptor
224: * @throws NullPointerException If {@code entity} or {@code context} is {@code null}
225: * @throws OWLPersistenceException If {@code context} is not a valid context URI or if an error during registration
226: * occurs
227: */
228: void registerNewObject(Object object, Descriptor descriptor);
229:
230: /**
231: * Remove the given object from the repository.
232: *
233: * @param object Object to remove
234: */
235: void removeObject(Object object);
236:
237: /**
238: * Restores the specified removed object.
239: * <p>
240: * This means it is reinstated as a managed entity and reinserted into the repository.
241: *
242: * @param entity The object to restore
243: */
244: void restoreRemovedObject(Object entity);
245:
246: /**
247: * Puts the specified object into the live object cache.
248: *
249: * @param identifier Object identifier
250: * @param entity Object to cache
251: * @param descriptor Descriptor of repository context
252: */
253: void putObjectIntoCache(Object identifier, Object entity, Descriptor descriptor);
254:
255: /**
256: * Removes the specified object from the live object cache.
257: * <p>
258: * This is particularly meant for merging deleted objects from transactions.
259: *
260: * @param object Object to remove from cache
261: * @param context Entity context URI
262: */
263: void removeObjectFromCache(Object object, URI context);
264:
265: /**
266: * Releases this unit of work.
267: * <p>
268: * Releasing an active Unit of Work with uncommitted changes causes all pending changes to be discarded.
269: */
270: void release();
271:
272: /**
273: * Refreshes the state of the specified object from the repository, overwriting any changes made to it.
274: *
275: * @param object The object to revert
276: * @param <T> Object type
277: * @throws IllegalArgumentException If the object is not managed
278: */
279: <T> void refreshObject(T object);
280:
281: /**
282: * Finds clone of the specified original object.
283: *
284: * @param original The original object whose clone we are looking for
285: * @return The clone or null, if there is none
286: */
287: Object getCloneForOriginal(Object original);
288:
289: /**
290: * Detaches the specified registered object from this Unit of Work.
291: *
292: * @param object Clone to detach
293: */
294: void unregisterObject(Object object);
295:
296: /**
297: * Writes any uncommitted changes into the ontology.
298: */
299: void writeUncommittedChanges();
300:
301: /**
302: * Gets repository contexts available to this session.
303: *
304: * @return Unmodifiable list of context URIs
305: */
306: List<URI> getContexts();
307:
308: /**
309: * Gets the registry of entity load state descriptors.
310: *
311: * @return {@code LoadStateDescriptorRegistry} for this persistence context
312: */
313: LoadStateDescriptorRegistry getLoadStateRegistry();
314:
315: /**
316: * Gets the load status of the specified attribute on the specified entity.
317: *
318: * @param entity Entity instance
319: * @param attributeName Attribute whose load status is to be determined
320: * @return Attribute load status
321: * @see cz.cvut.kbss.jopa.model.ProviderUtil#isLoadedWithoutReference(Object, String)
322: */
323: LoadState isLoaded(Object entity, String attributeName);
324:
325: /**
326: * Gets the load status of the specified entity.
327: *
328: * @param entity Entity whose load status is to be determined.
329: * @return Entity load status
330: * @see cz.cvut.kbss.jopa.model.ProviderUtil#isLoaded(Object)
331: */
332: LoadState isLoaded(Object entity);
333:
334: /**
335: * Gets the lifecycle state of the specified entity.
336: * <p>
337: * Note that since no repository is specified we can only determine if the entity is managed or removed. Therefore,
338: * if the case is different this method returns {@link EntityState#NOT_MANAGED}.
339: *
340: * @param entity Entity whose state to resolve
341: * @return Entity state
342: */
343: EntityState getState(Object entity);
344:
345: /**
346: * Gets the lifecycle state of the specified entity with respect to a repository context indicated by the specified
347: * descriptor.
348: *
349: * @param entity Entity whose state to resolve
350: * @param descriptor Descriptor of repository contexts
351: * @return Entity state
352: */
353: EntityState getState(Object entity, Descriptor descriptor);
354:
355: /**
356: * Checks whether the specified attribute value of the specified entity is inferred in the underlying repository.
357: * <p>
358: * Note that given the nature of the repository implementation, this method may return true if the corresponding
359: * statement is both inferred and asserted. Also note that this method will use the descriptor associated with the
360: * specified entity in this persistence context to resolve the repository context, but some underlying repositories
361: * do not store inferences in data contexts, so the attribute context may be ignored.
362: *
363: * @param entity Entity whose attribute to examine. Must be managed by this persistence context
364: * @param attribute Attribute whose value to examine
365: * @param value The value whose inference to examine
366: * @return {@code true} if the entity attribute value is inferred, {@code false} otherwise
367: */
368: <T>
369:
370: boolean isInferred(T entity, FieldSpecification<? super T, ?> attribute, Object value);
371:
372: /**
373: * Persists changed value of the specified field.
374: *
375: * @param entity Entity with changes (the clone)
376: * @param f The field whose value has changed
377: * @throws IllegalStateException If this UoW is not in transaction
378: * @see #attributeChanged(Object, FieldSpecification)
379: */
380: void attributeChanged(Object entity, Field f);
381:
382: /**
383: * Persists changed value of the specified field.
384: *
385: * @param entity Entity with changes (the clone)
386: * @param fieldSpec Metamodel element representing the attribute that changed
387: * @throws IllegalStateException If this UoW is not in transaction
388: */
389: void attributeChanged(Object entity, FieldSpecification<?, ?> fieldSpec);
390:
391: /**
392: * Creates an indirect collection that wraps the specified collection instance and propagates changes to this
393: * persistence context.
394: *
395: * @param collection Collection to be proxied
396: * @param owner Collection owner instance
397: * @param field Field filled with the collection
398: * @return Indirect collection
399: */
400: Object createIndirectCollection(Object collection, Object owner, Field field);
401:
402: /**
403: * Gets a {@link SparqlQueryFactory} instance associated with this persistence context.
404: *
405: * @return SPARQL query factory
406: */
407: SparqlQueryFactory sparqlQueryFactory();
408:
409: /**
410: * Gets a {@link CriteriaBuilder} instance for building Criteria API queries.
411: *
412: * @return Criteria query builder
413: */
414: CriteriaBuilder getCriteriaBuilder();
415: }