|
|
Sample Programs from NeXSTEP 3.3
/* BinderHanlder.m:
* You may freely copy, distribute, and reuse the code in this example.
* NeXT disclaims any warranty of any kind, expressed or implied, as to its
* fitness for any particular use.
*
* Written by: Mai Nguyen, NeXT Developer Support
*
*
*/
#import "BinderHandler.h"
#import <appkit/appkit.h>
#import <dbkit/dbkit.h>
#import <libc.h>
/* Define localized strings */
#define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when an operation has failed.")
#define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ")
#define OK NXLocalizedString("OK", NULL, "Okay to continue ")
#define NO_BINDER_OBJECT NXLocalizedString("Binder object not properly allocated", NULL, "Message given to user about a system problem.")
/* Global to be used by Author object */
static id myHandler;
@implementation BinderHandler
- appDidInit:sender
{
/* Connect to the Sybase Adaptor */
if ( myDatabase == nil ) {
myDatabase = [[DBDatabase alloc]init];
[myDatabase connectUsingAdaptor:"SybaseAdaptor"
andString:"sa@SYBASE/pubs"];
}
/* TESTING */
if (![myDatabase isConnected]) {
NXRunAlertPanel(FAILURE, CANNOT_CONNECT,OK, NULL, NULL);
return self;
}
[myDatabase setDelegate:self];
authorEntity = [myDatabase entityNamed:"authors"];
myHandler = self;
return self;
}
/* Stuff the binder with attributes from the authors table
*/
- initBinder
{
authorPrototype = [[Author alloc]init];
propertyList = [[List alloc] init];
containerList = [[List alloc] init];
myBinder = [[DBBinder alloc] init];
[myBinder setDatabase:myDatabase];
[myBinder setProperties:propertyList];
[myBinder setRecordPrototype:authorPrototype];
[myBinder associateRecordIvar:"first"
withProperty: [[DBExpression alloc] initForEntity:authorEntity
fromDescription:"au_fname"]];
[myBinder associateRecordIvar:"last"
withProperty: [[DBExpression alloc] initForEntity:authorEntity
fromDescription:"au_lname"]];
[myBinder associateRecordIvar:"address"
withProperty:[[DBExpression alloc] initForEntity:authorEntity
fromDescription:"address"]];
[myBinder associateRecordIvar:"state"
withProperty:[[DBExpression alloc] initForEntity:authorEntity
fromDescription:"state"]];
[myBinder associateRecordIvar:"zip"
withProperty:[[DBExpression alloc] initForEntity:authorEntity
fromDescription:"zip"]];
[myBinder associateRecordIvar:"phone"
withProperty:[[DBExpression alloc] initForEntity:authorEntity
fromDescription:"phone"]];
return self;
}
- free
{
if (authorPrototype)
[authorPrototype free];
if (propertyList)
[propertyList free];
if (containerList)
[containerList free];
if (myBinder)
[myBinder free];
return [super free];
}
- showAllRecords:sender
{
[self initBinder];
[self findAllRecords];
return self;
}
- findAllRecords
{
int recordCount;
if ( myBinder == nil ) {
NXRunAlertPanel(FAILURE, NO_BINDER_OBJECT,
"Binder object not properly allocated",
"OK", NULL, NULL);
return self;
}
[myBinder setContainer:containerList];
[myBinder select];
recordCount = [containerList count];
sprintf(buf, "\n------------------------\n");
[self appendToText:buf];
sprintf(buf, "%s\t%d\n", "Total Number of Records:", recordCount);
[self appendToText:buf];
[containerList makeObjectsPerform:@selector(printSelf)];
/* Make the input field first responder */
[lastNameField selectText:0];
return self;
}
/* Build a simple SQL query with DBQualifier and retrieve the data via the
* binder object.
*/
- findByName:sender
{
const char * name;
id aProp;
id theQualifier;
name = [lastNameField stringValue];
aProp = [[DBExpression alloc] initForEntity:authorEntity
fromDescription:"au_lname"];
theQualifier = [[DBQualifier allocFromZone:[self zone] ]
initForEntity:authorEntity
fromDescription:"%@ LIKE %s", aProp, name];
/* Must allocate a new binder object */
[self initBinder];
[myBinder setQualifier:theQualifier];
[self findAllRecords];
[aProp free];
[theQualifier free];
return self;
}
- findByState:sender
{
const char * state;
id aProp;
id theQualifier;
state = [stateField stringValue];
aProp = [[DBExpression alloc] initForEntity:authorEntity
fromDescription:"state"];
theQualifier = [[DBQualifier allocFromZone:[self zone] ]
initForEntity:authorEntity
fromDescription:"%@ LIKE %s", aProp, state];
/* Must allocate a new binder object with a different qualifier */
[self initBinder];
[myBinder setQualifier:theQualifier];
[self findAllRecords];
[aProp free];
[theQualifier free];
return self;
}
/* Appends the string passed to the doc view of the text view
*/
- appendToText:(const char *)newText
{
int currentLength = [theTextView textLength];
[theTextView setSel:currentLength :currentLength];
[theTextView replaceSel:newText];
[theTextView scrollSelToVisible];
return self;
}
/* DBDatabase delegate methods to log error messages and SQL queries */
- (BOOL)db:aDb willEvaluateString:(const unsigned char*)aString usingBinder:aBinder
{
[self appendToText:"\n << SQL Query:\n"];
[self appendToText:aString];
[self appendToText:" >> \n"];
return YES;
}
@end
@implementation Author
/* copyFromZone: is VERY important...this is how the prototype
* object is turned into records!
*/
- copyFromZone:(NXZone*)z
{
Author *theCopy = [[Author allocFromZone:z] init];
theCopy->first = NXCopyStringBufferFromZone(first, z);
theCopy->last = NXCopyStringBufferFromZone(last, z);
theCopy->address = NXCopyStringBufferFromZone(address, z);
theCopy->state = NXCopyStringBufferFromZone(state, z);
theCopy->zip = NXCopyStringBufferFromZone(zip, z);
theCopy->phone = NXCopyStringBufferFromZone(phone, z);
return theCopy;
}
/* Print data stored in the author object
*/
- printSelf
{
char buf[200];
sprintf(buf, "%s %s\n%s \t%s %s\n%s\n", first, last, address, state, zip,
phone);
if (myHandler != nil)
[myHandler appendToText: buf];
return self;
}
@end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.