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