xref: /AOO41X/main/connectivity/source/drivers/macab/MacabRecord.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1*9b5730f6SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9b5730f6SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9b5730f6SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9b5730f6SAndrew Rist  * distributed with this work for additional information
6*9b5730f6SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9b5730f6SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9b5730f6SAndrew Rist  * "License"); you may not use this file except in compliance
9*9b5730f6SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*9b5730f6SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*9b5730f6SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9b5730f6SAndrew Rist  * software distributed under the License is distributed on an
15*9b5730f6SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9b5730f6SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9b5730f6SAndrew Rist  * specific language governing permissions and limitations
18*9b5730f6SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*9b5730f6SAndrew Rist  *************************************************************/
21*9b5730f6SAndrew Rist 
22*9b5730f6SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_connectivity.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "MacabRecord.hxx"
28cdf0e10cSrcweir #include "macabutilities.hxx"
29cdf0e10cSrcweir #include <com/sun/star/util/DateTime.hpp>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <premac.h>
32cdf0e10cSrcweir #include <Carbon/Carbon.h>
33cdf0e10cSrcweir #include <AddressBook/ABAddressBookC.h>
34cdf0e10cSrcweir #include <postmac.h>
35cdf0e10cSrcweir #include <connectivity/dbconversion.hxx>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir using namespace connectivity::macab;
38cdf0e10cSrcweir using namespace com::sun::star::util;
39cdf0e10cSrcweir using namespace ::dbtools;
40cdf0e10cSrcweir 
41cdf0e10cSrcweir // -------------------------------------------------------------------------
MacabRecord()42cdf0e10cSrcweir MacabRecord::MacabRecord()
43cdf0e10cSrcweir {
44cdf0e10cSrcweir 	size = 0;
45cdf0e10cSrcweir 	fields = NULL;
46cdf0e10cSrcweir }
47cdf0e10cSrcweir 
48cdf0e10cSrcweir // -------------------------------------------------------------------------
MacabRecord(const sal_Int32 _size)49cdf0e10cSrcweir MacabRecord::MacabRecord(const sal_Int32 _size)
50cdf0e10cSrcweir {
51cdf0e10cSrcweir 	size = _size;
52cdf0e10cSrcweir 	fields = new macabfield *[size];
53cdf0e10cSrcweir 	sal_Int32 i;
54cdf0e10cSrcweir 	for(i = 0; i < size; i++)
55cdf0e10cSrcweir 		fields[i] = NULL;
56cdf0e10cSrcweir }
57cdf0e10cSrcweir 
58cdf0e10cSrcweir // -------------------------------------------------------------------------
~MacabRecord()59cdf0e10cSrcweir MacabRecord::~MacabRecord()
60cdf0e10cSrcweir {
61cdf0e10cSrcweir 	if(size > 0)
62cdf0e10cSrcweir 	{
63cdf0e10cSrcweir 		int i;
64cdf0e10cSrcweir 		for(i = 0; i < size; i++)
65cdf0e10cSrcweir 		{
66cdf0e10cSrcweir 			delete fields[i];
67cdf0e10cSrcweir 			fields[i] = NULL;
68cdf0e10cSrcweir 		}
69cdf0e10cSrcweir 	}
70cdf0e10cSrcweir 	delete [] fields;
71cdf0e10cSrcweir 	fields = NULL;
72cdf0e10cSrcweir }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir // -------------------------------------------------------------------------
insertAtColumn(CFTypeRef _value,ABPropertyType _type,const sal_Int32 _column)75cdf0e10cSrcweir void MacabRecord::insertAtColumn (CFTypeRef _value, ABPropertyType _type, const sal_Int32 _column)
76cdf0e10cSrcweir {
77cdf0e10cSrcweir 	if(_column < size)
78cdf0e10cSrcweir 	{
79cdf0e10cSrcweir 		if(fields[_column] == NULL)
80cdf0e10cSrcweir 			fields[_column] = new macabfield;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 		fields[_column]->value = _value;
83cdf0e10cSrcweir 		if (fields[_column]->value)
84cdf0e10cSrcweir 			CFRetain(fields[_column]->value);
85cdf0e10cSrcweir 		fields[_column]->type = _type;
86cdf0e10cSrcweir 	}
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
89cdf0e10cSrcweir // -------------------------------------------------------------------------
contains(const macabfield * _field) const90cdf0e10cSrcweir sal_Bool MacabRecord::contains (const macabfield *_field) const
91cdf0e10cSrcweir {
92cdf0e10cSrcweir 	if(_field == NULL)
93cdf0e10cSrcweir 		return sal_False;
94cdf0e10cSrcweir 	else
95cdf0e10cSrcweir 		return contains(_field->value);
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
98cdf0e10cSrcweir // -------------------------------------------------------------------------
contains(const CFTypeRef _value) const99cdf0e10cSrcweir sal_Bool MacabRecord::contains (const CFTypeRef _value) const
100cdf0e10cSrcweir {
101cdf0e10cSrcweir 	sal_Int32 i;
102cdf0e10cSrcweir 	for(i = 0; i < size; i++)
103cdf0e10cSrcweir 	{
104cdf0e10cSrcweir 		if(fields[i] != NULL)
105cdf0e10cSrcweir 		{
106cdf0e10cSrcweir 			if(CFEqual(fields[i]->value, _value))
107cdf0e10cSrcweir 			{
108cdf0e10cSrcweir 				return sal_True;
109cdf0e10cSrcweir 			}
110cdf0e10cSrcweir 		}
111cdf0e10cSrcweir 	}
112cdf0e10cSrcweir 
113cdf0e10cSrcweir 	return sal_False;
114cdf0e10cSrcweir }
115cdf0e10cSrcweir 
116cdf0e10cSrcweir // -------------------------------------------------------------------------
getSize() const117cdf0e10cSrcweir sal_Int32 MacabRecord::getSize() const
118cdf0e10cSrcweir {
119cdf0e10cSrcweir 	return size;
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir // -------------------------------------------------------------------------
copy(const sal_Int32 i) const123cdf0e10cSrcweir macabfield *MacabRecord::copy(const sal_Int32 i) const
124cdf0e10cSrcweir {
125cdf0e10cSrcweir 	/* Note: copy(i) creates a new macabfield identical to that at
126cdf0e10cSrcweir 	 * location i, whereas get(i) returns a pointer to the macabfield
127cdf0e10cSrcweir 	 * at location i.
128cdf0e10cSrcweir 	 */
129cdf0e10cSrcweir 	if(i < size)
130cdf0e10cSrcweir 	{
131cdf0e10cSrcweir 		macabfield *_copy = new macabfield;
132cdf0e10cSrcweir 		_copy->type = fields[i]->type;
133cdf0e10cSrcweir 		_copy->value = fields[i]->value;
134cdf0e10cSrcweir 		if (_copy->value)
135cdf0e10cSrcweir 			CFRetain(_copy->value);
136cdf0e10cSrcweir 		return _copy;
137cdf0e10cSrcweir 	}
138cdf0e10cSrcweir 
139cdf0e10cSrcweir 	return NULL;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir // -------------------------------------------------------------------------
get(const sal_Int32 i) const143cdf0e10cSrcweir macabfield *MacabRecord::get(const sal_Int32 i) const
144cdf0e10cSrcweir {
145cdf0e10cSrcweir 	/* Note: copy(i) creates a new macabfield identical to that at
146cdf0e10cSrcweir 	 * location i, whereas get(i) returns a pointer to the macabfield
147cdf0e10cSrcweir 	 * at location i.
148cdf0e10cSrcweir 	 */
149cdf0e10cSrcweir 	if(i < size)
150cdf0e10cSrcweir 	{
151cdf0e10cSrcweir 		return fields[i];
152cdf0e10cSrcweir 	}
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	return NULL;
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
157cdf0e10cSrcweir // -------------------------------------------------------------------------
releaseFields()158cdf0e10cSrcweir void MacabRecord::releaseFields()
159cdf0e10cSrcweir {
160cdf0e10cSrcweir 	/* This method is, at the moment, only used in MacabHeader.cxx, but
161cdf0e10cSrcweir 	 * the idea is simple: if you are not destroying this object but want
162cdf0e10cSrcweir 	 * to clear it of its macabfields, you should release each field's
163cdf0e10cSrcweir 	 * value.
164cdf0e10cSrcweir 	 */
165cdf0e10cSrcweir 	sal_Int32 i;
166cdf0e10cSrcweir 	for(i = 0; i < size; i++)
167cdf0e10cSrcweir 		CFRelease(fields[i]->value);
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
170cdf0e10cSrcweir // -------------------------------------------------------------------------
compareFields(const macabfield * _field1,const macabfield * _field2)171cdf0e10cSrcweir sal_Int32 MacabRecord::compareFields(const macabfield *_field1, const macabfield *_field2)
172cdf0e10cSrcweir {
173cdf0e10cSrcweir 
174cdf0e10cSrcweir 	/* When comparing records, if either field is NULL (and the other is
175cdf0e10cSrcweir 	 * not), that field is considered "greater than" the other, so that it
176cdf0e10cSrcweir 	 * shows up later in the list when fields are ordered.
177cdf0e10cSrcweir 	 */
178cdf0e10cSrcweir 	if(_field1 == _field2)
179cdf0e10cSrcweir 		return 0;
180cdf0e10cSrcweir 	if(_field1 == NULL)
181cdf0e10cSrcweir 		return 1;
182cdf0e10cSrcweir 	if(_field2 == NULL)
183cdf0e10cSrcweir 		return -1;
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 	/* If they aren't the same type, for now, return the one with
186cdf0e10cSrcweir 	 * the smaller type ID... I don't know of a better way to compare
187cdf0e10cSrcweir 	 * two different data types.
188cdf0e10cSrcweir 	 */
189cdf0e10cSrcweir 	if(_field1->type != _field2->type)
190cdf0e10cSrcweir 		return(_field1->type - _field2->type);
191cdf0e10cSrcweir 
192cdf0e10cSrcweir 	CFComparisonResult result;
193cdf0e10cSrcweir 
194cdf0e10cSrcweir 	/* Carbon has a unique compare function for each data type: */
195cdf0e10cSrcweir 	switch(_field1->type)
196cdf0e10cSrcweir 	{
197cdf0e10cSrcweir 		case kABStringProperty:
198cdf0e10cSrcweir 			result = CFStringCompare(
199cdf0e10cSrcweir 				(CFStringRef) _field1->value,
200cdf0e10cSrcweir 				(CFStringRef) _field2->value,
201cdf0e10cSrcweir 				kCFCompareLocalized); // Specifies that the comparison should take into account differences related to locale, such as the thousands separator character.
202cdf0e10cSrcweir 			break;
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 		case kABDateProperty:
205cdf0e10cSrcweir 			result = CFDateCompare(
206cdf0e10cSrcweir 				(CFDateRef) _field1->value,
207cdf0e10cSrcweir 				(CFDateRef) _field2->value,
208cdf0e10cSrcweir 				NULL); // NULL = unused variable
209cdf0e10cSrcweir 			break;
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 		case kABIntegerProperty:
212cdf0e10cSrcweir 		case kABRealProperty:
213cdf0e10cSrcweir 			result = CFNumberCompare(
214cdf0e10cSrcweir 				(CFNumberRef) _field1->value,
215cdf0e10cSrcweir 				(CFNumberRef) _field2->value,
216cdf0e10cSrcweir 				NULL); // NULL = unused variable
217cdf0e10cSrcweir 		break;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 		default:
220cdf0e10cSrcweir 			result = kCFCompareEqualTo; // can't compare
221cdf0e10cSrcweir 	}
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 	return (sal_Int32) result;
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
226cdf0e10cSrcweir // -------------------------------------------------------------------------
227cdf0e10cSrcweir /* Create a macabfield out of an OUString and type. Together with the
228cdf0e10cSrcweir  * method fieldToString() (below), it is possible to switch conveniently
229cdf0e10cSrcweir  * between an OUString and a macabfield (for use when creating and handling
230cdf0e10cSrcweir  * SQL statement).
231cdf0e10cSrcweir  */
createMacabField(const::rtl::OUString _newFieldString,const ABPropertyType _abType)232cdf0e10cSrcweir macabfield *MacabRecord::createMacabField(const ::rtl::OUString _newFieldString, const ABPropertyType _abType)
233cdf0e10cSrcweir {
234cdf0e10cSrcweir 	macabfield *newField = NULL;
235cdf0e10cSrcweir 	switch(_abType)
236cdf0e10cSrcweir 	{
237cdf0e10cSrcweir 		case kABStringProperty:
238cdf0e10cSrcweir 			newField = new macabfield;
239cdf0e10cSrcweir 			newField->value = OUStringToCFString(_newFieldString);
240cdf0e10cSrcweir 			newField->type = _abType;
241cdf0e10cSrcweir 			break;
242cdf0e10cSrcweir 		case kABDateProperty:
243cdf0e10cSrcweir 			{
244cdf0e10cSrcweir 				DateTime aDateTime = DBTypeConversion::toDateTime(_newFieldString);
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 				// bad format...
247cdf0e10cSrcweir 				if(aDateTime.Year == 0 && aDateTime.Month == 0 && aDateTime.Day == 0)
248cdf0e10cSrcweir 				{
249cdf0e10cSrcweir 				}
250cdf0e10cSrcweir 				else
251cdf0e10cSrcweir 				{
252cdf0e10cSrcweir 					double nTime = DBTypeConversion::toDouble(aDateTime, DBTypeConversion::getStandardDate());
253cdf0e10cSrcweir 					nTime -= kCFAbsoluteTimeIntervalSince1970;
254cdf0e10cSrcweir 					newField = new macabfield;
255cdf0e10cSrcweir 					newField->value = CFDateCreate(NULL, (CFAbsoluteTime) nTime);
256cdf0e10cSrcweir 					newField->type = _abType;
257cdf0e10cSrcweir 				}
258cdf0e10cSrcweir 			}
259cdf0e10cSrcweir 			break;
260cdf0e10cSrcweir 		case kABIntegerProperty:
261cdf0e10cSrcweir 			try
262cdf0e10cSrcweir 			{
263cdf0e10cSrcweir 				sal_Int64 nVal = _newFieldString.toInt64();
264cdf0e10cSrcweir 
265cdf0e10cSrcweir 				newField = new macabfield;
266cdf0e10cSrcweir 				newField->value = CFNumberCreate(NULL,kCFNumberLongType, &nVal);
267cdf0e10cSrcweir 				newField->type = _abType;
268cdf0e10cSrcweir 			}
269cdf0e10cSrcweir 			// bad format...
270cdf0e10cSrcweir 			catch(...)
271cdf0e10cSrcweir 			{
272cdf0e10cSrcweir 			}
273cdf0e10cSrcweir 			break;
274cdf0e10cSrcweir 		case kABRealProperty:
275cdf0e10cSrcweir 			try
276cdf0e10cSrcweir 			{
277cdf0e10cSrcweir 				double nVal = _newFieldString.toDouble();
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 				newField = new macabfield;
280cdf0e10cSrcweir 				newField->value = CFNumberCreate(NULL,kCFNumberDoubleType, &nVal);
281cdf0e10cSrcweir 				newField->type = _abType;
282cdf0e10cSrcweir 			}
283cdf0e10cSrcweir 			// bad format...
284cdf0e10cSrcweir 			catch(...)
285cdf0e10cSrcweir 			{
286cdf0e10cSrcweir 			}
287cdf0e10cSrcweir 			break;
288cdf0e10cSrcweir 		default:
289cdf0e10cSrcweir 			;
290cdf0e10cSrcweir 	}
291cdf0e10cSrcweir 	return newField;
292cdf0e10cSrcweir }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir // -------------------------------------------------------------------------
295cdf0e10cSrcweir /* Create an OUString out of a macabfield. Together with the method
296cdf0e10cSrcweir  * createMacabField() (above), it is possible to switch conveniently
297cdf0e10cSrcweir  * between an OUString and a macabfield (for use when creating and handling
298cdf0e10cSrcweir  * SQL statement).
299cdf0e10cSrcweir  */
fieldToString(const macabfield * _aField)300cdf0e10cSrcweir ::rtl::OUString MacabRecord::fieldToString(const macabfield *_aField)
301cdf0e10cSrcweir {
302cdf0e10cSrcweir 	if(_aField == NULL)
303cdf0e10cSrcweir 		return ::rtl::OUString();
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 	::rtl::OUString fieldString;
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 	switch(_aField->type)
308cdf0e10cSrcweir 	{
309cdf0e10cSrcweir 		case kABStringProperty:
310cdf0e10cSrcweir 			fieldString = CFStringToOUString((CFStringRef) _aField->value);
311cdf0e10cSrcweir 			break;
312cdf0e10cSrcweir 		case kABDateProperty:
313cdf0e10cSrcweir 			{
314cdf0e10cSrcweir 				DateTime aTime = CFDateToDateTime((CFDateRef) _aField->value);
315cdf0e10cSrcweir 				fieldString = DBTypeConversion::toDateTimeString(aTime);
316cdf0e10cSrcweir 			}
317cdf0e10cSrcweir 			break;
318cdf0e10cSrcweir 		case kABIntegerProperty:
319cdf0e10cSrcweir 			{
320cdf0e10cSrcweir 				CFNumberType numberType = CFNumberGetType( (CFNumberRef) _aField->value );
321cdf0e10cSrcweir 				sal_Int64 nVal;
322cdf0e10cSrcweir 				// Should we check for the wrong type here, e.g., a float?
323cdf0e10cSrcweir 				sal_Bool m_bSuccess = !CFNumberGetValue((CFNumberRef) _aField->value, numberType, &nVal);
324cdf0e10cSrcweir 				if(m_bSuccess != sal_False)
325cdf0e10cSrcweir 					fieldString = ::rtl::OUString::valueOf(nVal);
326cdf0e10cSrcweir 			}
327cdf0e10cSrcweir 			break;
328cdf0e10cSrcweir 		case kABRealProperty:
329cdf0e10cSrcweir 			{
330cdf0e10cSrcweir 				CFNumberType numberType = CFNumberGetType( (CFNumberRef) _aField->value );
331cdf0e10cSrcweir 				double nVal;
332cdf0e10cSrcweir 				// Should we check for the wrong type here, e.g., an int?
333cdf0e10cSrcweir 				sal_Bool m_bSuccess = !CFNumberGetValue((CFNumberRef) _aField->value, numberType, &nVal);
334cdf0e10cSrcweir 				if(m_bSuccess != sal_False)
335cdf0e10cSrcweir 					fieldString = ::rtl::OUString::valueOf(nVal);
336cdf0e10cSrcweir 			}
337cdf0e10cSrcweir 			break;
338cdf0e10cSrcweir 		default:
339cdf0e10cSrcweir 			;
340cdf0e10cSrcweir 	}
341cdf0e10cSrcweir 	return fieldString;
342cdf0e10cSrcweir 
343cdf0e10cSrcweir }
344