|
|
1.1 ! root 1: #import "UniqueKey.h" ! 2: #import "Projects.h" ! 3: ! 4: ! 5: static BOOL _Debug = YES; ! 6: ! 7: @implementation Projects ! 8: ! 9: /****************************************************************************** ! 10: * Create two instances of the UniqueKey object to grab blocks of <count> keys for ! 11: * our use during inserts. The count is set low so you can see the SQL reserve ! 12: * blocks of keys. Up the count to something larger for it to be of use. ! 13: * ! 14: * The login information (connection dictionary) in the model has been blanked out, ! 15: * since you may elect to have the tables in some database other than PEOPLE, so we ! 16: * elect to run a login panel. Once the login is complete we can get the ! 17: * connection dictionary from the adaptor and use that information to allow ! 18: * UniqueKey to login and create its separate connection for key reservation. ! 19: * ! 20: * Note the content views of the employee and project boxes and paste in the ! 21: * default content. ! 22: ******************************************************************************/ ! 23: - appDidInit:sender ! 24: { ! 25: EOAdaptor *eoAdaptor; ! 26: ! 27: dbChannel = [[(id)[employeeController dataSource] databaseChannel] retain]; ! 28: dbContext = [[dbChannel databaseContext] retain]; ! 29: ! 30: if(_Debug) [[dbChannel adaptorChannel] setDelegate:self]; ! 31: ! 32: projectEntity = [[(id)[projectController dataSource] entity] retain]; ! 33: employeeEntity = [[(id)[employeeController dataSource] entity] retain]; ! 34: empProjectEntity = [[(id)[projectEntity relationshipNamed:@"toEmpProjects"] destinationEntity] retain]; ! 35: empProjectDDS = [[EODatabaseDataSource alloc] initWithDatabaseChannel: dbChannel ! 36: entityNamed: [empProjectEntity name]]; ! 37: eoAdaptor = [[[dbChannel adaptorChannel] adaptorContext] adaptor]; ! 38: if(![eoAdaptor runLoginPanelAndValidateConnectionDictionary]) [NXApp terminate:self]; ! 39: [UniqueKey setConnectionDictionary:[eoAdaptor connectionDictionary]]; ! 40: ! 41: projectUniqueKey = [[[UniqueKey alloc] initWithEntity:projectEntity count:5] retain]; ! 42: employeeUniqueKey = [[[UniqueKey alloc] initWithEntity:employeeEntity count:5] retain]; ! 43: if(!projectUniqueKey || !employeeUniqueKey) [NXApp terminate:self]; ! 44: ! 45: [self setFetchOrderFor:projectController with:@"ProjectName" order:EOAscendingOrder]; ! 46: [self setFetchOrderFor:addProjectsForEmployeeController with:@"ProjectName" order:EOAscendingOrder]; ! 47: [self setFetchOrderFor:employeeController with:@"LastName" order:EOAscendingOrder]; ! 48: [self setFetchOrderFor:addEmployeesOnProjectController with:@"LastName" order:EOAscendingOrder]; ! 49: ! 50: [addProjectsForEmployeeController setSelectsFirstObjectAfterFetch:NO]; ! 51: [addEmployeesOnProjectController setSelectsFirstObjectAfterFetch:NO]; ! 52: ! 53: inspectorWindow=[swapBox window]; ! 54: [self projectInspector:nil]; // swap in the project content view ! 55: [[inspectorWindow center] makeKeyAndOrderFront:nil]; ! 56: return self; ! 57: } ! 58: ! 59: ! 60: /****************************************************************************** ! 61: * Set a controller's data source to fetch sorted by a given attribute name ! 62: * and order. ! 63: ******************************************************************************/ ! 64: - setFetchOrderFor:(EOController*)controller with:(NSString*)attributeName order:(EOOrdering)order ! 65: { ! 66: id dataSource = [controller dataSource]; ! 67: id attribute = [[dataSource entity] attributeNamed:attributeName]; ! 68: NSArray *orderArray; ! 69: ! 70: orderArray = [NSArray arrayWithObject: ! 71: [EOAttributeOrdering attributeOrderingWithAttribute:attribute ordering:order]]; ! 72: [dataSource setFetchOrder:orderArray]; ! 73: return self; ! 74: } ! 75: ! 76: ! 77: /****************************************************************************** ! 78: * Accept the users selection for either the Employee or Project inspector. Swap ! 79: * in the appropriate content view. ! 80: ******************************************************************************/ ! 81: - employeeInspector:sender ! 82: { ! 83: [inspectorWindow disableFlushWindow]; ! 84: [swapBox setContentView:[employeeBox contentView]]; ! 85: [employeeController fetch]; ! 86: [swapBox display]; ! 87: [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded]; ! 88: return self; ! 89: } ! 90: ! 91: - projectInspector:sender ! 92: { ! 93: [inspectorWindow disableFlushWindow]; ! 94: [swapBox setContentView:[projectBox contentView]]; ! 95: [projectController fetch]; ! 96: [swapBox display]; ! 97: [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded]; ! 98: return self; ! 99: } ! 100: ! 101: ! 102: /****************************************************************************** ! 103: * Utility to create an intermediate table empProject EOGenericRecord. ! 104: ******************************************************************************/ ! 105: - createEmpProject:(NSNumber*)empId:(NSNumber*)projectId ! 106: { ! 107: EOGenericRecord *empProject = [empProjectDDS createObject]; ! 108: ! 109: [empProject setObject:projectId forKey:@"ProjectId"]; ! 110: [empProject setObject:empId forKey:@"EmpId"]; ! 111: return empProject; ! 112: } ! 113: ! 114: ! 115: /****************************************************************************** ! 116: * Bring up the add employee selection panel and start a modal session. Construct ! 117: * and 'otherEmployees' qualifier to select employees that do not already appear ! 118: * in the EmployeesOnProject detail view. ! 119: ******************************************************************************/ ! 120: - addEmployeesOnProject:sender ! 121: { ! 122: EOGenericRecord *project = [(id)[employeesOnProjectController dataSource] masterObject]; ! 123: NSNumber *projectId = [project objectForKey:@"ProjectId"]; ! 124: EOQualifier *otherEmployees; ! 125: NSString *qualifierString; ! 126: ! 127: qualifierString = [NSString stringWithFormat: ! 128: @"EmpId not in (SELECT z1.EMP_ID FROM EMPLOYEE z1, EMP_PROJECT z2 " ! 129: @"WHERE z1.EMP_ID = z2.EMP_ID AND z2.PROJECT_ID = %@)",projectId]; ! 130: ! 131: otherEmployees = [[[EOQualifier alloc] ! 132: initWithEntity:employeeEntity qualifierFormat:qualifierString] autorelease]; ! 133: ! 134: [(id)[addEmployeesOnProjectController dataSource] setQualifier:otherEmployees]; ! 135: [addEmployeesOnProjectController clearSelection]; ! 136: [addEmployeesOnProjectController fetch]; ! 137: [[addEmployeesPanel center] makeKeyAndOrderFront:nil]; ! 138: [NXApp runModalFor:addEmployeesPanel]; ! 139: [addEmployeesPanel orderOut:self]; ! 140: [projectController fetch]; ! 141: return self; ! 142: } ! 143: ! 144: - addEmployeesOnProjectOK:sender ! 145: { ! 146: NSArray *eArray; ! 147: NSEnumerator *eEnumerator; ! 148: EOGenericRecord *project; ! 149: NSNumber *projectId; ! 150: EOGenericRecord *employee; ! 151: EOGenericRecord *empProject; ! 152: ! 153: eArray = [addEmployeesOnProjectController selectedObjects]; ! 154: eEnumerator = [eArray objectEnumerator]; ! 155: project = [(id)[employeesOnProjectController dataSource] masterObject]; ! 156: projectId = [project objectForKey:@"ProjectId"]; ! 157: [dbContext beginTransaction]; ! 158: while((employee = [eEnumerator nextObject]) != nil) { ! 159: empProject = [self createEmpProject:[employee objectForKey:@"EmpId"]:projectId]; ! 160: [dbChannel insertObject:empProject]; ! 161: } ! 162: [dbContext commitTransaction]; ! 163: [NXApp stopModal]; ! 164: return self; ! 165: } ! 166: ! 167: ! 168: /****************************************************************************** ! 169: * Bring up the add project selection panel and start a modal session. Construct ! 170: * and 'otherProjects' qualifier to select project that do not already appear ! 171: * in the ProjectsForEmployee detail view. We use an imbedded select here with ! 172: * '.' chars in the qualifier string. These names will not be converted, since they ! 173: * contain '.' chars, so we have the ability to write qualifiers that ! 174: * reference external names it we like. ! 175: ******************************************************************************/ ! 176: - addProjectsForEmployee:sender ! 177: { ! 178: EOGenericRecord *employee = [(id)[projectsForEmployeeController dataSource] masterObject]; ! 179: NSNumber *empId = [employee objectForKey:@"EmpId"]; ! 180: EOQualifier *otherProjects; ! 181: NSString *qualifierString; ! 182: ! 183: qualifierString = [NSString stringWithFormat: ! 184: @"ProjectId not in (SELECT z1.PROJECT_ID FROM PROJECT z1, EMP_PROJECT z2 " ! 185: @"WHERE z1.PROJECT_ID = z2.PROJECT_ID AND z2.EMP_ID = %@)",empId]; ! 186: ! 187: otherProjects = [[[EOQualifier alloc] ! 188: initWithEntity:projectEntity qualifierFormat:qualifierString] autorelease]; ! 189: ! 190: [(id)[addProjectsForEmployeeController dataSource] setQualifier:otherProjects]; ! 191: [addProjectsForEmployeeController clearSelection]; ! 192: [addProjectsForEmployeeController fetch]; ! 193: [[addProjectsPanel center] makeKeyAndOrderFront:nil]; ! 194: [NXApp runModalFor:addProjectsPanel]; ! 195: [addProjectsPanel orderOut:self]; ! 196: [employeeController fetch]; ! 197: return self; ! 198: } ! 199: ! 200: - addProjectsForEmployeeOK:sender ! 201: { ! 202: NSArray *pArray; ! 203: NSEnumerator *pEnumerator; ! 204: EOGenericRecord *employee; ! 205: NSNumber *empId; ! 206: EOGenericRecord *project; ! 207: EOGenericRecord *empProject; ! 208: ! 209: pArray = [addProjectsForEmployeeController selectedObjects]; ! 210: pEnumerator = [pArray objectEnumerator]; ! 211: employee = [(id)[projectsForEmployeeController dataSource] masterObject]; ! 212: empId = [employee objectForKey:@"EmpId"]; ! 213: ! 214: [dbContext beginTransaction]; ! 215: while((project = [pEnumerator nextObject]) != nil) { ! 216: empProject = [self createEmpProject:empId:[project objectForKey:@"ProjectId"]]; ! 217: [dbChannel insertObject:empProject]; ! 218: } ! 219: [dbContext commitTransaction]; ! 220: [NXApp stopModal]; ! 221: return self; ! 222: } ! 223: ! 224: ! 225: /****************************************************************************** ! 226: * Delete the intermediate table entries for the selected employee. To do this we ! 227: * get the selected master object and ask it for the enumerator of empProject ! 228: * objects. Since each empProject object can be asked objectForKey:@"Employee", we ! 229: * see if that empProject object has a corresponding employee in the selected employee ! 230: * array (eArray). We choose to use the method indexOfObjectIdenticalTo: to do the ! 231: * check since it uses pointer equality. This works because object uniquing is ! 232: * enabled by default. ! 233: ******************************************************************************/ ! 234: - removeSelectedEmployeesOnProject:sender ! 235: { ! 236: NSArray *eArray; ! 237: EOGenericRecord *project; ! 238: NSEnumerator *epEnumerator; ! 239: EOGenericRecord *empProject; ! 240: ! 241: eArray = [employeesOnProjectController selectedObjects]; ! 242: project = [(id)[employeesOnProjectController dataSource] masterObject]; ! 243: epEnumerator = [[project objectForKey:@"toEmpProjects"] objectEnumerator]; ! 244: ! 245: [dbContext beginTransaction]; ! 246: while((empProject=[epEnumerator nextObject]) != nil) ! 247: if([eArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toEmployee"]]!=NSNotFound) ! 248: [dbChannel deleteObject:empProject]; ! 249: [dbContext commitTransaction]; ! 250: [projectController fetch]; ! 251: return self; ! 252: } ! 253: ! 254: ! 255: /****************************************************************************** ! 256: * Delete the intermediate table entries for the selected project. To do this we ! 257: * get the selected master object and ask it for the enumerator of empProject ! 258: * objects. Since each empProject object can be asked objectForKey:@"Project", we ! 259: * see if that empProject object has a corresponding project in the selected project ! 260: * array (pArray). We choose to use the method indexOfObjectIdenticalTo: to do the ! 261: * check since it uses pointer equality. This works because object uniquing is ! 262: * enabled by default. ! 263: ******************************************************************************/ ! 264: - removeSelectedProjectsForEmployee:sender ! 265: { ! 266: NSArray *pArray; ! 267: EOGenericRecord *employee; ! 268: NSEnumerator *epEnumerator; ! 269: EOGenericRecord *empProject; ! 270: ! 271: pArray = [projectsForEmployeeController selectedObjects]; ! 272: employee = [(id)[projectsForEmployeeController dataSource] masterObject]; ! 273: epEnumerator = [[employee objectForKey:@"toEmpProjects"] objectEnumerator]; ! 274: ! 275: [dbContext beginTransaction]; ! 276: while((empProject=[epEnumerator nextObject]) != nil) ! 277: if([pArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toProject"]]!=NSNotFound) ! 278: [dbChannel deleteObject:empProject]; ! 279: [dbContext commitTransaction]; ! 280: [employeeController fetch]; ! 281: return self; ! 282: } ! 283: ! 284: ! 285: /****************************************************************************** ! 286: * Generate unique keys for the new object. Use the instance of UniqueKey ! 287: * to dole out a key from its internal buffer. The UniqueKey object has its ! 288: * own channel to the DB which it uses to allocate blocks of keys. ! 289: ******************************************************************************/ ! 290: - (BOOL)controller:(EOController *)controller willInsertObject:object atIndex: (unsigned)newIndex ! 291: { ! 292: if(controller==employeeController) { ! 293: NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease]; ! 294: NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease]; ! 295: NSNumber *empId = [NSNumber numberWithInt:[employeeUniqueKey nextKey]]; ! 296: ! 297: [object setObject:empId forKey:@"EmpId"]; ! 298: [object setObject:@"<FirstName>" forKey:@"FirstName"]; ! 299: [object setObject:@"<LastName>" forKey:@"LastName"]; ! 300: [object setObject:@"<Phone>" forKey:@"Phone"]; ! 301: [object setObject:emptyArray1 forKey:@"toEmpProjects"]; ! 302: [object setObject:emptyArray2 forKey:@"toProjects"]; ! 303: return YES; ! 304: } ! 305: if(controller==projectController) { ! 306: NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease]; ! 307: NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease]; ! 308: NSNumber *projectId = [NSNumber numberWithInt:[projectUniqueKey nextKey]]; ! 309: ! 310: [object setObject:projectId forKey:@"ProjectId"]; ! 311: [object setObject:@"<ProjectName>" forKey:@"ProjectName"]; ! 312: [object setObject:emptyArray1 forKey:@"toEmpProjects"]; ! 313: [object setObject:emptyArray2 forKey:@"toEmployees"]; ! 314: return YES; ! 315: } ! 316: return NO; ! 317: } ! 318: ! 319: ! 320: /****************************************************************************** ! 321: * When a project or employee is deleted, make sure we delete the entry in the ! 322: * empProject intermediate table. Both the project and employee entities have ! 323: * a toEmpProjects relationship which we can use to delete the intermediate ! 324: * table records. ! 325: ******************************************************************************/ ! 326: - (BOOL)controller:controller willDeleteObject:object ! 327: { ! 328: NSArray *epArray; ! 329: NSEnumerator *epEnumerator; ! 330: EOGenericRecord *empProject; ! 331: ! 332: // The employee and project entities have a toEmpProjects ! 333: // relationship to the intermediate table ! 334: if(controller==projectController || ! 335: controller==employeeController) { ! 336: [dbContext beginTransaction]; ! 337: epArray=[object objectForKey:@"toEmpProjects"]; ! 338: epEnumerator=[epArray objectEnumerator]; ! 339: while((empProject = [epEnumerator nextObject]) != nil) ! 340: [dbChannel deleteObject:empProject]; ! 341: [dbContext commitTransaction]; ! 342: } ! 343: return YES; ! 344: } ! 345: ! 346: ! 347: /****************************************************************************** ! 348: * Echo SQL when debug is enabled. ! 349: ******************************************************************************/ ! 350: - (EODelegateResponse)adaptorChannel:channel willEvaluateExpression:(NSMutableString *)expression ! 351: { ! 352: NSLog(expression); ! 353: return EODelegateApproves; ! 354: } ! 355: ! 356: - (void)dealloc ! 357: { ! 358: [dbContext release]; ! 359: [dbChannel release]; ! 360: [projectEntity release]; ! 361: [employeeEntity release]; ! 362: [empProjectEntity release]; ! 363: [projectUniqueKey release]; ! 364: [employeeUniqueKey release]; ! 365: [super dealloc]; ! 366: ! 367: } ! 368: ! 369: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.