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