home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------
- *
- * 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
-