Tag: cws_src680_macaddressbook01 User: cremlae Date: 2007-07-15 01:57:05+0000 Modified: dba/connectivity/source/drivers/macab/MacabRecords.cxx dba/connectivity/source/drivers/macab/MacabRecords.hxx dba/connectivity/source/drivers/macab/MacabRecord.cxx dba/connectivity/source/drivers/macab/MacabRecord.hxx dba/connectivity/source/drivers/macab/MacabHeader.cxx dba/connectivity/source/drivers/macab/MacabGroup.cxx dba/connectivity/source/drivers/macab/MacabAddressBook.cxx
Log: #i79612# Added comments to several files in connectivity/source/macab File Changes: Directory: /dba/connectivity/source/drivers/macab/ ================================================== File [changed]: MacabRecords.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabRecords.cxx?r1=1.1.2.3&r2=1.1.2.4 Delta lines: +240 -53 ---------------------- --- MacabRecords.cxx 2007-07-13 20:02:32+0000 1.1.2.3 +++ MacabRecords.cxx 2007-07-15 01:56:55+0000 1.1.2.4 @@ -4,9 +4,9 @@ * * $RCSfile: MacabRecords.cxx,v $ * - * $Revision: 1.1.2.3 $ + * $Revision: 1.1.2.4 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 20:02:32 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -65,28 +65,44 @@ // ------------------------------------------------------------------------- MacabRecords::MacabRecords(const ABAddressBookRef _addressBook, MacabHeader *_header, MacabRecord **_records, sal_Int32 _numRecords) { + /* Variables passed in... */ header = _header; recordsSize = _numRecords; currentRecord = _numRecords; records = _records; addressBook = _addressBook; + + /* Default variables... */ recordType = kABPersonRecordType; + + /* Variables constructed... */ bootstrap_CF_types(); bootstrap_requiredProperties(); } // ------------------------------------------------------------------------- +/* Creates a MacabRecords from another: copies the length, name, and + * address book of the original, but the header or the records themselves. + * The idea is that the only reason to copy a MacabRecords is to create + * a filtered version of it, which can have the same length (to avoid + * resizing) and will work from the same base addressbook, but might have + * entirey different values and even (possibly in the future) a different + * header. + */ MacabRecords::MacabRecords(const MacabRecords *_copy) { + /* Variables passed in... */ recordsSize = _copy->recordsSize; addressBook = _copy->addressBook; m_sName = _copy->m_sName; + /* Default variables... */ currentRecord = 0; header = NULL; records = new MacabRecord *[recordsSize]; recordType = kABPersonRecordType; + /* Variables constructed... */ bootstrap_CF_types(); bootstrap_requiredProperties(); } @@ -94,12 +110,17 @@ // ------------------------------------------------------------------------- MacabRecords::MacabRecords(const ABAddressBookRef _addressBook) { + /* Variables passed in... */ + addressBook = _addressBook; + + /* Default variables... */ recordsSize = 0; currentRecord = 0; records = NULL; header = NULL; - addressBook = _addressBook; recordType = kABPersonRecordType; + + /* Variables constructed... */ bootstrap_CF_types(); bootstrap_requiredProperties(); } @@ -108,6 +129,11 @@ void MacabRecords::initialize() { + /* Make sure everything is NULL before initializing. (We usually just + * initialize after we use the constructor that takes only a + * MacabAddressBook, so these variables will most likely already be + * NULL. + */ if(records != NULL) { sal_Int32 i; @@ -121,6 +147,9 @@ if(header != NULL) delete header; + /* We can handle both default record Address Book record types in + * this method, though only kABPersonRecordType is ever used. + */ CFArrayRef allRecords; if(CFStringCompare(recordType, kABPersonRecordType, 0) == kCFCompareEqualTo) allRecords = ABCopyArrayOfAllPeople(addressBook); @@ -132,8 +161,10 @@ recordsSize = (sal_Int32) CFArrayGetCount(allRecords); records = new MacabRecord *[recordsSize]; + /* First, we create the header... */ header = createHeaderForRecordType(allRecords, recordType); + /* Then, we create each of the records... */ for(i = 0; i < recordsSize; i++) { record = (ABRecordRef) CFArrayGetValueAtIndex(allRecords, i); @@ -164,9 +195,16 @@ } // ------------------------------------------------------------------------- +/* Inserts a MacabRecord at a given location. If there is already a + * MacabRecord at that location, return it. + */ MacabRecord *MacabRecords::insertRecord(MacabRecord *_newRecord, const sal_Int32 _location) { MacabRecord *oldRecord; + + /* If the location is greater than the current allocated size of this + * MacabRecords, allocate more space. + */ if(_location >= recordsSize) { sal_Int32 i; @@ -178,6 +216,10 @@ records = newRecordsArray; } + /* Remember: currentRecord refers to one above the highest existing + * record (i.e., it refers to where to place the next record if a + * location is not given). + */ if(_location >= currentRecord) currentRecord = _location+1; @@ -187,6 +229,7 @@ } // ------------------------------------------------------------------------- +/* Insert a record at the next available place. */ void MacabRecords::insertRecord(MacabRecord *_newRecord) { insertRecord(_newRecord, currentRecord); @@ -300,25 +343,63 @@ } // ------------------------------------------------------------------------- +/* Create the header for a given record type and a given array of records. + * Because the array of records and the record type are given, if you want + * to, you can run this method on the members of a group, or on any other + * filtered list of people and get a header relevant to them (e.g., if + * they only have home addresses, the work address fields won't show up). + */ MacabHeader *MacabRecords::createHeaderForRecordType(const CFArrayRef _records, const CFStringRef _recordType) const { + /* We have two types of properties for a given record type, nonrequired + * and required. Required properties are ones that will show up whether + * or not they are empty. Nonrequired properties will only show up if + * at least one record in the set has that property filled. The reason + * is that some properties, like the kABTitleProperty are required by + * the mail merge wizard (in module sw) but are by default not shown in + * the Mac OS X address book, so they would be weeded out at this stage + * and not shown if they were not required. + * + * Note: with the addition of required properties, I am not sure that + * this method still works for kABGroupRecordType (since the required + * properites are all for kABPersonRecordType). + * + * Note: required properties are constructed in the method + * bootstrap_requiredProperties() (above). + */ CFArrayRef allProperties = ABCopyArrayOfPropertiesForRecordType(addressBook, _recordType); CFStringRef *nonRequiredProperties; - ABRecordRef record; sal_Int32 numRecords = (sal_Int32) CFArrayGetCount(_records); sal_Int32 numProperties = (sal_Int32) CFArrayGetCount(allProperties); - sal_Int32 i, j, k; - CFStringRef property; + sal_Int32 numNonRequiredProperties = numProperties - numRequiredProperties; + + /* While searching through the properties for required properties, these + * sal_Bools will keep track of what we have found. + */ + sal_Bool bFoundProperty; + sal_Bool bFoundRequiredProperties[numRequiredProperties]; + + + /* We have three MacabHeaders: headerDataForProperty is where we + * store the result of createHeaderForProperty(), which return a + * MacabHeader for a single property. lcl_header is where we store + * the MacabHeader that we are constructing. And, nonRequiredHeader + * is where we construct the MacabHeader for non-required properties, + * so that we can sort them before adding them to lcl_header. + */ MacabHeader *headerDataForProperty; MacabHeader *lcl_header = new MacabHeader(); MacabHeader *nonRequiredHeader = new MacabHeader(); - sal_Int32 numNonRequiredProperties = numProperties - numRequiredProperties; - sal_Bool bFoundProperty; - sal_Bool bFoundRequiredProperties[numRequiredProperties]; + /* Other variables... */ + sal_Int32 i, j, k; + ABRecordRef record; + CFStringRef property; + + + /* Allocate and initialize... */ nonRequiredProperties = new CFStringRef[numNonRequiredProperties]; k = 0; - for(i = 0; i < numRequiredProperties; i++) bFoundRequiredProperties[i] = sal_False; @@ -339,6 +420,7 @@ if(bFoundProperty == sal_False) { + /* If we have found too many non-required properties */ if(k == numNonRequiredProperties) { k++; // so that the OSL_ENSURE below fails @@ -354,7 +436,7 @@ // we also test later. OSL_ENSURE(k == numNonRequiredProperties, "MacabRecords::createHeaderForRecordType: Found an unexpected number of non-required properties"); - /* Fill in required headers first... */ + /* Fill the header with required properties first... */ for(i = 0; i < numRequiredProperties; i++) { if(bFoundRequiredProperties[i] == sal_True) @@ -389,13 +471,11 @@ } } - /* And now, non-required ones... */ + /* And now, non-required properties... */ for(i = 0; i < numRecords; i++) { - /* This is the record */ record = (ABRecordRef) CFArrayGetValueAtIndex(_records, i); - /* Go through the properties array... */ for(j = 0; j < numNonRequiredProperties; j++) { property = nonRequiredProperties[j]; @@ -407,7 +487,7 @@ } } - } // end of for loop through records + } nonRequiredHeader->sortRecord(); (*lcl_header) += nonRequiredHeader; @@ -420,6 +500,10 @@ } // ------------------------------------------------------------------------- +/* Create a header for a single property. Basically, this method gets + * the property's value and type and then calls another method of + * the same name to do the dirty work. + */ MacabHeader *MacabRecords::createHeaderForProperty(const ABRecordRef _record, const CFStringRef _propertyName, const CFStringRef _recordType, const sal_Bool _isPropertyRequired) const { // local variables @@ -443,6 +527,10 @@ } // ------------------------------------------------------------------------- +/* Create a header for a single property. This method is recursive + * because a single property might contain several sub-properties that + * we also want to treat singly. + */ MacabHeader *MacabRecords::createHeaderForProperty(const ABPropertyType _propertyType, const CFTypeRef _propertyValue, const CFStringRef _propertyName) const { macabfield **headerNames = NULL; @@ -450,6 +538,7 @@ switch(_propertyType) { + /* Scalars */ case kABStringProperty: case kABRealProperty: case kABIntegerProperty: @@ -461,6 +550,7 @@ headerNames[0]->type = _propertyType; break; + /* Multi-scalars */ case kABMultiIntegerProperty: case kABMultiDateProperty: case kABMultiStringProperty: @@ -484,10 +574,11 @@ headerNames = new macabfield *[multiLength]; multiPropertyString = CFStringToOUString(_propertyName); - /* Go through each entry... */ + /* Go through each element, and - since each element is a scalar - + * just create a new macabfield for it. + */ for(i = 0; i < multiLength; i++) { - /* label */ multiLabel = ABMultiValueCopyLabelAtIndex((ABMutableMultiValueRef) _propertyValue, i); multiLabelString = CFStringToOUString(multiLabel); CFRelease(multiLabel); @@ -499,6 +590,7 @@ } break; + /* Multi-array or dictionary */ case kABMultiArrayProperty: case kABMultiDictionaryProperty: /* For non-scalars, we can only get more information if the property @@ -507,8 +599,17 @@ if(_propertyValue != NULL) { sal_Int32 i,j,k; + + // Total number of multi-array or multi-dictionary elements. sal_Int32 multiLengthFirstLevel = ABMultiValueCount((ABMutableMultiValueRef) _propertyValue); + + /* Total length, including the length of each element (e.g., if + * this multi-dictionary contains three dictionaries, and each + * dictionary has four elements, this variable will be twelve, + * whereas multiLengthFirstLevel will be three. + */ sal_Int32 multiLengthSecondLevel = 0; + CFStringRef multiLabel; CFTypeRef multiValue; ::rtl::OUString multiLabelString; @@ -518,7 +619,12 @@ multiPropertyString = CFStringToOUString(_propertyName); - /* Go through each entry... */ + /* Go through each element - since each element can really + * contain anything, we run this method again on each element + * and store the resulting MacabHeader (in the multiHeaders + * array). Then, all we'll have to do is combine the MacabHeaders + * into a single one. + */ for(i = 0; i < multiLengthFirstLevel; i++) { /* label */ @@ -542,6 +648,11 @@ CFRelease(multiValue); } + /* We now have enough information to create our final MacabHeader. + * We go through each field of each header and add it to the + * headerNames array (which is what is used below to construct + * the MacabHeader we return). + */ length = multiLengthSecondLevel; headerNames = new macabfield *[multiLengthSecondLevel]; @@ -562,6 +673,7 @@ } break; + /* Dictionary */ case kABDictionaryProperty: /* For non-scalars, we can only get more information if the property * actually exists. @@ -570,23 +682,38 @@ { /* Assume all keys are strings */ sal_Int32 numRecords = (sal_Int32) CFDictionaryGetCount((CFDictionaryRef) _propertyValue); + + /* The only method for getting info out of a CFDictionary, of both + * keys and values, is to all of them all at once, so these + * variables will hold them. + */ CFStringRef *dictKeys; CFTypeRef *dictValues; + + sal_Int32 i,j,k; ::rtl::OUString dictKeyString, propertyNameString; ABPropertyType dictType; - sal_Int32 i,j,k; MacabHeader **dictHeaders = new MacabHeader *[numRecords]; ::rtl::OUString dictLabelString; CFStringRef dictLabel; + /* Get the keys and values */ dictKeys = (CFStringRef *) malloc(sizeof(CFStringRef)*numRecords); dictValues = (CFTypeRef *) malloc(sizeof(CFTypeRef)*numRecords); - CFDictionaryGetKeysAndValues((CFDictionaryRef) _propertyValue, (const void **) dictKeys, (const void **) dictValues); propertyNameString = CFStringToOUString(_propertyName); length = 0; + /* Go through each element - assuming that the key is a string but + * that the value could be anything. Since the value could be + * anything, we can't assume that it is scalar (it could even be + * another dictionary), so we attempt to get its type using + * the method getABTypeFromCFType and then run this method + * recursively on that element, storing the MacabHeader that + * results. Then, we just combine all of the MacabHeaders into + * one. + */ for(i = 0; i < numRecords; i++) { dictType = (ABPropertyType) getABTypeFromCFType( CFGetTypeID(dictValues[i]) ); @@ -600,6 +727,10 @@ CFRelease(dictLabel); } + /* Combine all of the macabfields in each MacabHeader into the + * headerNames array, which (at the end of this method) is used + * to create the MacabHeader that is returned. + */ headerNames = new macabfield *[length]; for(i = 0, j = 0, k = 0; i < length; i++,k++) { @@ -621,6 +752,7 @@ } break; + /* Array */ case kABArrayProperty: /* For non-scalars, we can only get more information if the property * actually exists. @@ -637,6 +769,15 @@ CFStringRef arrLabel; length = 0; + /* Go through each element - since the elements here do not have + * unique keys like the ones in dictionaries, we create a unique + * key out of the id of the element in the array (the first + * element gets a 0 plopped onto the end of it, the second a 1... + * As with dictionaries, the elements could be anything, including + * another array, so we have to run this method recursively on + * each element, storing the resulting MacabHeader into an array, + * which we then combine into one MacabHeader that is returned. + */ for(i = 0; i < arrLength; i++) { arrValue = (CFTypeRef) CFArrayGetValueAtIndex( (CFArrayRef) _propertyValue, i); @@ -672,6 +813,13 @@ break; } + + /* If we succeeded at adding elements to the headerNames array, then + * length will no longer be 0. If it is, create a new MacabHeader + * out of the headerNames (after weeding out duplicate headers), and + * then return the result. If the length is still 0, return NULL: we + * failed to create a MacabHeader out of this property. + */ if(length != 0) { manageDuplicateHeaders(headerNames, length); @@ -716,16 +864,30 @@ } // ------------------------------------------------------------------------- +/* Create a MacabRecord out of an ABRecord, using a given MacabHeader and + * the record's type. We go through each property for this record type + * then process it much like we processed the header (above), with two + * exceptions: if we come upon something not in the header, we ignore it + * (it's something we don't want to add), and once we find a corresponding + * location in the header, we store the property and the property type in + * a macabfield. (For the header, we stored the property type and the name + * of the property as a CFString.) + */ MacabRecord *MacabRecords::createMacabRecord(const ABRecordRef _abrecord, const MacabHeader *_header, const CFStringRef _recordType) const { + /* The new record that we will create... */ MacabRecord *macabRecord = new MacabRecord(_header->getSize()); - sal_Int32 i; + CFArrayRef recordProperties = ABCopyArrayOfPropertiesForRecordType(addressBook, _recordType); sal_Int32 numProperties = (sal_Int32) CFArrayGetCount(recordProperties); - CFStringRef propertyName; - ::rtl::OUString propertyNameString; + + sal_Int32 i; + CFTypeRef propertyValue; ABPropertyType propertyType; + + CFStringRef propertyName; + ::rtl::OUString propertyNameString; for(i = 0; i < numProperties; i++) { propertyName = (CFStringRef) CFArrayGetValueAtIndex(recordProperties, i); @@ -747,6 +909,11 @@ } // ------------------------------------------------------------------------- +/* Inserts a given property into a MacabRecord. This method calls another + * method by the same name after getting the property type (it only + * receives the property value). It is called when we aren't given the + * property's type already. + */ void MacabRecords::insertPropertyIntoMacabRecord(MacabRecord *_abrecord, const MacabHeader *_header, const ::rtl::OUString _propertyName, const CFTypeRef _propertyValue) const { CFTypeID cf_type = CFGetTypeID(_propertyValue); @@ -757,10 +924,11 @@ } // ------------------------------------------------------------------------- +/* Inserts a given property into a MacabRecord. This method is recursive + * because properties can contain many sub-properties. + */ void MacabRecords::insertPropertyIntoMacabRecord(const ABPropertyType _propertyType, MacabRecord *_abrecord, const MacabHeader *_header, const ::rtl::OUString _propertyName, const CFTypeRef _propertyValue) const { - // local variables - /* If there is no value, return */ if(_propertyValue == NULL) return; @@ -768,11 +936,30 @@ /* The main switch statement */ switch(_propertyType) { + /* Scalars */ case kABStringProperty: case kABRealProperty: case kABIntegerProperty: case kABDateProperty: { + /* Only scalars actually insert a property into the MacabRecord. + * In all other cases, this method is called recursively until a + * scalar type, an error, or an unknown type are found. + * Because of that, the following checks only occur for this type. + * We store whether we have successfully placed this property + * into the MacabRecord (or whether an unrecoverable error occured). + * Then, we try over and over again to place the property into the + * record. There are three possible results: + * 1) Success! + * 2) There is already a property stored at the column of this name, + * in which case we have a duplicate header (see the method + * manageDuplicateHeaders()). If that is the case, we add an ID + * to the end of the column name in the same format as we do in + * manageDuplicateHeaders() and try again. + * 3) No column of this name exists in the header. In this case, + * there is nothing we can do: we have failed to place this + * property into the record. + */ sal_Bool bPlaced = sal_False; ::rtl::OUString columnName = ::rtl::OUString(_propertyName); sal_Int32 i = 1; @@ -784,13 +971,15 @@ bPlaced = sal_True; if(columnNumber != -1) { - // collision! + // collision! A property already exists here! if(_abrecord->get(columnNumber) != NULL) { bPlaced = sal_False; i++; columnName = ::rtl::OUString(_propertyName) + ::rtl::OUString::createFromAscii(" (") + ::rtl::OUString::valueOf(i) + ::rtl::OUString::createFromAscii(")"); } + + // success! else { _abrecord->insertAtColumn(_propertyValue, _propertyType, columnNumber); @@ -804,26 +993,24 @@ case kABArrayProperty: { /* An array is basically just a list of anything, so all we do - * is go through the array, and get the string representation - * of each element, and list them in a string, separated by - * commas. + * is go through the array, and rerun this method recursively + * on each element. */ sal_Int32 arrLength = (sal_Int32) CFArrayGetCount( (CFArrayRef) _propertyValue); sal_Int32 i; const void *arrValue; ::rtl::OUString newPropertyName; - /* Going through the array... */ + /* Going through each element... */ for(i = 0; i < arrLength; i++) { - /* Get the value */ arrValue = CFArrayGetValueAtIndex( (CFArrayRef) _propertyValue, i); newPropertyName = _propertyName + ::rtl::OUString::valueOf(i); insertPropertyIntoMacabRecord(_abrecord, _header, newPropertyName, arrValue); CFRelease(arrValue); } - } // end of block for the case of array type + } break; /* Dictionary */ @@ -831,30 +1018,32 @@ { /* A dictionary is basically a hashmap. Technically, it can * hold any object as a key and any object as a value. - * Traditionally, as far as I can tell, the key and value are - * both strings, but (to be safe) we don't assume that and - * run the version of getStringRepresentationOfPropertyValue - * that tries to find the type on its own on each key and - * each value. + * For our case, we assume that the key is a string (so that + * we can use the key to get the column name and match it against + * the header), but we don't assume anything about the value, so + * we run this method recursively (or, rather, we run the version + * of this method for when we don't know the object's type) until + * we hit a scalar value. */ sal_Int32 numRecords = (sal_Int32) CFDictionaryGetCount((CFDictionaryRef) _propertyValue); - CFStringRef *dictKeys; - CFTypeRef *dictValues; ::rtl::OUString dictKeyString; sal_Int32 i; ::rtl::OUString newPropertyName; + /* Unfortunately, the only way to get both keys and values out + * of a dictionary in Carbon is to get them all at once, so we + * do that. + */ + CFStringRef *dictKeys; + CFTypeRef *dictValues; dictKeys = (CFStringRef *) malloc(sizeof(CFStringRef)*numRecords); dictValues = (CFTypeRef *) malloc(sizeof(CFTypeRef)*numRecords); - CFDictionaryGetKeysAndValues((CFDictionaryRef) _propertyValue, (const void **) dictKeys, (const void **) dictValues); - - /* Going through the dictionary... */ + /* Going through each element... */ for(i = 0; i < numRecords; i++) { - /* Get the value */ dictKeyString = CFStringToOUString(dictKeys[i]); newPropertyName = _propertyName + ::rtl::OUString::createFromAscii(": ") + fixLabel(dictKeyString); insertPropertyIntoMacabRecord(_abrecord, _header, newPropertyName, dictValues[i]); @@ -862,7 +1051,7 @@ free(dictKeys); free(dictValues); - } // end of block for the case of dictionary type + } break; /* Multivalue */ @@ -873,18 +1062,16 @@ case kABMultiDataProperty: case kABMultiDictionaryProperty: case kABMultiArrayProperty: - { - /* All scalar multivalues are handled in the same way. Each entry is - * a label and a value. All labels are strings + /* All scalar multivalues are handled in the same way. Each element + * is a label and a value. All labels are strings * (kABStringProperty), and all values have the same type * (which is the type of the multivalue minus 255, or as - * Carbon's list of property types has it, minux 0x100. - * We just get the correct type, then go through each entry + * Carbon's list of property types has it, minus 0x100. + * We just get the correct type, then go through each element * and get the label and value and print them in a list. */ - /* variables local to this block */ sal_Int32 i; sal_Int32 multiLength = ABMultiValueCount((ABMutableMultiValueRef) _propertyValue); CFStringRef multiLabel; @@ -892,7 +1079,7 @@ ::rtl::OUString multiLabelString, newPropertyName; ABPropertyType multiType = (ABPropertyType) (ABMultiValuePropertyType((ABMutableMultiValueRef) _propertyValue) - 0x100); - /* Go through each entry... */ + /* Go through each element... */ for(i = 0; i < multiLength; i++) { /* Label and value */ @@ -906,8 +1093,8 @@ /* free our variables */ CFRelease(multiLabel); CFRelease(multiValue); - } // end of loop through each entry - } // end of block for the case of multivalue types + } + } break; /* Unhandled types */ File [changed]: MacabRecords.hxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabRecords.hxx?r1=1.1.2.3&r2=1.1.2.4 Delta lines: +21 -5 -------------------- --- MacabRecords.hxx 2007-07-13 20:02:33+0000 1.1.2.3 +++ MacabRecords.hxx 2007-07-15 01:56:55+0000 1.1.2.4 @@ -4,9 +4,9 @@ * * $RCSfile: MacabRecords.hxx,v $ * - * $Revision: 1.1.2.3 $ + * $Revision: 1.1.2.4 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 20:02:33 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -57,6 +57,9 @@ { namespace macab { + /* This struct is for converting CF types to AB types (Core Foundation + * types to Address Book types). + */ struct lcl_CFType { sal_Int32 cf; sal_Int32 ab; @@ -64,19 +67,32 @@ class MacabRecords{ protected: + /* MacabRecords is, at its core, a table of macabfields, in the + * form of a header and a list of objects of type MacabRecord. + * It also has a unique name that refers to the name of the table. + */ sal_Int32 recordsSize; sal_Int32 currentRecord; CFStringRef recordType; - sal_Int32 lcl_CFTypesLength; - lcl_CFType *lcl_CFTypes; MacabHeader *header; MacabRecord **records; ABAddressBookRef addressBook; ::rtl::OUString m_sName; - // cremlae, fill me + + /* For converting CF types to AB types */ + sal_Int32 lcl_CFTypesLength; + lcl_CFType *lcl_CFTypes; + + /* For required properties */ CFStringRef *requiredProperties; sal_Int32 numRequiredProperties; + private: + /* All of the private methods are for creating a MacabHeader or a + * MacabRecord. They are used by the initialize method that goes + * about filling a MacabRecords using all of the records in the + * Mac OS X Address Book. + */ void bootstrap_CF_types(); void bootstrap_requiredProperties(); MacabHeader *createHeaderForProperty(const ABRecordRef _record, const CFStringRef _propertyName, const CFStringRef _recordType, const sal_Bool _isPropertyRequired) const; File [changed]: MacabRecord.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabRecord.cxx?r1=1.1.2.2&r2=1.1.2.3 Delta lines: +35 -8 -------------------- --- MacabRecord.cxx 2007-07-13 18:17:42+0000 1.1.2.2 +++ MacabRecord.cxx 2007-07-15 01:56:55+0000 1.1.2.3 @@ -4,9 +4,9 @@ * * $RCSfile: MacabRecord.cxx,v $ * - * $Revision: 1.1.2.2 $ + * $Revision: 1.1.2.3 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 18:17:42 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -42,10 +42,6 @@ #include "macabutilities.hxx" #endif -/* cremlae -#include <math.h> -*/ - #ifndef _COM_SUN_STAR_UTIL_DATETIME_HPP_ #include <com/sun/star/util/DateTime.hpp> #endif @@ -133,6 +129,10 @@ // ------------------------------------------------------------------------- macabfield *MacabRecord::copy(const sal_Int32 i) const { + /* Note: copy(i) creates a new macabfield identical to that at + * location i, whereas get(i) returns a pointer to the macabfield + * at location i. + */ if(i < size) { macabfield *_copy = new macabfield; @@ -148,6 +148,10 @@ // ------------------------------------------------------------------------- macabfield *MacabRecord::get(const sal_Int32 i) const { + /* Note: copy(i) creates a new macabfield identical to that at + * location i, whereas get(i) returns a pointer to the macabfield + * at location i. + */ if(i < size) { return fields[i]; @@ -156,8 +160,14 @@ return NULL; } +// ------------------------------------------------------------------------- void MacabRecord::releaseFields() { + /* This method is, at the moment, only used in MacabHeader.cxx, but + * the idea is simple: if you are not destroying this object but want + * to clear it of its macabfields, you should release each field's + * value. + */ sal_Int32 i; for(i = 0; i < size; i++) CFRelease(fields[i]->value); @@ -167,6 +177,10 @@ sal_Int32 MacabRecord::compareFields(const macabfield *_field1, const macabfield *_field2) { + /* When comparing records, if either field is NULL (and the other is + * not), that field is considered "greater than" the other, so that it + * shows up later in the list when fields are ordered. + */ if(_field1 == _field2) return 0; if(_field1 == NULL) @@ -174,13 +188,16 @@ if(_field2 == NULL) return -1; - // If they aren't the same type, for now, return the one with - // the smaller type ID... for now. + /* If they aren't the same type, for now, return the one with + * the smaller type ID... I don't know of a better way to compare + * two different data types. + */ if(_field1->type != _field2->type) return(_field1->type - _field2->type); CFComparisonResult result; + /* Carbon has a unique compare function for each data type: */ switch(_field1->type) { case kABStringProperty: @@ -213,6 +230,11 @@ } // ------------------------------------------------------------------------- +/* Create a macabfield out of an OUString and type. Together with the + * method fieldToString() (below), it is possible to switch conveniently + * between an OUString and a macabfield (for use when creating and handling + * SQL statement). + */ macabfield *MacabRecord::createMacabField(const ::rtl::OUString _newFieldString, const ABPropertyType _abType) { macabfield *newField = NULL; @@ -276,6 +298,11 @@ } // ------------------------------------------------------------------------- +/* Create an OUString out of a macabfield. Together with the method + * createMacabField() (above), it is possible to switch conveniently + * between an OUString and a macabfield (for use when creating and handling + * SQL statement). + */ ::rtl::OUString MacabRecord::fieldToString(const macabfield *_aField) { if(_aField == NULL) File [changed]: MacabRecord.hxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabRecord.hxx?r1=1.1.2.2&r2=1.1.2.3 Delta lines: +6 -2 ------------------- --- MacabRecord.hxx 2007-07-13 18:17:42+0000 1.1.2.2 +++ MacabRecord.hxx 2007-07-15 01:56:55+0000 1.1.2.3 @@ -4,9 +4,9 @@ * * $RCSfile: MacabRecord.hxx,v $ * - * $Revision: 1.1.2.2 $ + * $Revision: 1.1.2.3 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 18:17:42 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -49,6 +49,10 @@ { namespace macab { + /* a MacabRecord is at root a list of macabfields (which is just + * something to hold both a CFTypeRef (a CoreFoundation object) and + * its Address Book type. + */ struct macabfield { CFTypeRef value; File [changed]: MacabHeader.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabHeader.cxx?r1=1.1.2.2&r2=1.1.2.3 Delta lines: +34 -3 -------------------- --- MacabHeader.cxx 2007-07-13 20:02:33+0000 1.1.2.2 +++ MacabHeader.cxx 2007-07-15 01:56:55+0000 1.1.2.3 @@ -4,9 +4,9 @@ * * $RCSfile: MacabHeader.cxx,v $ * - * $Revision: 1.1.2.2 $ + * $Revision: 1.1.2.3 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 20:02:33 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -69,6 +69,9 @@ } else { + /* The constructor duplicates the macabfields it gets because they + * are either deleted later or used for other purposes. + */ fields[i] = new macabfield; fields[i]->type = _fields[i]->type; fields[i]->value = _fields[i]->value; @@ -93,9 +96,15 @@ // ------------------------------------------------------------------------- void MacabHeader::operator+= (const MacabHeader *r) { + /* Add one MacabHeader to another. Anything not already in the header is + * added to the end of it. + */ sal_Int32 rSize = r->getSize(); - if(rSize != 0) + if(rSize != 0) // If the new header does actually have fields { + /* If our header is currently empty, just copy all of the fields from + * the new header to this one. + */ if(size == 0) { sal_Int32 i; @@ -106,6 +115,15 @@ fields[i] = r->copy(i); } } + + /* Otherwise, only add the duplicates. We do this with a two-pass + * approach. First, find out how many fields to add, then reallocate + * the size of the fields array and add the old ones at the end. + * (More precisely, we create a _new_ fields array with the new length + * allocated to it, then get all of the fields from the current + * fields array to it, then copy the non-duplicates from the new + * header to the end.) + */ else { sal_Int32 i; @@ -173,6 +191,11 @@ // ------------------------------------------------------------------------- macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length) { + /* Sort using mergesort. Because it uses mergesort, it is recursive and + * not in place (so it creates a new array at every step of the + * recursion), so if you prefer to use a different sort, please feel + * free to implement it. + */ macabfield** sorted = new macabfield *[_length]; if(_length <= 2) { @@ -241,6 +264,14 @@ sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2) { + /* Comparing two fields in a MacabHeader is different than comparing two + * fields in a MacabRecord. It starts in the same way (if one of the two + * fields is NULL, it belongs after the other, so it is considered + * "greater"). But, then, all headers are CFStrings, no matter what + * type they claim to be (since they actually hold the expected type for + * the records with that header). That being said, all we have to do is + * the built-in CFStringCompare. + */ if(_field1 == _field2) return 0; if(_field1 == NULL) File [changed]: MacabGroup.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabGroup.cxx?r1=1.1.2.1&r2=1.1.2.2 Delta lines: +15 -3 -------------------- --- MacabGroup.cxx 2007-07-08 19:20:58+0000 1.1.2.1 +++ MacabGroup.cxx 2007-07-15 01:56:55+0000 1.1.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: MacabGroup.cxx,v $ * - * $Revision: 1.1.2.1 $ + * $Revision: 1.1.2.2 $ * - * last change: $Author: msicotte $ $Date: 2007/07/08 19:20:58 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -48,6 +48,13 @@ using namespace connectivity::macab; +// ------------------------------------------------------------------------- +/* A MacabGroup is basically a MacabRecords with a different constructor. + * It only exists as a different entity for clarification purposes (a group + * is its own entity in the Mac OS X Address Book) and because its + * construction is so unique (it is based on an already existent + * MacabRecords of the entire address book). + */ MacabGroup::MacabGroup(const ABAddressBookRef _addressBook, const MacabRecords *_allRecords, const ABGroupRef _xGroup) : MacabRecords(_addressBook) { @@ -69,6 +76,11 @@ records = new MacabRecord *[recordsSize]; setHeader(_allRecords->getHeader()); + /* Go through each record in the group and try to find that record's UID + * in the MacabRecords that was passed in. If it is found, add that + * record to the group. Otherwise, report an error. (All records should + * exist in the MacabRecords that was passed in.) + */ nAllRecordsSize = _allRecords->size(); for(i = 0; i < recordsSize; i++) { @@ -86,7 +98,7 @@ { if(CFEqual(xRecordField->value, sGroupMemberUID)) { - // insert into the MacabGroup + /* Found the matching UID! Insert into the group... */ insertRecord(_allRecords->getRecord(j)); bFound = sal_True; break; File [changed]: MacabAddressBook.cxx Url: http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/macab/MacabAddressBook.cxx?r1=1.1.2.3&r2=1.1.2.4 Delta lines: +17 -2 -------------------- --- MacabAddressBook.cxx 2007-07-13 20:02:33+0000 1.1.2.3 +++ MacabAddressBook.cxx 2007-07-15 01:56:55+0000 1.1.2.4 @@ -4,9 +4,9 @@ * * $RCSfile: MacabAddressBook.cxx,v $ * - * $Revision: 1.1.2.3 $ + * $Revision: 1.1.2.4 $ * - * last change: $Author: cremlae $ $Date: 2007/07/13 20:02:33 $ + * last change: $Author: cremlae $ $Date: 2007/07/15 01:56:55 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -87,8 +87,12 @@ } // ----------------------------------------------------------------------------- +/* Get the address book's default table name. This is the table name that + * refers to the table containing _all_ records in the address book. + */ const ::rtl::OUString & MacabAddressBook::getDefaultTableName() { + /* This string probably needs to be localized. */ static const ::rtl::OUString aDefaultTableName (::rtl::OUString::createFromAscii("Address Book")); @@ -98,6 +102,7 @@ // ----------------------------------------------------------------------------- MacabRecords *MacabAddressBook::getMacabRecords() { + /* If the MacabRecords don't exist, create them. */ if(m_xMacabRecords == NULL) { m_xMacabRecords = new MacabRecords(m_aAddressBook); @@ -109,6 +114,9 @@ } // ----------------------------------------------------------------------------- +/* Get the MacabRecords for a given name: either a group name or the + * default table name. + */ MacabRecords *MacabAddressBook::getMacabRecords(const ::rtl::OUString _tableName) { if(_tableName == getDefaultTableName()) @@ -135,8 +143,10 @@ // ----------------------------------------------------------------------------- ::std::vector<MacabGroup *> MacabAddressBook::getMacabGroups() { + /* If the MacabGroups haven't been created yet, create them. */ if(m_bRetrievedGroups == sal_False) { + /* If the MacabRecords haven't been created yet, create them. */ if(m_xMacabRecords == NULL) { m_xMacabRecords = new MacabRecords(m_aAddressBook); @@ -150,12 +160,17 @@ sal_Int32 i; ABGroupRef xGroup; + + /* Go through each group and create a MacabGroup out of it. */ for(i = 0; i < nGroups; i++) { xGroup = (ABGroupRef) CFArrayGetValueAtIndex(allGroups, i); m_xMacabGroups[i] = new MacabGroup(m_aAddressBook, m_xMacabRecords, xGroup); } + CFRelease(allGroups); + + /* Manage duplicates. */ manageDuplicateGroups(m_xMacabGroups); m_bRetrievedGroups = sal_True; } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
