This is QueryController.m in view mode; [Download] [Up]
/*-------------------------------------------------------------------------- * * You may freely copy, distribute, and reuse the code in this example. * SHL Systemhouse disclaims any warranty of any kind, expressed or * implied, as to its fitness for any particular use. * * * QueryController * * Inherits From: NSObject * * Conforms To: None. * * Declared In: QueryController.h * * *------------------------------------------------------------------------*/ #import "QueryController.h" #import "EOQualifierContentsCategory.h" @implementation QueryController /*-------------------------------------------------------------------------- * Model file reading and preparation for query building *------------------------------------------------------------------------*/ - _setUpForModelFile: (NSString *)aFilepath { id model = [[EOModel allocWithZone: NULL] initWithContentsOfFile: aFilepath]; /*---------------------------------------------------------------------- * create adaptor with specifics contained in the model (server, etc.) *--------------------------------------------------------------------*/ if (adaptor) [adaptor release]; adaptor = [[EOAdaptor adaptorWithModel: model] retain]; [model release]; /*---------------------------------------------------------------------- * set up database pieces to allow transactions, qualifiers, etc. *--------------------------------------------------------------------*/ if (database) [database release]; database = [[EODatabase allocWithZone: [self zone]] initWithAdaptor: adaptor]; if (dbContext) [dbContext release]; dbContext = [[EODatabaseContext alloc] initWithDatabase: database]; if (dbChannel) [dbChannel release]; dbChannel = [[EODatabaseChannel alloc] initWithDatabaseContext: dbContext]; /*---------------------------------------------------------------------- * open the channel and turn on debug to see SQL in console *--------------------------------------------------------------------*/ if (! [dbChannel openChannel]) { NSLog(@"database channel could not be opened."); } [[dbChannel adaptorChannel] setDebugEnabled:YES]; entity = nil; [self clearQualifier:nil]; [[qualifierBrowser matrixInColumn:0] renewRows:0 cols:0]; [[qualifierBrowser matrixInColumn:0] sizeToCells]; [qualifierBrowser display]; return self; } /*-------------------------------------------------------------------------- * IconWell delegate method *------------------------------------------------------------------------*/ - dragSource:dragSource didDropOnIconWell:sender { [modelPath setStringValue: (const char *)[sender path]]; [self _setUpForModelFile: [NSString stringWithCString: (char *)[sender path]]]; [[browser loadColumnZero] display]; [window makeKeyAndOrderFront: self]; return self; } /*-------------------------------------------------------------------------- * Application delegation *------------------------------------------------------------------------*/ - appDidInit: sender { qualifier = nil; dataSource = nil; controller = nil; dbContext = nil; dbChannel = nil; [qualifierOperation setEmptySelectionEnabled:YES]; [qualifierOperation selectCellAt:-1:-1]; [window makeKeyAndOrderFront: self]; return self; } /*-------------------------------------------------------------------------- * Query Actions *------------------------------------------------------------------------*/ - performQuery:sender { id selection = [[NSMutableArray allocWithZone:NULL] init]; id selectedCells = [[List alloc] init]; int countSelected, iterator; const char *cString; /*---------------------------------------------------------------------- * get attribute names to be selected and browsed *--------------------------------------------------------------------*/ [[browser matrixInColumn:1] getSelectedCells:selectedCells]; countSelected = [selectedCells count]; if (countSelected == 0) { [selectedCells free]; selectedCells = [[browser matrixInColumn:1] cellList]; countSelected = [selectedCells count]; } /*---------------------------------------------------------------------- * transfer info from a NS3.2 list to a NS3.3NSArray *--------------------------------------------------------------------*/ for (iterator = 0; iterator < countSelected; iterator++) { cString = [(Cell *)[selectedCells objectAt: iterator] stringValue]; [(NSMutableArray *)selection addObject: [NSString stringWithCString: cString]]; } /*---------------------------------------------------------------------- * assure current entity *--------------------------------------------------------------------*/ cString = [(Cell *)[[browser matrixInColumn:0] selectedCell] stringValue]; entity = [[adaptor model] entityNamed: [NSString stringWithCString: cString]]; /*---------------------------------------------------------------------- * if qualifier is not defined, create an unqualified fetch. *--------------------------------------------------------------------*/ if (qualifier == nil) qualifier = [entity qualifier]; /*---------------------------------------------------------------------- * call method to handle fetch and reporting thru NXTableView *--------------------------------------------------------------------*/ [self fetchAndDisplay:selection inEntity:entity withQualifier:qualifier]; return self; } - (void) fetchAndDisplay:(NSArray *)attributes inEntity:(EOEntity *)anEntity withQualifier:(EOQualifier *)aQualifier { unsigned int count, iterator; [resultWindow disableDisplay]; /*---------------------------------------------------------------------- * if not the first query, we need to change dataSources. The entity * may be different from the previous query. *--------------------------------------------------------------------*/ if (dataSource) [dataSource release]; dataSource = [[EODatabaseDataSource allocWithZone: [self zone]] initWithEntity: anEntity databaseChannel: dbChannel]; /*---------------------------------------------------------------------- * get a new controller with the new dataSource *--------------------------------------------------------------------*/ controller = [[EOController allocWithZone: [self zone]] initWithDataSource: dataSource]; /*---------------------------------------------------------------------- * delete all current columns in the table view *--------------------------------------------------------------------*/ count = [resultTable columnCount]; for (iterator = count; iterator > 0; iterator--) [resultTable removeColumnAt: iterator-1]; [(NXTableView *)resultTable setDataSource:nil]; /*---------------------------------------------------------------------- * iterate through the desired select attributes and build columns for * each in the tableView. *--------------------------------------------------------------------*/ count = [attributes count]; for (iterator = 0; iterator < count; iterator ++) { id association; id attribute = [anEntity attributeNamed: [attributes objectAtIndex:iterator]]; [resultTable addColumn:attribute withTitle: [[(EOAttribute *)attribute name] cString]]; /*---------------------------------------------------------------------- * create a new association for each of these attribute/column pairs *--------------------------------------------------------------------*/ association = [[EOColumnAssociation allocWithZone: [self zone]] initWithController:controller key: [(EOAttribute *)attribute name] destination:[resultTable columnAt:iterator]]; [association setTableView:resultTable]; [controller addAssociation: association]; [association release]; } /*---------------------------------------------------------------------- * set the qualifier for the fetch. *--------------------------------------------------------------------*/ [dataSource setQualifier: aQualifier]; /*---------------------------------------------------------------------- * Start a transaction, do the fetch, rollback the transaction (a fetch * doesn't need to commit anything) have the values filled to the * tableView via the columnAssociations. *--------------------------------------------------------------------*/ [dbContext beginTransaction]; if (! [controller fetch]) NSLog(@"controller fetch failed."); [dbContext rollbackTransaction]; /*---------------------------------------------------------------------- * Redisplay everything... *--------------------------------------------------------------------*/ [resultWindow reenableDisplay]; [controller redisplay]; [resultWindow makeKeyAndOrderFront:self]; return; } - (int) browser:aBrowser fillMatrix:aMatrix inColumn:(int)aColumn { int iterator = 0, entryCount = 0; id contents = nil; id enumerator, current; /*---------------------------------------------------------------------- * Fill qualifier browser with the attributes of the selected entity; * this is the same list as in the second column of the first browser. *--------------------------------------------------------------------*/ if (aBrowser == qualifierBrowser) { id selectedEntity; iterator = 0; if ([browser selectedColumn] < 0) return 0; selectedEntity = [NSString stringWithCString: [(Cell *)[[browser matrixInColumn:0] selectedCell] stringValue]]; contents = [[[adaptor model] entityNamed: selectedEntity] attributes]; entity = nil; entryCount = [contents count]; [aMatrix renewRows: entryCount cols: 1]; enumerator = [contents objectEnumerator]; while (current = [enumerator nextObject]) { [[[aMatrix cellAt: iterator++ : 0] setStringValue: [[(EOAttribute *)current name] cString]] setLeaf: YES]; } return entryCount; } /*---------------------------------------------------------------------- * The main entity attribute browser with two columns. One selects the * entity for the query the other the attributes to be selected. Note * that since we're using the EODatabaseAdaptor (instead of the * EOChannelAdaptor, we actually select the entire object, but only these * fields will be associated with the tableView. * * Reset query qualifiers for new entity *--------------------------------------------------------------------*/ [qualifier release]; [qualifierText setStringValue: ""]; [queryText setStringValue: ""]; if (aColumn == 0) contents = [[adaptor model] entities]; else if (aColumn == 1) { id selectedEntity; selectedEntity = [NSString stringWithCString: [(Cell *)[[aBrowser matrixInColumn:0] selectedCell] stringValue]]; contents = [[[adaptor model] entityNamed: selectedEntity] attributes]; entity = nil; } entryCount = [contents count]; [aMatrix renewRows: entryCount cols: 1]; enumerator = [contents objectEnumerator]; while (current = [enumerator nextObject]) { [[[aMatrix cellAt: iterator : 0] setStringValue: [[(EOEntity *)current name] cString]] setLeaf: aColumn == 1 ]; iterator++; } if (aColumn == 1) [[qualifierBrowser loadColumnZero] display]; return entryCount; } - selectOperation:sender { int selectedOp; id opString = nil; int selection; selectedOp = [[qualifierOperation selectedCell] tag]; if (selectedOp == 0) opString = @"<"; else if (selectedOp == 1) opString = @"<="; else if (selectedOp == 2) opString = @">"; else if (selectedOp == 3) opString = @">="; else if (selectedOp == 4) opString = @"="; else if (selectedOp == 5) opString = @"<>"; [qualifierText setStringValue: [[NSString stringWithFormat:@"%s%s ", [(TextField *)qualifierText stringValue], [opString cString]] cString]]; selection = strlen([(TextField *)qualifierText stringValue]); [qualifierText selectText:nil]; return self; } - selectAttribute:sender { id selectedCell; EOAttribute *newAttribute; if (entity == nil) { const char *entityName; entityName = [(Cell *)[[browser matrixInColumn: 0] selectedCell] stringValue]; entity = [[adaptor model] entityNamed: [NSString stringWithCString: entityName]]; } if (selectedCell = [qualifierBrowser selectedCell]) { id newString; newAttribute = [entity attributeNamed: [NSString stringWithCString:[(Cell *)selectedCell stringValue]]]; /*---------------------------------------------------------------------- * Get the name internal to the database; if it is a column, get the * column name, otherwise, it is a complex value (a flattened attribute) * so get the description. *--------------------------------------------------------------------*/ newString = [NSString stringWithFormat: @"%s%s ", [(TextField *)qualifierText stringValue], [newAttribute columnName] ? [(NSString *)[newAttribute columnName] cString] : [(NSString *)[newAttribute definition] cString]]; [qualifierText setStringValue: [newString cString]]; [qualifierText selectText: nil]; } return self; } - replaceQualifier: sender { if (qualifier) [qualifier release]; if (entity == nil) { const char *entityName; entityName = [(Cell *)[[browser matrixInColumn: 0] selectedCell] stringValue]; if (! entityName) { NXRunAlertPanel("Query Builder", "A model file must be present before a query is possible.", NULL, NULL, NULL); return nil; } entity = [[adaptor model] entityNamed: [NSString stringWithCString: entityName]]; } qualifier = [[EOQualifier allocWithZone:[self zone]] initWithEntity:entity qualifierFormat: [NSString stringWithCString: [(TextField *)qualifierText stringValue]]]; if ([negator state]) [qualifier negate]; [negator setState: 0]; [queryText setStringValue:[[qualifier contents] cString]]; [qualifierText setStringValue:""]; [qualifierText selectText: nil]; [qualifierOperation selectCellAt:-1:-1]; return self; } - appendAND: sender { id newQualifier; if (entity == nil) { const char *entityName; entityName = [(Cell *)[[browser matrixInColumn: 0] selectedCell] stringValue]; if (! entityName) { NXRunAlertPanel("Query Builder", "A model file must be present before a query is possible.", NULL, NULL, NULL); return nil; } entity = [[adaptor model] entityNamed: [NSString stringWithCString: entityName]]; } newQualifier = [[EOQualifier allocWithZone:[self zone]] initWithEntity:entity qualifierFormat: [NSString stringWithCString: [(TextField *)qualifierText stringValue]]]; /*---------------------------------------------------------------------- * If the qualifier is to be negated... *--------------------------------------------------------------------*/ if ([negator state]) [newQualifier negate]; /*---------------------------------------------------------------------- * AND the new qualifier with the previous one *--------------------------------------------------------------------*/ [qualifier conjoinWithQualifier: newQualifier]; [newQualifier release]; [negator setState: 0]; [queryText setStringValue:[[qualifier contents] cString]]; [qualifierText setStringValue:""]; [qualifierText selectText: nil]; [qualifierOperation selectCellAt:-1:-1]; return self; } - appendOR: sender { id newQualifier; if (entity == nil) { const char *entityName; entityName = [(Cell *)[[browser matrixInColumn: 0] selectedCell] stringValue]; if (! entityName) { NXRunAlertPanel("Query Builder", "A model file must be present before a query is possible.", NULL, NULL, NULL); return nil; } entity = [[adaptor model] entityNamed: [NSString stringWithCString: entityName]]; } newQualifier = [[EOQualifier allocWithZone:[self zone]] initWithEntity:entity qualifierFormat: [NSString stringWithCString: [(TextField *)qualifierText stringValue]]]; /*---------------------------------------------------------------------- * If the qualifier is to be negated... *--------------------------------------------------------------------*/ if ([negator state]) [newQualifier negate]; /*---------------------------------------------------------------------- * OR the new qualifier with the previous one. *--------------------------------------------------------------------*/ [qualifier disjoinWithQualifier: newQualifier]; [newQualifier release]; [negator setState: 0]; [queryText setStringValue:[[qualifier contents] cString]]; [qualifierText setStringValue:""]; [qualifierText selectText: nil]; [qualifierOperation selectCellAt:-1:-1]; return self; } - clearQualifier: sender { [qualifier release]; qualifier = nil; [negator setState: 0]; [queryText setStringValue:""]; [qualifierText setStringValue:""]; [qualifierText selectText:nil]; [qualifierOperation selectCellAt:-1:-1]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.