home *** CD-ROM | disk | FTP | other *** search
/ NeXT Enterprise Objects Framework 1.1 / NeXT Enterprise Objects Framework 1.1.iso / NextDeveloper / Examples / EnterpriseObjects / DistributedEO / AppManager.m < prev    next >
Encoding:
Text File  |  1995-02-17  |  7.0 KB  |  229 lines

  1. /*
  2.    AppManager.m created by enoyau on Fri 13-Jan-1995
  3.  
  4.    You may freely copy, distribute, and reuse the code in this example.
  5.    NeXT disclaims any warranty of any kind, expressed or implied, as to its
  6.    fitness for any particular use.
  7. */
  8.  
  9. #import "AppManager.h"
  10. #import "Employee.h"
  11.  
  12. // A property added to the EMPLOYEE table in the PEOPLE demo database.
  13. // This property is needed to avoid concurrent update to the same record.
  14. #define lockProperty @"lock"
  15.  
  16. @interface AppManager(private)
  17. - (void)_updateDisplay;
  18. @end
  19.  
  20. @implementation AppManager(private)
  21.  
  22. // Responsible for keeping the lock button states up-to-date and to
  23. // allow/disallow editing in the tableview. 
  24. - (void)_updateDisplay
  25. {
  26.     id currentSelection = [[eoController selectedObjects] objectAtIndex:0];
  27.  
  28.     BOOL isEditable = [currentSelection isEditable];
  29.     BOOL isLocked = [currentSelection isLocked];
  30.  
  31.     [lockButton setTitle:isLocked ? "Unlock" : "Lock"];
  32.     [lockButton setEnabled:(!isLocked) || isEditable];
  33.  
  34.     [tableView setTarget:isLocked ? nil : lockButton]; 
  35.     if([tableView isEditable] != isEditable) {
  36.         [tableView setEditable:isEditable];
  37.         if(!isEditable) {
  38.             [tableView perform:@selector(display)
  39.                           with:nil
  40.                     afterDelay:0
  41.                 cancelPrevious:NO];
  42.         }
  43.     }
  44.     return;
  45. }
  46.  
  47. @end
  48.  
  49. @implementation AppManager
  50.  
  51. // This notification is sent to AppManager by the DEONotificationCenter.
  52. - (void)databaseChange:(DEONotification *)notification
  53. {
  54.     id eoObject = [notification notificationObject];
  55.  
  56.     if( !([EOFault isFault:eoObject] || [notification isLocal]) ) {
  57.         EODatabaseDataSource *eoDatabasedataSource;
  58.         EODatabaseChannel *eoDatabaseChannel;
  59.         EODatabaseContext *eoDatabaseContext;
  60.         BOOL autoTransaction = NO;
  61.  
  62.         eoDatabasedataSource =(EODatabaseDataSource*)[eoController dataSource];
  63.         eoDatabaseChannel = [eoDatabasedataSource databaseChannel];
  64.         eoDatabaseContext = [eoDatabaseChannel databaseContext];
  65.  
  66.         // refetch the EO from the database server to preserve data integrity.
  67.         if (![eoDatabaseContext transactionNestingLevel]) {
  68.             [eoDatabaseContext beginTransaction];
  69.             autoTransaction = YES;
  70.         }
  71.  
  72.         [eoDatabaseChannel refetchObject:eoObject];
  73.  
  74.         if (autoTransaction) [eoDatabaseContext commitTransaction];
  75.  
  76.         // redisplay the data. If editing is not ended, wait until it is done
  77.         // (by changing the selection or the state of the lock)       
  78.         if([tableView isEditable]) {
  79.             needRedisplay = YES;
  80.         } else {
  81.             [eoController redisplay];
  82.             [self _updateDisplay];
  83.         }
  84.     }
  85.     return;
  86. }
  87.  
  88. // Update the lock value in the database when lock button is pressed.
  89. - toggleLockOnSelection:sender
  90. {
  91.     if([lockButton isEnabled]) {
  92.         id currentSelection;
  93.         NSArray *keys;
  94.         NSMutableDictionary *objectValue;
  95.  
  96.         currentSelection = [[eoController selectedObjects] objectAtIndex:0];
  97.         keys = [NSArray arrayWithObject:lockProperty];
  98.         objectValue = [[[currentSelection valuesForKeys:keys] mutableCopy] autorelease];
  99.  
  100.         if([[objectValue objectForKey:lockProperty] isEqual:[EONull null]]) {
  101.             [objectValue setObject:lockString forKey:lockProperty];
  102.         } else {
  103.             [objectValue setObject:[EONull null] forKey:lockProperty];
  104.         }
  105.  
  106.         [eoController setValues:objectValue forObject:currentSelection];
  107.  
  108.         [self _updateDisplay];
  109.     }
  110.     return self;
  111. }
  112. @end
  113.  
  114. @implementation AppManager(EOControllerDelegate)
  115. - (void)controllerDidChangeSelection:(EOController *)controller
  116. {
  117.     if(needRedisplay) {
  118.         [eoController redisplay];
  119.         needRedisplay = NO;
  120.     }
  121.     [self _updateDisplay];
  122. }
  123. @end
  124.  
  125. @implementation AppManager(EOApplicationDelegate)
  126. - appDidInit:sender
  127. {
  128.     EODatabaseDataSource *eoDatabaseDataSource;
  129.     EODatabaseChannel *eoDatabaseChannel;
  130.     EOAdaptorContext *eoAdaptorContext;
  131.  
  132.     eoDatabaseDataSource = [eoController dataSource];
  133.     eoDatabaseChannel = [eoDatabaseDataSource databaseChannel];
  134.     eoAdaptorContext = [[eoDatabaseChannel adaptorChannel] adaptorContext];
  135.     
  136.     // Set up as the delegate of EOController, EODatabaseChannel,
  137.     // and EOAdaptorContext
  138.     [(EOController*)eoController setDelegate:self];
  139.     [eoDatabaseChannel setDelegate:self]; // EO updates, inserts and deletes.
  140.     [eoAdaptorContext setDelegate:self];  // Transactions begin, commit or rollback.
  141.  
  142.     // Put an ImageFormatter in column 0
  143.     [[tableView columnAt:0] setFormatter:[[NXImageFormatter alloc] init]];
  144.  
  145.     // A double click will lock the current selection to start the
  146.     // editing mode
  147.     [tableView setTarget:lockButton];
  148.     [tableView setDoubleAction:@selector(performClick:)];
  149.     
  150.     // Set up the Distributed Entreprise Object notification center
  151.     deoNotificationCenter =
  152.         [[DEONotificationCenter alloc]
  153.                      initWithDatabaseChannel:eoDatabaseChannel
  154.                                       entity:[eoDatabaseDataSource entity]];
  155.  
  156.     // Register for notification whenever objects of this entity are updated
  157.     [deoNotificationCenter addObserver:self
  158.                               selector:@selector(databaseChange:)
  159.                       notificationName:DEOUpdate
  160.                                 object:nil];
  161.  
  162.     // Update instance variables
  163.     transactions = [NSMutableArray new];
  164.     needRedisplay = NO;
  165.     lockString = [[NSString alloc] initWithFormat:@"%s-%@-%d",
  166.         NXUserName(),
  167.         [DEONotificationCenter localHostname],
  168.         NXProcessID];
  169.     
  170.     [Employee setLocalLockString:lockString];
  171.     
  172.     // Force the first fetch
  173.     [eoController fetch:self];
  174.  
  175.     [self _updateDisplay];
  176.     return self;
  177. }
  178.  
  179. - appWillTerminate:sender
  180. {
  181.     [transactions release];
  182.     [lockString release];
  183.     [deoNotificationCenter removeObserver:self];
  184.     [deoNotificationCenter release];
  185.     return self;
  186. }
  187. @end
  188.  
  189. // We keep a list of all objects updated in the current transaction
  190. // and post notification of the changes when the transaction commits.
  191. // A more complete implementation could also keep track of insertions
  192. // and deletions.
  193. @implementation AppManager(EOAdaptorContextDelegate)
  194. - (void)adaptorContextDidBegin:context
  195. {
  196.     [transactions addObject:[NSMutableArray array]];
  197. }
  198.  
  199. - (void)adaptorContextDidCommit:context
  200. {
  201.     NSMutableDictionary *commitedTransaction = [transactions lastObject];
  202.     id enumerator, current;
  203.  
  204.     [transactions removeLastObject];
  205.     if([transactions count]) {
  206.         [[transactions lastObject] addObjectsFromArray:commitedTransaction];
  207.     } else {
  208.         enumerator = [commitedTransaction objectEnumerator];
  209.         while(current = [enumerator nextObject]) {
  210.             [deoNotificationCenter postNotificationName:DEOUpdate object:current];
  211.         }
  212.     }
  213. }
  214.  
  215. // If the transaction rolls back, there is no notification.
  216. - (void)adaptorContextDidRollback:context
  217. {
  218.     [transactions removeLastObject];
  219. }
  220.  
  221. @end
  222.  
  223. @implementation AppManager(EODatabaseChannelDelegate)
  224. - (void)databaseChannel:channel didUpdateObject:anEO
  225. {
  226.     [(NSMutableArray *)[transactions lastObject] addObject:anEO];
  227. }
  228. @end
  229.