Coverage Report - net.wotonomy.test.DataObjectStore
 
Classes in this File Line Coverage Branch Coverage Complexity
DataObjectStore
0% 
0% 
2.267
 
 1  
 package net.wotonomy.test;
 2  
 
 3  
 import java.util.Iterator;
 4  
 import java.util.LinkedList;
 5  
 import java.util.List;
 6  
 import java.util.Map;
 7  
 
 8  
 import net.wotonomy.control.ArrayFault;
 9  
 import net.wotonomy.control.EOEditingContext;
 10  
 import net.wotonomy.control.EOFetchSpecification;
 11  
 import net.wotonomy.control.EOGlobalID;
 12  
 import net.wotonomy.control.EOObjectStore;
 13  
 import net.wotonomy.control.EOObserverCenter;
 14  
 import net.wotonomy.control.KeyValueCodingUtilities;
 15  
 import net.wotonomy.datastore.DataKey;
 16  
 import net.wotonomy.datastore.DataSoup;
 17  
 import net.wotonomy.datastore.DataView;
 18  
 import net.wotonomy.datastore.XMLFileSoup;
 19  
 import net.wotonomy.foundation.NSArray;
 20  
 import net.wotonomy.foundation.NSMutableArray;
 21  
 import net.wotonomy.foundation.NSMutableDictionary;
 22  
 import net.wotonomy.foundation.NSNotification;
 23  
 import net.wotonomy.foundation.NSNotificationQueue;
 24  
 import net.wotonomy.foundation.internal.WotonomyException;
 25  
 
 26  
 /**
 27  
 * An object store that wraps a datastore for vending test objects.
 28  
 */
 29  
 public class DataObjectStore extends EOObjectStore
 30  
 {
 31  
     DataSoup soup;
 32  
     
 33  
     /**
 34  
     * Constructor specifies path to datastore.
 35  
     */
 36  0
     public DataObjectStore( String aPath )
 37  0
     {
 38  0
         soup = new XMLFileSoup( aPath );
 39  0
     }
 40  
         
 41  
     /**
 42  
     * This implementation returns an appropriately configured array fault.
 43  
     */
 44  
     public NSArray arrayFaultWithSourceGlobalID ( 
 45  
         EOGlobalID aGlobalID,
 46  
         String aRelationship,
 47  
         EOEditingContext aContext )
 48  
     {
 49  0
         return new ArrayFault( 
 50  0
             aGlobalID, aRelationship, aContext );
 51  
     }
 52  
      
 53  
     /**
 54  
     * This implementation returns the actual
 55  
     * object for the specified id.
 56  
     */
 57  
     public Object faultForGlobalID ( 
 58  
         EOGlobalID aGlobalID,
 59  
         EOEditingContext aContext )
 60  
     {
 61  0
 System.out.println( "DataObjectStore.faultForGlobalID: * reading object * : " + aGlobalID );
 62  0
         Object result = soup.getObjectByKey( 
 63  0
             ((DataKeyID)aGlobalID).getKey() );
 64  
 
 65  0
         if ( result == null ) return null;
 66  
         
 67  
         //! transpose keys to objects
 68  0
         convertRelationKeysToObjects( aContext, result, aGlobalID );
 69  
         //!
 70  
             
 71  0
         aContext.recordObject( result, aGlobalID );
 72  0
         return result;
 73  
     }
 74  
         
 75  
     /**
 76  
     * Returns a fault representing an object of 
 77  
     * the specified entity type with values from 
 78  
     * the specified dictionary.  The fault should
 79  
     * belong to the specified editing context.
 80  
     */        
 81  
     public Object faultForRawRow ( 
 82  
         Map aDictionary,
 83  
         String anEntityName,
 84  
         EOEditingContext aContext )
 85  
     {
 86  
         //TODO: faults are not yet supported
 87  0
         throw new WotonomyException( 
 88  0
             "Faults are not yet supported." );
 89  
     }
 90  
         
 91  
     /**
 92  
     * Given a newly instantiated object, this method 
 93  
     * initializes its properties to values appropriate
 94  
     * for the specified id.  The object should belong
 95  
     * to the specified editing context.  
 96  
     * This method is called to populate faults.
 97  
     */        
 98  
     public void initializeObject(Object anObject, EOGlobalID aGlobalID,
 99  
                         EOEditingContext aContext) {
 100  0
                 if (aGlobalID.isTemporary()) {
 101  
                         // TODO: this should never happen, but it does now until we get
 102  
                         // faults.
 103  
 
 104  
                         // do not reinit an uncommitted object
 105  0
                         return;
 106  
                 }
 107  
 
 108  0
                 System.out.println("DataObjectStore.initializeObject: * reading object * : "
 109  0
                                                 + aGlobalID);
 110  
                 //net.wotonomy.ui.swing.util.StackTraceInspector.printShortStackTrace();
 111  0
                 Object original = soup.getObjectByKey(((DataKeyID) aGlobalID).getKey());
 112  
 
 113  
                 // ! transpose keys to objects
 114  0
                 convertRelationKeysToObjects(aContext, original, aGlobalID);
 115  
                 // !
 116  0
                 EOObserverCenter.notifyObserversObjectWillChange(anObject);
 117  0
                 KeyValueCodingUtilities.copy(aContext, original, aContext, anObject);
 118  0
         }
 119  
         
 120  
     /**
 121  
          * Remove all values from all objects in memory, turning them into faults,
 122  
          * and posts a notification that all objects have been invalidated.
 123  
          */
 124  
     public void invalidateAllObjects ()
 125  
     {
 126  
         // does nothing except post notification
 127  
         
 128  0
         NSNotificationQueue.defaultQueue().enqueueNotification(
 129  0
             new NSNotification(
 130  0
                 InvalidatedAllObjectsInStoreNotification, this ),
 131  0
             NSNotificationQueue.PostNow );
 132  0
     }
 133  
     
 134  
     /**
 135  
     * Removes values with the specified ids from memory,
 136  
     * turning them into faults, and posts a notification
 137  
     * that those objects have been invalidated.
 138  
     */
 139  
     public void invalidateObjectsWithGlobalIDs ( 
 140  
         List aList )
 141  
     {
 142  
         // does nothing
 143  0
     }
 144  
         
 145  
     /**
 146  
     * Returns false because locking is not permitted.
 147  
     */
 148  
     public boolean isObjectLockedWithGlobalID ( 
 149  
         EOGlobalID aGlobalID,
 150  
         EOEditingContext aContext )
 151  
     {
 152  0
         return false;
 153  
     }
 154  
         
 155  
     /**
 156  
     * Does nothing because locking is not permitted.
 157  
     */
 158  
     public void lockObjectWithGlobalID ( 
 159  
         EOGlobalID aGlobalID,
 160  
         EOEditingContext aContext )
 161  
     {
 162  
         // does nothing   
 163  0
     }
 164  
         
 165  
     /**
 166  
     * Returns a List of objects associated with the object 
 167  
     * with the specified id for the specified property 
 168  
     * relationship.  This method may not return an array fault
 169  
     * because array faults call this method to fetch on demand.
 170  
     * All objects must be registered the specified editing context.
 171  
     * The specified relationship key must produce a result of
 172  
     * type Collection for the source object or an exception is thrown.
 173  
     */
 174  
     public NSArray objectsForSourceGlobalID ( 
 175  
         EOGlobalID aGlobalID,
 176  
         String aRelationship,
 177  
         EOEditingContext aContext )
 178  
     {
 179  0
             System.out.println( "DataObjectStore.objectsForSourceGlobalID: * reading object * : " + aGlobalID );
 180  0
         Object object = soup.getObjectByKey(((DataKeyID)aGlobalID).getKey() );
 181  
 
 182  0
         if ( object == null ) return null;
 183  
         
 184  
         Object fault;
 185  
         EOGlobalID id;
 186  0
         NSMutableArray result = new NSMutableArray();
 187  
         
 188  0
         Iterator it = ((TestObject)object).getChildList().iterator();
 189  0
         while ( it.hasNext() )
 190  
         {
 191  0
             id = new DataKeyID((DataKey)it.next());
 192  0
             fault = aContext.faultForGlobalID( id, aContext );
 193  
                 
 194  
             // if key still exists
 195  0
             if ( fault != null ) 
 196  
             {
 197  
 //System.out.println( "objectsForSourceGlobalID: found: " + id + " : " + fault ); 
 198  0
                 result.add( fault );
 199  
 
 200  
 // for testing purposes                
 201  0
 ((TestObject)fault).setParent( (TestObject) object );
 202  0
             }
 203  
             else // key no longer exists
 204  
             {
 205  
                 // do not add
 206  0
 System.out.println( "objectsForSourceGlobalID: could not find fault for id: " + id ); 
 207  
             }
 208  0
         }
 209  0
         return result;
 210  
 
 211  
     }
 212  
         
 213  
     /**
 214  
     * Returns a List of objects the meet the criteria of
 215  
     * the supplied specification.  
 216  
     * Each object is registered with the specified editing context.
 217  
     * If any object is already registered in the specified context, 
 218  
     * it is not refetched and that object should be used in the array.
 219  
     */
 220  
     public NSArray objectsWithFetchSpecification ( 
 221  
         EOFetchSpecification aFetchSpec,
 222  
         EOEditingContext aContext )
 223  
     {
 224  
         //TODO: fetch specs are not yet supported
 225  
         
 226  0
         DataView view = soup.queryObjects( null, null );
 227  0
 System.out.println( "DataObjectStore: ** querying all objects **" );
 228  
 
 229  
         // we've changed this implementation so that 
 230  
         // it simply calls faultForGlobalID on the context
 231  
         // for each id in the result set.
 232  
         // this way, child contexts inherit parent's state.
 233  
         // however, it's unclear if the specification allows
 234  
         // faults in the resulting array.  sounds like it doesn't.
 235  0
         NSMutableArray result = new NSMutableArray();
 236  
         DataKeyID id;
 237  0
         Iterator it = view.iterator();
 238  0
         while ( it.hasNext() )
 239  
         {
 240  0
             id = new DataKeyID( view.getKeyForObject( it.next() ) );
 241  0
             result.addObject( aContext.faultForGlobalID( id, aContext ) );
 242  0
         }
 243  0
         return result;
 244  
     }
 245  
         
 246  
     /**
 247  
     * Removes all values from the specified object, 
 248  
     * converting it into a fault for the specified id.
 249  
     * New or deleted objects should not be refaulted.
 250  
     */
 251  
     public void refaultObject ( 
 252  
         Object anObject,
 253  
         EOGlobalID aGlobalID,
 254  
         EOEditingContext aContext )
 255  
     {
 256  
         //TODO: faults are not yet supported
 257  
         // just re-initialize the object
 258  0
         initializeObject( anObject, aGlobalID, aContext );
 259  0
     }
 260  
         
 261  
     /**
 262  
     * Writes all changes in the specified editing context
 263  
     * to the respository.
 264  
     */
 265  
     public void saveChangesInEditingContext ( 
 266  
         EOEditingContext aContext )
 267  
     {
 268  
         Object o;
 269  
         DataKeyID id;
 270  
         Iterator it;
 271  
         
 272  
         // process deletes
 273  0
         it = aContext.deletedObjects().iterator();
 274  0
         while ( it.hasNext() )
 275  
         {
 276  0
             o = it.next();
 277  0
             id = (DataKeyID) aContext.globalIDForObject( o );
 278  0
 System.out.println( "DataObjectStore: * deleting object * : " + id );
 279  0
             soup.removeObject( id.getKey() );
 280  
             // remove object from editing context
 281  0
             aContext.forgetObject( o );
 282  0
         }
 283  
         
 284  
         // process inserts
 285  0
         NSMutableDictionary userInfo = null;
 286  0
         it = aContext.insertedObjects().iterator();
 287  0
         while ( it.hasNext() )
 288  
         {   
 289  0
             o = it.next();
 290  0
             EOGlobalID oldId = aContext.globalIDForObject( o );
 291  
 
 292  
             //! transpose objects to keys
 293  0
             convertRelationObjectsToKeys( aContext, (TestObject) o );
 294  0
             id = new DataKeyID( soup.addObject( o ) );
 295  0
             convertRelationKeysToObjects( aContext, (TestObject) o, oldId );
 296  
             //!
 297  
 
 298  0
 System.out.println( "DataObjectStore: * adding object * : " + id );
 299  
             
 300  
             // save mapping of old id to new id
 301  0
             if ( userInfo == null ) 
 302  
             {
 303  0
                 userInfo = new NSMutableDictionary();   
 304  
             }
 305  0
             userInfo.setObjectForKey( id, oldId );
 306  0
         }
 307  
         
 308  
         // broadcast inserted objects' new ids if necessary
 309  0
         if ( userInfo != null )
 310  
         {
 311  0
             NSNotificationQueue.defaultQueue().enqueueNotification(
 312  0
                 new NSNotification(
 313  0
                     EOGlobalID.GlobalIDChangedNotification, null, userInfo ),
 314  0
                 NSNotificationQueue.PostNow );
 315  
         }
 316  
 
 317  0
         System.out.println( aContext.updatedObjects() );
 318  
         
 319  
         // process updates
 320  0
         it = aContext.updatedObjects().iterator();
 321  0
         while ( it.hasNext() )
 322  
         {
 323  
 //if ( true ) // test validation error message handling
 324  
 //throw new RuntimeException( "Update not allowed." );            
 325  0
             o = it.next();
 326  0
             id = (DataKeyID) aContext.globalIDForObject( o );
 327  0
 System.out.println( "DataObjectStore: * updating object * : " + id );
 328  
 
 329  
             //! transpose objects to keys
 330  0
             convertRelationObjectsToKeys( aContext, (TestObject) o );
 331  0
             soup.updateObject( id.getKey(), o );
 332  0
             convertRelationKeysToObjects( aContext, (TestObject) o, id );
 333  
             //!
 334  
             
 335  0
         }
 336  0
     }
 337  
 
 338  
     private void convertRelationKeysToObjects( 
 339  
         EOEditingContext aContext, Object anObject, EOGlobalID aGlobalID )
 340  
     { // System.out.println( "convertRelationKeysToObjects: " + anObject );        
 341  
 // set editing context for testing
 342  0
 ((TestObject)anObject).editingContext = aContext;
 343  
         
 344  
         Object fault;
 345  
         DataKeyID id;
 346  0
         List result = new LinkedList();
 347  0
         Iterator it = ((TestObject)anObject).getChildList().iterator();
 348  0
         while ( it.hasNext() )
 349  
         {
 350  0
             id = new DataKeyID((DataKey)it.next());
 351  0
             fault = aContext.faultForGlobalID( id, aContext );
 352  
                 
 353  
             // if key still exists
 354  0
             if ( fault != null ) 
 355  
             {
 356  
 //System.out.println( "convertRelationObjectsToKeys: found: " + id + " : " + fault ); 
 357  0
                 result.add( fault );
 358  
 
 359  
 // for testing purposes                
 360  0
 ((TestObject)fault).setParent( (TestObject) anObject );
 361  0
             }
 362  
             else // key no longer exists
 363  
             {
 364  
                 // do not add
 365  0
 System.out.println( "convertRelationObjectsToKeys: could not find fault for id: " + id ); 
 366  
             }
 367  0
         }
 368  
         // this tests loading manually on-demand
 369  
 //        ((TestObject)anObject).setChildList( null );
 370  
         // this tests loading immediately
 371  0
         ((TestObject)anObject).setChildList( result );
 372  
         // this tests loading array faults
 373  
 //        ((TestObject)result).setChildList( null );
 374  0
         ((TestObject)anObject).setChildList( 
 375  0
             aContext.arrayFaultWithSourceGlobalID( 
 376  0
                 aGlobalID, "childList", aContext ) );
 377  
 
 378  0
     }
 379  
     
 380  
     private void convertRelationObjectsToKeys( 
 381  
         EOEditingContext aContext, Object anObject )
 382  
     { // System.out.println( "convertRelationObjectsToKeys: " + anObject );        
 383  
         Object o;
 384  
         DataKeyID id;
 385  0
         List result = new LinkedList();
 386  0
         Iterator it = ((TestObject)anObject).getChildList().iterator();
 387  
 // for testing purposes                
 388  0
 ((TestObject)anObject).setParent( null );
 389  0
 ((TestObject)anObject).editingContext = null;
 390  0
         while ( it.hasNext() )
 391  
         {
 392  0
             o = it.next();
 393  
 //System.out.println( "convertRelationObjectsToKeys: " + o + " : " + aContext.globalIDForObject( o ) ); 
 394  0
             id = (DataKeyID)aContext.globalIDForObject( o );            
 395  
             
 396  
             // if object still exists in context
 397  0
             if ( id != null ) 
 398  
             {
 399  0
                 result.add( id.getKey() );
 400  0
             }
 401  
             else // object was deleted
 402  
             {
 403  
                 // do not add  
 404  0
 System.out.println( "convertRelationObjectsToKeys: could not find id for object: " + o ); 
 405  0
 System.out.println( aContext.registeredObjects() ); 
 406  
             }
 407  
             
 408  0
         }
 409  0
         ((TestObject)anObject).setChildList( result );
 410  0
     }
 411  
     
 412  
     
 413  
 /*
 414  
  * $Log$
 415  
  * Revision 1.1  2006/02/19 16:30:25  cgruber
 416  
  * Update imports and maven dependencies.
 417  
  *
 418  
  * Revision 1.1  2006/02/16 13:18:56  cgruber
 419  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 420  
  *
 421  
  * Revision 1.18  2002/03/11 03:18:39  mpowers
 422  
  * Now properly handling ObserverChangesLater.
 423  
  *
 424  
  * Revision 1.17  2001/10/26 18:39:44  mpowers
 425  
  * Posting notifications immediately, rather than delayed.
 426  
  *
 427  
  * Revision 1.16  2001/05/06 18:27:10  mpowers
 428  
  * More broadly catching editing contexts for now.
 429  
  *
 430  
  * Revision 1.15  2001/05/05 23:05:43  mpowers
 431  
  * Implemented Array Faults.
 432  
  *
 433  
  * Revision 1.14  2001/05/05 15:00:06  mpowers
 434  
  * Tested load-on-demand: still works.
 435  
  * Now using registerClone for consistency.
 436  
  * Editing context is temporarily posting notification on objectWillChange.
 437  
  *
 438  
  * Revision 1.13  2001/05/04 23:24:30  mpowers
 439  
  * Changes to test code.
 440  
  *
 441  
  * Revision 1.12  2001/05/04 16:57:56  mpowers
 442  
  * Now correctly transposing references to editing contexts when
 443  
  * cloning/copying between editing contexts.
 444  
  *
 445  
  * Revision 1.11  2001/05/02 17:33:28  mpowers
 446  
  * More changes for testing.
 447  
  *
 448  
  * Revision 1.10  2001/04/30 13:15:24  mpowers
 449  
  * Child contexts re-initializing objects invalidated in parent now
 450  
  * propery transpose relationships.
 451  
  *
 452  
  * Revision 1.9  2001/04/29 22:02:45  mpowers
 453  
  * Work on id transposing between editing contexts.
 454  
  *
 455  
  * Revision 1.8  2001/04/29 02:29:31  mpowers
 456  
  * Debugging relationship faulting.
 457  
  *
 458  
  * Revision 1.7  2001/04/28 22:17:51  mpowers
 459  
  * Revised PropertyDataSource to be EOClassDescription-aware.
 460  
  *
 461  
  * Revision 1.6  2001/04/28 16:18:44  mpowers
 462  
  * Implementing relationships.
 463  
  *
 464  
  * Revision 1.5  2001/04/13 16:33:36  mpowers
 465  
  * Now broadcasting notifications.
 466  
  *
 467  
  * Revision 1.4  2001/04/08 21:00:54  mpowers
 468  
  * Changes to support new objectsForFetchSpecification scheme.
 469  
  *
 470  
  * Revision 1.3  2001/03/22 21:37:52  mpowers
 471  
  * Testing new features.
 472  
  *
 473  
  * Revision 1.2  2001/03/15 21:10:41  mpowers
 474  
  * Implemented global id re-registration for newly saved inserts.
 475  
  *
 476  
  * Revision 1.1  2001/03/05 22:12:11  mpowers
 477  
  * Created the control package for a datastore-specific implementation
 478  
  * of EOObjectStore.
 479  
  *
 480  
  * 
 481  
  */
 482  
 }
 483