fullRuntime/src/sc/db/DBObject.java
public PropUpdate dbSetProp(String propertyName, Object propertyValue, Object oldValue)  {
      restartIfNecessary();

      if (replacedBy != null)
         return ((DBObject) replacedBy.getDBObject()).dbSetProp(propertyName, propertyValue, oldValue);

      if ((flags & (REMOVED | STOPPED)) != 0)
         throw new IllegalStateException("setProperty on: " + getStateString() + " dbObject: " + this);

      boolean changed = false;
      if (propertyValue != oldValue) {
         changed = true;
         if (oldValue instanceof IChangeable) {
            if (changeableListeners != null) {
               DBChangeableListener oldListener = changeableListeners.remove(propertyName);
               if (oldListener != null)
                  Bind.removeListener(oldValue, null, oldListener, IListener.VALUE_INVALIDATED);
            }
         }
         if (propertyValue instanceof IChangeable) {
            if (changeableListeners == null)
               changeableListeners = new TreeMap<String,DBChangeableListener>();
            DBChangeableListener newListener = new DBChangeableListener(this, propertyName, (IChangeable) propertyValue);
            Bind.addListener(propertyValue, null, newListener, IListener.VALUE_INVALIDATED);
            changeableListeners.put(propertyName, newListener);
         }
      }
      else if (propertyValue instanceof IChangeable)
         changed = true;

      if ((flags & TRANSIENT) != 0)
         return null;
      DBTransaction curr = DBTransaction.getOrCreate();
      // When we are applying this transaction, we need to return null here to allow the setX call to update the cached value
      if (curr.commitInProgress) {
         return null;
      }
      SelectGroupQuery selectQuery = dbTypeDesc.getFetchQueryForProperty(propertyName);
      if (selectQuery == null)
         throw new IllegalArgumentException("Missing propQueries entry for property: " + propertyName);
      int lockCt = selectQuery.queryNumber;
      long fetchedBit = FETCHED << (lockCt * 2);

      // For the case where we are populating a newly selected instance, mark the property as selected and update the field
      if (curr.applyingDBChanges) {
         if ((fstate & fetchedBit) != 0)
            return null;

         // This is by default true but set to false when updating referenced values, since we might be setting the reverse
         // property in an object but do not want to mark it's state as fetched - just the parent object's state.
         if (curr.updateSelectState) {
            synchronized (this) {
               fstate |= fetchedBit;
            }
         }
         return null;
      }

      // Setting a property that has not been selected from the DB - possibly being selected from a query
      if ((fstate & fetchedBit) == 0)
         return null;
      //if (((fstate >> (lockCt * 2)) & FETCHED) == 0)
      //   return null;

      // If we are setting the value to the same value that's in the cache don't create a new DB update. A common case is
      // setting a property that's been fetched to null that's already null.
      // but for IChangeable, the value may have changed particularly if this called from DBChangeableListener
      PropUpdate pu = getPendingUpdate(curr, propertyName, changed, propertyValue);
      if (pu == null)
         return null;
      pu.value = propertyValue;

      // TODO: should we make this an option? If we don't; send this, reverse properties are not updated until after the
      // commit. We should at least be able to make those changes visible by the current thread before the commit and it
      // seems like code will behave better if it's notified sooner that a change is coming. If we notify other threads about a
      // change in progress it's not a problem - locking will protect it in some cases or if the other thread sees the old value
      // another change will be sent when we commit the property.
      Bind.sendChange(getInst(), propertyName, propertyValue);
      return pu;
   }
/**
    * Called to update the saved representation of the instance. Returns null to allow the assignment
    * in the field. If it returns non-null, the setX method will just return.
    * Note: In the current implementation if there's a change to the property made that's local to the thread, the
    * Bind.sendEvent call should be made by the framework since the setX method won't do anything else... for example,
    * in a reverse relationship change.
    */
Called to update the saved representation of the instance. Returns null to allow the assignment
in the field. If it returns non-null, the setX method will just return.
Note: In the current implementation if there's a change to the property made that's local to the thread, the
Bind.sendEvent call should be made by the framework since the setX method won't do anything else... for example,
in a reverse relationship change.
Called to update the saved representation of the instance . Returns null to allow the assignment in the field . If it returns non - null the setX method will just return . Note : In the current implementation if there ' s a change to the property made that ' s local to the thread the Bind . sendEvent call should be made by the framework since the setX method won ' t do anything else ... for example in a reverse relationship change .
public PropUpdate dbSetProp(String propertyName, Object propertyValue, Object oldValue)  {
      restartIfNecessary();
      if (replacedBy != null)
         return ((DBObject) replacedBy.getDBObject()).dbSetProp(propertyName, propertyValue, oldValue);
      if ((flags & (REMOVED | STOPPED)) != 0)
         throw new IllegalStateException("setProperty on: " + getStateString() + " dbObject: " + this);
      boolean changed = false;
      if (propertyValue != oldValue) {
         changed = true;
         if (oldValue instanceof IChangeable) {
            if (changeableListeners != null) {
               DBChangeableListener oldListener = changeableListeners.remove(propertyName);
               if (oldListener != null)
                  Bind.removeListener(oldValue, null, oldListener, IListener.VALUE_INVALIDATED);
            }
         }
         if (propertyValue instanceof IChangeable) {
            if (changeableListeners == null)
               changeableListeners = new TreeMap<String,DBChangeableListener>();
            DBChangeableListener newListener = new DBChangeableListener(this, propertyName, (IChangeable) propertyValue);
            Bind.addListener(propertyValue, null, newListener, IListener.VALUE_INVALIDATED);
            changeableListeners.put(propertyName, newListener);
         }
      }
      else if (propertyValue instanceof IChangeable)
         changed = true;
      if ((flags & TRANSIENT) != 0)
         return null;
      DBTransaction curr = DBTransaction.getOrCreate();
      if (curr.commitInProgress) {
         return null;
      }
      SelectGroupQuery selectQuery = dbTypeDesc.getFetchQueryForProperty(propertyName);
      if (selectQuery == null)
         throw new IllegalArgumentException("Missing propQueries entry for property: " + propertyName);
      int lockCt = selectQuery.queryNumber;
      long fetchedBit = FETCHED << (lockCt * 2);
      if (curr.applyingDBChanges) {
         if ((fstate & fetchedBit) != 0)
            return null;
         if (curr.updateSelectState) {
            synchronized (this) {
               fstate |= fetchedBit;
            }
         }
         return null;
      }
      if ((fstate & fetchedBit) == 0)
         return null;
      PropUpdate pu = getPendingUpdate(curr, propertyName, changed, propertyValue);
      if (pu == null)
         return null;
      pu.value = propertyValue;
      Bind.sendChange(getInst(), propertyName, propertyValue);
      return pu;
   }
public PropUpdate dbSetProp ( String propertyName , Object propertyValue , Object oldValue ) { restartIfNecessary ( ) ; if ( replacedBy != null ) return ( ( DBObject ) replacedBy . getDBObject ( ) ) . dbSetProp ( propertyName , propertyValue , oldValue ) ; if ( ( flags & ( REMOVED | STOPPED ) ) != 0 ) throw new IllegalStateException ( "setProperty on: " + getStateString ( ) + " dbObject: " + this ) ; boolean changed = false ; if ( propertyValue != oldValue ) { changed = true ; if ( oldValue instanceof IChangeable ) { if ( changeableListeners != null ) { DBChangeableListener oldListener = changeableListeners . remove ( propertyName ) ; if ( oldListener != null ) Bind . removeListener ( oldValue , null , oldListener , IListener . VALUE_INVALIDATED ) ; } } if ( propertyValue instanceof IChangeable ) { if ( changeableListeners == null ) changeableListeners = new TreeMap < String , DBChangeableListener > ( ) ; DBChangeableListener newListener = new DBChangeableListener ( this , propertyName , ( IChangeable ) propertyValue ) ; Bind . addListener ( propertyValue , null , newListener , IListener . VALUE_INVALIDATED ) ; changeableListeners . put ( propertyName , newListener ) ; } } else if ( propertyValue instanceof IChangeable ) changed = true ; if ( ( flags & TRANSIENT ) != 0 ) return null ; DBTransaction curr = DBTransaction . getOrCreate ( ) ; if ( curr . commitInProgress ) { return null ; } SelectGroupQuery selectQuery = dbTypeDesc . getFetchQueryForProperty ( propertyName ) ; if ( selectQuery == null ) throw new IllegalArgumentException ( "Missing propQueries entry for property: " + propertyName ) ; int lockCt = selectQuery . queryNumber ; long fetchedBit = FETCHED << ( lockCt * 2 ) ; if ( curr . applyingDBChanges ) { if ( ( fstate & fetchedBit ) != 0 ) return null ; if ( curr . updateSelectState ) { synchronized ( this ) { fstate |= fetchedBit ; } } return null ; } if ( ( fstate & fetchedBit ) == 0 ) return null ; PropUpdate pu = getPendingUpdate ( curr , propertyName , changed , propertyValue ) ; if ( pu == null ) return null ; pu . value = propertyValue ; Bind . sendChange ( getInst ( ) , propertyName , propertyValue ) ; return pu ; }
Called to update the saved representation of the instance.
Called to update the saved representation of the instance .
// When we are applying this transaction, we need to return null here to allow the setX call to update the cached value // For the case where we are populating a newly selected instance, mark the property as selected and update the field // This is by default true but set to false when updating referenced values, since we might be setting the reverse // property in an object but do not want to mark it's state as fetched - just the parent object's state. // Setting a property that has not been selected from the DB - possibly being selected from a query //if (((fstate >> (lockCt * 2)) & FETCHED) == 0) //   return null; // If we are setting the value to the same value that's in the cache don't create a new DB update. A common case is // setting a property that's been fetched to null that's already null. // but for IChangeable, the value may have changed particularly if this called from DBChangeableListener // TODO: should we make this an option? If we don't; send this, reverse properties are not updated until after the // commit. We should at least be able to make those changes visible by the current thread before the commit and it // seems like code will behave better if it's notified sooner that a change is coming. If we notify other threads about a // change in progress it's not a problem - locking will protect it in some cases or if the other thread sees the old value // another change will be sent when we commit the property.