|
|
1.1 ! root 1: /* BinderHanlder.m: ! 2: * You may freely copy, distribute, and reuse the code in this example. ! 3: * NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 4: * fitness for any particular use. ! 5: * ! 6: * Written by: Mai Nguyen, NeXT Developer Support ! 7: * ! 8: * ! 9: */ ! 10: ! 11: #import "BinderHandler.h" ! 12: #import <appkit/appkit.h> ! 13: #import <dbkit/dbkit.h> ! 14: #import <libc.h> ! 15: ! 16: /* Define localized strings */ ! 17: #define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when an operation has failed.") ! 18: #define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ") ! 19: #define OK NXLocalizedString("OK", NULL, "Okay to continue ") ! 20: #define NO_BINDER_OBJECT NXLocalizedString("Binder object not properly allocated", NULL, "Message given to user about a system problem.") ! 21: ! 22: /* Global to be used by Author object */ ! 23: static id myHandler; ! 24: @implementation BinderHandler ! 25: ! 26: - appDidInit:sender ! 27: { ! 28: /* Connect to the Sybase Adaptor */ ! 29: if ( myDatabase == nil ) { ! 30: myDatabase = [[DBDatabase alloc]init]; ! 31: [myDatabase connectUsingAdaptor:"SybaseAdaptor" ! 32: andString:"sa@SYBASE/pubs"]; ! 33: } ! 34: ! 35: /* TESTING */ ! 36: if (![myDatabase isConnected]) { ! 37: NXRunAlertPanel(FAILURE, CANNOT_CONNECT,OK, NULL, NULL); ! 38: return self; ! 39: } ! 40: [myDatabase setDelegate:self]; ! 41: authorEntity = [myDatabase entityNamed:"authors"]; ! 42: ! 43: myHandler = self; ! 44: ! 45: return self; ! 46: } ! 47: ! 48: /* Stuff the binder with attributes from the authors table ! 49: */ ! 50: - initBinder ! 51: { ! 52: ! 53: authorPrototype = [[Author alloc]init]; ! 54: propertyList = [[List alloc] init]; ! 55: containerList = [[List alloc] init]; ! 56: myBinder = [[DBBinder alloc] init]; ! 57: ! 58: [myBinder setDatabase:myDatabase]; ! 59: [myBinder setProperties:propertyList]; ! 60: [myBinder setRecordPrototype:authorPrototype]; ! 61: ! 62: [myBinder associateRecordIvar:"first" ! 63: withProperty: [[DBExpression alloc] initForEntity:authorEntity ! 64: fromDescription:"au_fname"]]; ! 65: [myBinder associateRecordIvar:"last" ! 66: withProperty: [[DBExpression alloc] initForEntity:authorEntity ! 67: fromDescription:"au_lname"]]; ! 68: [myBinder associateRecordIvar:"address" ! 69: withProperty:[[DBExpression alloc] initForEntity:authorEntity ! 70: fromDescription:"address"]]; ! 71: [myBinder associateRecordIvar:"state" ! 72: withProperty:[[DBExpression alloc] initForEntity:authorEntity ! 73: fromDescription:"state"]]; ! 74: [myBinder associateRecordIvar:"zip" ! 75: withProperty:[[DBExpression alloc] initForEntity:authorEntity ! 76: fromDescription:"zip"]]; ! 77: [myBinder associateRecordIvar:"phone" ! 78: withProperty:[[DBExpression alloc] initForEntity:authorEntity ! 79: fromDescription:"phone"]]; ! 80: ! 81: return self; ! 82: } ! 83: ! 84: ! 85: - free ! 86: { ! 87: if (authorPrototype) ! 88: [authorPrototype free]; ! 89: if (propertyList) ! 90: [propertyList free]; ! 91: if (containerList) ! 92: [containerList free]; ! 93: if (myBinder) ! 94: [myBinder free]; ! 95: ! 96: return [super free]; ! 97: } ! 98: ! 99: - showAllRecords:sender ! 100: { ! 101: [self initBinder]; ! 102: [self findAllRecords]; ! 103: ! 104: return self; ! 105: } ! 106: ! 107: ! 108: - findAllRecords ! 109: { ! 110: int recordCount; ! 111: ! 112: if ( myBinder == nil ) { ! 113: NXRunAlertPanel(FAILURE, NO_BINDER_OBJECT, ! 114: "Binder object not properly allocated", ! 115: "OK", NULL, NULL); ! 116: return self; ! 117: } ! 118: ! 119: [myBinder setContainer:containerList]; ! 120: [myBinder select]; ! 121: ! 122: recordCount = [containerList count]; ! 123: sprintf(buf, "\n------------------------\n"); ! 124: [self appendToText:buf]; ! 125: sprintf(buf, "%s\t%d\n", "Total Number of Records:", recordCount); ! 126: [self appendToText:buf]; ! 127: [containerList makeObjectsPerform:@selector(printSelf)]; ! 128: /* Make the input field first responder */ ! 129: [lastNameField selectText:0]; ! 130: return self; ! 131: } ! 132: ! 133: ! 134: /* Build a simple SQL query with DBQualifier and retrieve the data via the ! 135: * binder object. ! 136: */ ! 137: - findByName:sender ! 138: { ! 139: const char * name; ! 140: id aProp; ! 141: id theQualifier; ! 142: ! 143: name = [lastNameField stringValue]; ! 144: ! 145: aProp = [[DBExpression alloc] initForEntity:authorEntity ! 146: fromDescription:"au_lname"]; ! 147: theQualifier = [[DBQualifier allocFromZone:[self zone] ] ! 148: initForEntity:authorEntity ! 149: fromDescription:"%@ LIKE %s", aProp, name]; ! 150: ! 151: /* Must allocate a new binder object */ ! 152: [self initBinder]; ! 153: [myBinder setQualifier:theQualifier]; ! 154: [self findAllRecords]; ! 155: [aProp free]; ! 156: [theQualifier free]; ! 157: return self; ! 158: } ! 159: ! 160: ! 161: - findByState:sender ! 162: { ! 163: const char * state; ! 164: id aProp; ! 165: id theQualifier; ! 166: ! 167: ! 168: state = [stateField stringValue]; ! 169: ! 170: aProp = [[DBExpression alloc] initForEntity:authorEntity ! 171: fromDescription:"state"]; ! 172: theQualifier = [[DBQualifier allocFromZone:[self zone] ] ! 173: initForEntity:authorEntity ! 174: fromDescription:"%@ LIKE %s", aProp, state]; ! 175: ! 176: /* Must allocate a new binder object with a different qualifier */ ! 177: [self initBinder]; ! 178: [myBinder setQualifier:theQualifier]; ! 179: [self findAllRecords]; ! 180: [aProp free]; ! 181: [theQualifier free]; ! 182: return self; ! 183: } ! 184: ! 185: ! 186: /* Appends the string passed to the doc view of the text view ! 187: */ ! 188: - appendToText:(const char *)newText ! 189: { ! 190: int currentLength = [theTextView textLength]; ! 191: [theTextView setSel:currentLength :currentLength]; ! 192: [theTextView replaceSel:newText]; ! 193: [theTextView scrollSelToVisible]; ! 194: return self; ! 195: } ! 196: ! 197: ! 198: /* DBDatabase delegate methods to log error messages and SQL queries */ ! 199: ! 200: - (BOOL)db:aDb willEvaluateString:(const unsigned char*)aString usingBinder:aBinder ! 201: { ! 202: [self appendToText:"\n << SQL Query:\n"]; ! 203: [self appendToText:aString]; ! 204: [self appendToText:" >> \n"]; ! 205: return YES; ! 206: } ! 207: ! 208: @end ! 209: ! 210: @implementation Author ! 211: ! 212: /* copyFromZone: is VERY important...this is how the prototype ! 213: * object is turned into records! ! 214: */ ! 215: ! 216: - copyFromZone:(NXZone*)z ! 217: { ! 218: Author *theCopy = [[Author allocFromZone:z] init]; ! 219: theCopy->first = NXCopyStringBufferFromZone(first, z); ! 220: theCopy->last = NXCopyStringBufferFromZone(last, z); ! 221: theCopy->address = NXCopyStringBufferFromZone(address, z); ! 222: theCopy->state = NXCopyStringBufferFromZone(state, z); ! 223: theCopy->zip = NXCopyStringBufferFromZone(zip, z); ! 224: theCopy->phone = NXCopyStringBufferFromZone(phone, z); ! 225: return theCopy; ! 226: } ! 227: ! 228: ! 229: /* Print data stored in the author object ! 230: */ ! 231: - printSelf ! 232: { ! 233: char buf[200]; ! 234: ! 235: sprintf(buf, "%s %s\n%s \t%s %s\n%s\n", first, last, address, state, zip, ! 236: phone); ! 237: if (myHandler != nil) ! 238: [myHandler appendToText: buf]; ! 239: return self; ! 240: } ! 241: ! 242: ! 243: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.