|
|
Sample Programs from NeXSTEP 3.3
/*--------------------------------------------------------------------------
*
* 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 autorelease];
adaptor = [[EOAdaptor adaptorWithModel: model] retain];
[model autorelease];
/*----------------------------------------------------------------------
* set up database pieces to allow transactions, qualifiers, etc.
*--------------------------------------------------------------------*/
if (database) [database autorelease];
database = [[EODatabase allocWithZone: [self zone]]
initWithAdaptor: adaptor];
if (dbContext) [dbContext autorelease];
dbContext = [[EODatabaseContext alloc] initWithDatabase: database];
if (dbChannel) [dbChannel autorelease];
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 autorelease];
dataSource = [[EODatabaseDataSource allocWithZone:[self zone]]
initWithDatabaseChannel:dbChannel
entityNamed:[anEntity name]];
/*----------------------------------------------------------------------
* 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 autorelease];
}
/*----------------------------------------------------------------------
* 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]) != nil) {
[[[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 autorelease];
[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]) != nil) {
[[[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 autorelease];
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 autorelease];
[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 autorelease];
[negator setState: 0];
[queryText setStringValue:[[qualifier contents] cString]];
[qualifierText setStringValue:""];
[qualifierText selectText: nil];
[qualifierOperation selectCellAt:-1:-1];
return self;
}
- clearQualifier: sender
{
[qualifier autorelease];
qualifier = nil;
[negator setState: 0];
[queryText setStringValue:""];
[qualifierText setStringValue:""];
[qualifierText selectText:nil];
[qualifierOperation selectCellAt:-1:-1];
return self;
}
@end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.