/** * Determine whether this instance is a normal instance or is an in-memory "snapshot" instance associated * with a {@link SnapshotJTransaction}. * * <p> * Equvialent to {@code getTransaction().isSnapshot()}. * * @return true if instance is a snapshot instance */ default boolean isSnapshot() { return this.getTransaction().isSnapshot(); }
/** * Get the default {@link SnapshotJTransaction} associated with this instance. * * <p> * The default {@link SnapshotJTransaction} uses {@link ValidationMode#MANUAL}. * * <p> * This instance must not itself be a {@link SnapshotJTransaction}; use * {@link createSnapshotTransaction createSnapshotTransaction()} to create additional snapshot transactions. * * @return the associated snapshot transaction * @see JObject#copyOut JObject.copyOut() * @throws IllegalArgumentException if this instance is itself a {@link SnapshotJTransaction} */ public synchronized SnapshotJTransaction getSnapshotTransaction() { Preconditions.checkArgument(!this.isSnapshot(), "getSnapshotTransaction() invoked on a snapshot transaction; use createSnapshotTransaction() instead"); if (this.snapshotTransaction == null) this.snapshotTransaction = this.createSnapshotTransaction(ValidationMode.MANUAL); return this.snapshotTransaction; }
/** * Constructor. * * @throws IllegalArgumentException if any parameter is null */ JTransaction(Permazen jdb, Transaction tx, ValidationMode validationMode) { // Initialization Preconditions.checkArgument(jdb != null, "null jdb"); Preconditions.checkArgument(tx != null, "null tx"); Preconditions.checkArgument(validationMode != null, "null validationMode"); this.jdb = jdb; this.tx = tx; this.validationMode = validationMode; // Set back-reference tx.setUserObject(this); // Register listeners, or re-use our existing listener set final boolean automaticValidation = validationMode == ValidationMode.AUTOMATIC; final boolean isSnapshot = this.isSnapshot(); final int listenerSetIndex = (automaticValidation ? 2 : 0) + (isSnapshot ? 0 : 1); final Transaction.ListenerSet listenerSet = jdb.listenerSets[listenerSetIndex]; if (listenerSet == null) { JTransaction.registerListeners(jdb, tx, automaticValidation, isSnapshot); jdb.listenerSets[listenerSetIndex] = tx.snapshotListeners(); } else tx.setListeners(listenerSet); }
private void doOnCreate(ObjId id) { // Get JClass, if known final JClass<?> jclass; try { jclass = this.jdb.getJClass(id); } catch (TypeNotInSchemaVersionException e) { return; // object type does not exist in our schema } // Enqueue for revalidation if (this.validationMode == ValidationMode.AUTOMATIC && jclass.requiresDefaultValidation) this.revalidate(Collections.singleton(id)); // Notify @OnCreate methods Object jobj = null; for (OnCreateScanner<?>.MethodInfo info : jclass.onCreateMethods) { if (this.isSnapshot() && !info.getAnnotation().snapshotTransactions()) continue; if (jobj == null) jobj = this.get(id); Util.invoke(info.getMethod(), jobj); } }
private void doOnDelete(ObjId id) { // Get JClass, if known final JClass<?> jclass; try { jclass = this.jdb.getJClass(id); } catch (TypeNotInSchemaVersionException e) { return; // object type does not exist in our schema } // Notify @OnDelete methods Object jobj = null; for (OnDeleteScanner<?>.MethodInfo info : jclass.onDeleteMethods) { if (this.isSnapshot() && !info.getAnnotation().snapshotTransactions()) continue; if (jobj == null) jobj = this.get(id); Util.invoke(info.getMethod(), jobj); } }
if (!disableListenerNotifications && dest.isSnapshot() && jclass != null) disableListenerNotifications = !jclass.hasSnapshotCreateOrChangeMethods;