|
|
1.1 ! root 1: /*-------------------------------------------------------------------------- ! 2: * ! 3: * You may freely copy, distribute, and reuse the code in this example. ! 4: * SHL Systemhouse disclaims any warranty of any kind, expressed or ! 5: * implied, as to its fitness for any particular use. ! 6: * ! 7: * ! 8: * QueryController ! 9: * ! 10: * Inherits From: NSObject ! 11: * ! 12: * Conforms To: None. ! 13: * ! 14: * Declared In: QueryController.h ! 15: * ! 16: * ! 17: *------------------------------------------------------------------------*/ ! 18: #import "QueryController.h" ! 19: #import "EOQualifierContentsCategory.h" ! 20: ! 21: ! 22: ! 23: ! 24: @implementation QueryController ! 25: ! 26: ! 27: /*-------------------------------------------------------------------------- ! 28: * Model file reading and preparation for query building ! 29: *------------------------------------------------------------------------*/ ! 30: - _setUpForModelFile: (NSString *)aFilepath ! 31: { ! 32: id model = [[EOModel allocWithZone: NULL] ! 33: initWithContentsOfFile: aFilepath]; ! 34: ! 35: /*---------------------------------------------------------------------- ! 36: * create adaptor with specifics contained in the model (server, etc.) ! 37: *--------------------------------------------------------------------*/ ! 38: if (adaptor) [adaptor autorelease]; ! 39: adaptor = [[EOAdaptor adaptorWithModel: model] retain]; ! 40: [model autorelease]; ! 41: ! 42: /*---------------------------------------------------------------------- ! 43: * set up database pieces to allow transactions, qualifiers, etc. ! 44: *--------------------------------------------------------------------*/ ! 45: if (database) [database autorelease]; ! 46: database = [[EODatabase allocWithZone: [self zone]] ! 47: initWithAdaptor: adaptor]; ! 48: ! 49: if (dbContext) [dbContext autorelease]; ! 50: dbContext = [[EODatabaseContext alloc] initWithDatabase: database]; ! 51: ! 52: if (dbChannel) [dbChannel autorelease]; ! 53: dbChannel = [[EODatabaseChannel alloc] initWithDatabaseContext: dbContext]; ! 54: ! 55: /*---------------------------------------------------------------------- ! 56: * open the channel and turn on debug to see SQL in console ! 57: *--------------------------------------------------------------------*/ ! 58: if (! [dbChannel openChannel]) { ! 59: NSLog(@"database channel could not be opened."); ! 60: } ! 61: [[dbChannel adaptorChannel] setDebugEnabled:YES]; ! 62: ! 63: entity = nil; ! 64: ! 65: [self clearQualifier:nil]; ! 66: [[qualifierBrowser matrixInColumn:0] renewRows:0 cols:0]; ! 67: [[qualifierBrowser matrixInColumn:0] sizeToCells]; ! 68: [qualifierBrowser display]; ! 69: return self; ! 70: } ! 71: ! 72: ! 73: /*-------------------------------------------------------------------------- ! 74: * IconWell delegate method ! 75: *------------------------------------------------------------------------*/ ! 76: - dragSource:dragSource didDropOnIconWell:sender ! 77: { ! 78: [modelPath setStringValue: (const char *)[sender path]]; ! 79: [self _setUpForModelFile: [NSString stringWithCString: ! 80: (char *)[sender path]]]; ! 81: ! 82: [[browser loadColumnZero] display]; ! 83: [window makeKeyAndOrderFront: self]; ! 84: ! 85: return self; ! 86: } ! 87: ! 88: ! 89: /*-------------------------------------------------------------------------- ! 90: * Application delegation ! 91: *------------------------------------------------------------------------*/ ! 92: - appDidInit: sender ! 93: { ! 94: qualifier = nil; ! 95: dataSource = nil; ! 96: controller = nil; ! 97: dbContext = nil; ! 98: dbChannel = nil; ! 99: ! 100: [qualifierOperation setEmptySelectionEnabled:YES]; ! 101: [qualifierOperation selectCellAt:-1:-1]; ! 102: [window makeKeyAndOrderFront: self]; ! 103: return self; ! 104: } ! 105: ! 106: ! 107: /*-------------------------------------------------------------------------- ! 108: * Query Actions ! 109: *------------------------------------------------------------------------*/ ! 110: - performQuery:sender ! 111: { ! 112: id selection = [[NSMutableArray allocWithZone:NULL] init]; ! 113: id selectedCells = [[List alloc] init]; ! 114: int countSelected, iterator; ! 115: const char *cString; ! 116: ! 117: /*---------------------------------------------------------------------- ! 118: * get attribute names to be selected and browsed ! 119: *--------------------------------------------------------------------*/ ! 120: [[browser matrixInColumn:1] getSelectedCells:selectedCells]; ! 121: countSelected = [selectedCells count]; ! 122: ! 123: if (countSelected == 0) { ! 124: [selectedCells free]; ! 125: selectedCells = [[browser matrixInColumn:1] cellList]; ! 126: countSelected = [selectedCells count]; ! 127: } ! 128: ! 129: /*---------------------------------------------------------------------- ! 130: * transfer info from a NS3.2 list to a NS3.3NSArray ! 131: *--------------------------------------------------------------------*/ ! 132: for (iterator = 0; iterator < countSelected; iterator++) { ! 133: cString = [(Cell *)[selectedCells objectAt: iterator] stringValue]; ! 134: [(NSMutableArray *)selection addObject: ! 135: [NSString stringWithCString: cString]]; ! 136: } ! 137: ! 138: /*---------------------------------------------------------------------- ! 139: * assure current entity ! 140: *--------------------------------------------------------------------*/ ! 141: cString = [(Cell *)[[browser matrixInColumn:0] selectedCell] stringValue]; ! 142: entity = [[adaptor model] entityNamed: ! 143: [NSString stringWithCString: cString]]; ! 144: ! 145: /*---------------------------------------------------------------------- ! 146: * if qualifier is not defined, create an unqualified fetch. ! 147: *--------------------------------------------------------------------*/ ! 148: if (qualifier == nil) ! 149: qualifier = [entity qualifier]; ! 150: ! 151: /*---------------------------------------------------------------------- ! 152: * call method to handle fetch and reporting thru NXTableView ! 153: *--------------------------------------------------------------------*/ ! 154: [self fetchAndDisplay:selection inEntity:entity ! 155: withQualifier:qualifier]; ! 156: ! 157: return self; ! 158: } ! 159: ! 160: ! 161: - (void) fetchAndDisplay:(NSArray *)attributes inEntity:(EOEntity *)anEntity ! 162: withQualifier:(EOQualifier *)aQualifier ! 163: { ! 164: unsigned int count, iterator; ! 165: ! 166: [resultWindow disableDisplay]; ! 167: ! 168: /*---------------------------------------------------------------------- ! 169: * if not the first query, we need to change dataSources. The entity ! 170: * may be different from the previous query. ! 171: *--------------------------------------------------------------------*/ ! 172: if (dataSource) [dataSource autorelease]; ! 173: ! 174: dataSource = [[EODatabaseDataSource allocWithZone:[self zone]] ! 175: initWithDatabaseChannel:dbChannel ! 176: entityNamed:[anEntity name]]; ! 177: /*---------------------------------------------------------------------- ! 178: * get a new controller with the new dataSource ! 179: *--------------------------------------------------------------------*/ ! 180: controller = [[EOController allocWithZone: [self zone]] ! 181: initWithDataSource: dataSource]; ! 182: ! 183: /*---------------------------------------------------------------------- ! 184: * delete all current columns in the table view ! 185: *--------------------------------------------------------------------*/ ! 186: count = [resultTable columnCount]; ! 187: for (iterator = count; iterator > 0; iterator--) ! 188: [resultTable removeColumnAt: iterator-1]; ! 189: [(NXTableView *)resultTable setDataSource:nil]; ! 190: ! 191: /*---------------------------------------------------------------------- ! 192: * iterate through the desired select attributes and build columns for ! 193: * each in the tableView. ! 194: *--------------------------------------------------------------------*/ ! 195: count = [attributes count]; ! 196: for (iterator = 0; iterator < count; iterator ++) { ! 197: id association; ! 198: id attribute = [anEntity attributeNamed: ! 199: [attributes objectAtIndex:iterator]]; ! 200: ! 201: [resultTable addColumn:attribute withTitle: ! 202: [[(EOAttribute *)attribute name] cString]]; ! 203: ! 204: /*---------------------------------------------------------------------- ! 205: * create a new association for each of these attribute/column pairs ! 206: *--------------------------------------------------------------------*/ ! 207: association = [[EOColumnAssociation allocWithZone: [self zone]] ! 208: initWithController:controller key: [(EOAttribute *)attribute name] ! 209: destination:[resultTable columnAt:iterator]]; ! 210: ! 211: [association setTableView:resultTable]; ! 212: [controller addAssociation: association]; ! 213: [association autorelease]; ! 214: } ! 215: ! 216: /*---------------------------------------------------------------------- ! 217: * set the qualifier for the fetch. ! 218: *--------------------------------------------------------------------*/ ! 219: [dataSource setQualifier: aQualifier]; ! 220: ! 221: /*---------------------------------------------------------------------- ! 222: * Start a transaction, do the fetch, rollback the transaction (a fetch ! 223: * doesn't need to commit anything) have the values filled to the ! 224: * tableView via the columnAssociations. ! 225: *--------------------------------------------------------------------*/ ! 226: [dbContext beginTransaction]; ! 227: ! 228: if (! [controller fetch]) ! 229: NSLog(@"controller fetch failed."); ! 230: ! 231: [dbContext rollbackTransaction]; ! 232: ! 233: /*---------------------------------------------------------------------- ! 234: * Redisplay everything... ! 235: *--------------------------------------------------------------------*/ ! 236: [resultWindow reenableDisplay]; ! 237: [controller redisplay]; ! 238: [resultWindow makeKeyAndOrderFront:self]; ! 239: return; ! 240: } ! 241: ! 242: ! 243: - (int) browser:aBrowser fillMatrix:aMatrix inColumn:(int)aColumn ! 244: { ! 245: int iterator = 0, entryCount = 0; ! 246: id contents = nil; ! 247: id enumerator, current; ! 248: ! 249: /*---------------------------------------------------------------------- ! 250: * Fill qualifier browser with the attributes of the selected entity; ! 251: * this is the same list as in the second column of the first browser. ! 252: *--------------------------------------------------------------------*/ ! 253: if (aBrowser == qualifierBrowser) { ! 254: id selectedEntity; ! 255: ! 256: iterator = 0; ! 257: if ([browser selectedColumn] < 0) ! 258: return 0; ! 259: ! 260: selectedEntity = [NSString stringWithCString: ! 261: [(Cell *)[[browser matrixInColumn:0] selectedCell] ! 262: stringValue]]; ! 263: contents = [[[adaptor model] entityNamed: selectedEntity] attributes]; ! 264: entity = nil; ! 265: ! 266: entryCount = [contents count]; ! 267: [aMatrix renewRows: entryCount cols: 1]; ! 268: ! 269: enumerator = [contents objectEnumerator]; ! 270: while ((current = [enumerator nextObject]) != nil) { ! 271: ! 272: [[[aMatrix cellAt: iterator++ : 0] ! 273: setStringValue: [[(EOAttribute *)current name] cString]] ! 274: setLeaf: YES]; ! 275: } ! 276: return entryCount; ! 277: } ! 278: ! 279: /*---------------------------------------------------------------------- ! 280: * The main entity attribute browser with two columns. One selects the ! 281: * entity for the query the other the attributes to be selected. Note ! 282: * that since we're using the EODatabaseAdaptor (instead of the ! 283: * EOChannelAdaptor, we actually select the entire object, but only these ! 284: * fields will be associated with the tableView. ! 285: * ! 286: * Reset query qualifiers for new entity ! 287: *--------------------------------------------------------------------*/ ! 288: [qualifier autorelease]; ! 289: [qualifierText setStringValue: ""]; ! 290: [queryText setStringValue: ""]; ! 291: ! 292: if (aColumn == 0) ! 293: contents = [[adaptor model] entities]; ! 294: ! 295: else if (aColumn == 1) { ! 296: id selectedEntity; ! 297: ! 298: selectedEntity = [NSString stringWithCString: ! 299: [(Cell *)[[aBrowser matrixInColumn:0] selectedCell] stringValue]]; ! 300: contents = [[[adaptor model] entityNamed: selectedEntity] attributes]; ! 301: entity = nil; ! 302: } ! 303: ! 304: entryCount = [contents count]; ! 305: [aMatrix renewRows: entryCount cols: 1]; ! 306: ! 307: enumerator = [contents objectEnumerator]; ! 308: while ((current = [enumerator nextObject]) != nil) { ! 309: ! 310: [[[aMatrix cellAt: iterator : 0] ! 311: setStringValue: [[(EOEntity *)current name] cString]] ! 312: setLeaf: aColumn == 1 ]; ! 313: iterator++; ! 314: } ! 315: ! 316: if (aColumn == 1) ! 317: [[qualifierBrowser loadColumnZero] display]; ! 318: ! 319: return entryCount; ! 320: } ! 321: ! 322: ! 323: - selectOperation:sender ! 324: { ! 325: int selectedOp; ! 326: id opString = nil; ! 327: int selection; ! 328: ! 329: selectedOp = [[qualifierOperation selectedCell] tag]; ! 330: ! 331: if (selectedOp == 0) opString = @"<"; ! 332: else if (selectedOp == 1) opString = @"<="; ! 333: else if (selectedOp == 2) opString = @">"; ! 334: else if (selectedOp == 3) opString = @">="; ! 335: else if (selectedOp == 4) opString = @"="; ! 336: else if (selectedOp == 5) opString = @"<>"; ! 337: ! 338: ! 339: [qualifierText setStringValue: ! 340: [[NSString stringWithFormat:@"%s%s ", ! 341: [(TextField *)qualifierText stringValue], ! 342: [opString cString]] cString]]; ! 343: ! 344: selection = strlen([(TextField *)qualifierText stringValue]); ! 345: [qualifierText selectText:nil]; ! 346: ! 347: ! 348: return self; ! 349: } ! 350: ! 351: ! 352: - selectAttribute:sender ! 353: { ! 354: id selectedCell; ! 355: EOAttribute *newAttribute; ! 356: ! 357: if (entity == nil) { ! 358: const char *entityName; ! 359: ! 360: entityName = [(Cell *)[[browser matrixInColumn: 0] ! 361: selectedCell] stringValue]; ! 362: entity = [[adaptor model] entityNamed: ! 363: [NSString stringWithCString: entityName]]; ! 364: } ! 365: ! 366: if ((selectedCell = [qualifierBrowser selectedCell])) { ! 367: id newString; ! 368: ! 369: newAttribute = [entity attributeNamed: ! 370: [NSString stringWithCString:[(Cell *)selectedCell stringValue]]]; ! 371: ! 372: /*---------------------------------------------------------------------- ! 373: * Get the name internal to the database; if it is a column, get the ! 374: * column name, otherwise, it is a complex value (a flattened attribute) ! 375: * so get the description. ! 376: *--------------------------------------------------------------------*/ ! 377: newString = [NSString stringWithFormat: @"%s%s ", ! 378: [(TextField *)qualifierText stringValue], ! 379: [newAttribute columnName] ? ! 380: [(NSString *)[newAttribute columnName] cString] : ! 381: [(NSString *)[newAttribute definition] cString]]; ! 382: ! 383: [qualifierText setStringValue: [newString cString]]; ! 384: [qualifierText selectText: nil]; ! 385: ! 386: } ! 387: ! 388: return self; ! 389: } ! 390: ! 391: ! 392: - replaceQualifier: sender ! 393: { ! 394: if (qualifier) [qualifier autorelease]; ! 395: ! 396: if (entity == nil) { ! 397: const char *entityName; ! 398: ! 399: entityName = [(Cell *)[[browser matrixInColumn: 0] ! 400: selectedCell] stringValue]; ! 401: if (! entityName) { ! 402: NXRunAlertPanel("Query Builder", ! 403: "A model file must be present before a query is possible.", ! 404: NULL, NULL, NULL); ! 405: return nil; ! 406: } ! 407: ! 408: entity = [[adaptor model] entityNamed: ! 409: [NSString stringWithCString: entityName]]; ! 410: } ! 411: ! 412: qualifier = [[EOQualifier allocWithZone:[self zone]] ! 413: initWithEntity:entity ! 414: qualifierFormat: [NSString stringWithCString: ! 415: [(TextField *)qualifierText stringValue]]]; ! 416: ! 417: if ([negator state]) [qualifier negate]; ! 418: ! 419: [negator setState: 0]; ! 420: [queryText setStringValue:[[qualifier contents] cString]]; ! 421: [qualifierText setStringValue:""]; ! 422: [qualifierText selectText: nil]; ! 423: [qualifierOperation selectCellAt:-1:-1]; ! 424: ! 425: ! 426: return self; ! 427: } ! 428: ! 429: ! 430: - appendAND: sender ! 431: { ! 432: id newQualifier; ! 433: ! 434: if (entity == nil) { ! 435: const char *entityName; ! 436: ! 437: entityName = [(Cell *)[[browser matrixInColumn: 0] ! 438: selectedCell] stringValue]; ! 439: if (! entityName) { ! 440: NXRunAlertPanel("Query Builder", ! 441: "A model file must be present before a query is possible.", ! 442: NULL, NULL, NULL); ! 443: return nil; ! 444: } ! 445: ! 446: entity = [[adaptor model] entityNamed: ! 447: [NSString stringWithCString: entityName]]; ! 448: } ! 449: ! 450: ! 451: newQualifier = [[EOQualifier allocWithZone:[self zone]] ! 452: initWithEntity:entity ! 453: qualifierFormat: [NSString stringWithCString: ! 454: [(TextField *)qualifierText stringValue]]]; ! 455: ! 456: /*---------------------------------------------------------------------- ! 457: * If the qualifier is to be negated... ! 458: *--------------------------------------------------------------------*/ ! 459: if ([negator state]) [newQualifier negate]; ! 460: ! 461: /*---------------------------------------------------------------------- ! 462: * AND the new qualifier with the previous one ! 463: *--------------------------------------------------------------------*/ ! 464: [qualifier conjoinWithQualifier: newQualifier]; ! 465: ! 466: [newQualifier autorelease]; ! 467: ! 468: [negator setState: 0]; ! 469: [queryText setStringValue:[[qualifier contents] cString]]; ! 470: [qualifierText setStringValue:""]; ! 471: [qualifierText selectText: nil]; ! 472: [qualifierOperation selectCellAt:-1:-1]; ! 473: ! 474: ! 475: return self; ! 476: } ! 477: ! 478: ! 479: - appendOR: sender ! 480: { ! 481: id newQualifier; ! 482: ! 483: if (entity == nil) { ! 484: const char *entityName; ! 485: ! 486: entityName = [(Cell *)[[browser matrixInColumn: 0] ! 487: selectedCell] stringValue]; ! 488: if (! entityName) { ! 489: NXRunAlertPanel("Query Builder", ! 490: "A model file must be present before a query is possible.", ! 491: NULL, NULL, NULL); ! 492: return nil; ! 493: } ! 494: ! 495: entity = [[adaptor model] entityNamed: ! 496: [NSString stringWithCString: entityName]]; ! 497: } ! 498: ! 499: ! 500: newQualifier = [[EOQualifier allocWithZone:[self zone]] ! 501: initWithEntity:entity ! 502: qualifierFormat: [NSString stringWithCString: ! 503: [(TextField *)qualifierText stringValue]]]; ! 504: ! 505: /*---------------------------------------------------------------------- ! 506: * If the qualifier is to be negated... ! 507: *--------------------------------------------------------------------*/ ! 508: if ([negator state]) [newQualifier negate]; ! 509: ! 510: /*---------------------------------------------------------------------- ! 511: * OR the new qualifier with the previous one. ! 512: *--------------------------------------------------------------------*/ ! 513: [qualifier disjoinWithQualifier: newQualifier]; ! 514: ! 515: [newQualifier autorelease]; ! 516: ! 517: [negator setState: 0]; ! 518: [queryText setStringValue:[[qualifier contents] cString]]; ! 519: [qualifierText setStringValue:""]; ! 520: [qualifierText selectText: nil]; ! 521: [qualifierOperation selectCellAt:-1:-1]; ! 522: ! 523: ! 524: return self; ! 525: } ! 526: ! 527: ! 528: - clearQualifier: sender ! 529: { ! 530: [qualifier autorelease]; ! 531: qualifier = nil; ! 532: [negator setState: 0]; ! 533: [queryText setStringValue:""]; ! 534: [qualifierText setStringValue:""]; ! 535: [qualifierText selectText:nil]; ! 536: [qualifierOperation selectCellAt:-1:-1]; ! 537: ! 538: return self; ! 539: } ! 540: ! 541: ! 542: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.