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