1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MacabRecord.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "MacabRecord.hxx"
35 #include "macabutilities.hxx"
36 #include <com/sun/star/util/DateTime.hpp>
39 #include <Carbon/Carbon.h>
40 #include <AddressBook/ABAddressBookC.h>
42 #include <connectivity/dbconversion.hxx>
44 using namespace connectivity::macab
;
45 using namespace com::sun::star::util
;
46 using namespace ::dbtools
;
48 // -------------------------------------------------------------------------
49 MacabRecord::MacabRecord()
55 // -------------------------------------------------------------------------
56 MacabRecord::MacabRecord(const sal_Int32 _size
)
59 fields
= new macabfield
*[size
];
61 for(i
= 0; i
< size
; i
++)
65 // -------------------------------------------------------------------------
66 MacabRecord::~MacabRecord()
71 for(i
= 0; i
< size
; i
++)
81 // -------------------------------------------------------------------------
82 void MacabRecord::insertAtColumn (CFTypeRef _value
, ABPropertyType _type
, const sal_Int32 _column
)
86 if(fields
[_column
] == NULL
)
87 fields
[_column
] = new macabfield
;
89 fields
[_column
]->value
= _value
;
90 if (fields
[_column
]->value
)
91 CFRetain(fields
[_column
]->value
);
92 fields
[_column
]->type
= _type
;
96 // -------------------------------------------------------------------------
97 sal_Bool
MacabRecord::contains (const macabfield
*_field
) const
102 return contains(_field
->value
);
105 // -------------------------------------------------------------------------
106 sal_Bool
MacabRecord::contains (const CFTypeRef _value
) const
109 for(i
= 0; i
< size
; i
++)
111 if(fields
[i
] != NULL
)
113 if(CFEqual(fields
[i
]->value
, _value
))
123 // -------------------------------------------------------------------------
124 sal_Int32
MacabRecord::getSize() const
129 // -------------------------------------------------------------------------
130 macabfield
*MacabRecord::copy(const sal_Int32 i
) const
132 /* Note: copy(i) creates a new macabfield identical to that at
133 * location i, whereas get(i) returns a pointer to the macabfield
138 macabfield
*_copy
= new macabfield
;
139 _copy
->type
= fields
[i
]->type
;
140 _copy
->value
= fields
[i
]->value
;
142 CFRetain(_copy
->value
);
149 // -------------------------------------------------------------------------
150 macabfield
*MacabRecord::get(const sal_Int32 i
) const
152 /* Note: copy(i) creates a new macabfield identical to that at
153 * location i, whereas get(i) returns a pointer to the macabfield
164 // -------------------------------------------------------------------------
165 void MacabRecord::releaseFields()
167 /* This method is, at the moment, only used in MacabHeader.cxx, but
168 * the idea is simple: if you are not destroying this object but want
169 * to clear it of its macabfields, you should release each field's
173 for(i
= 0; i
< size
; i
++)
174 CFRelease(fields
[i
]->value
);
177 // -------------------------------------------------------------------------
178 sal_Int32
MacabRecord::compareFields(const macabfield
*_field1
, const macabfield
*_field2
)
181 /* When comparing records, if either field is NULL (and the other is
182 * not), that field is considered "greater than" the other, so that it
183 * shows up later in the list when fields are ordered.
185 if(_field1
== _field2
)
192 /* If they aren't the same type, for now, return the one with
193 * the smaller type ID... I don't know of a better way to compare
194 * two different data types.
196 if(_field1
->type
!= _field2
->type
)
197 return(_field1
->type
- _field2
->type
);
199 CFComparisonResult result
;
201 /* Carbon has a unique compare function for each data type: */
202 switch(_field1
->type
)
204 case kABStringProperty
:
205 result
= CFStringCompare(
206 (CFStringRef
) _field1
->value
,
207 (CFStringRef
) _field2
->value
,
208 0); // 0 = no options (like ignore case)
211 case kABDateProperty
:
212 result
= CFDateCompare(
213 (CFDateRef
) _field1
->value
,
214 (CFDateRef
) _field2
->value
,
215 NULL
); // NULL = unused variable
218 case kABIntegerProperty
:
219 case kABRealProperty
:
220 result
= CFNumberCompare(
221 (CFNumberRef
) _field1
->value
,
222 (CFNumberRef
) _field2
->value
,
223 NULL
); // NULL = unused variable
227 result
= kCFCompareEqualTo
; // can't compare
230 return (sal_Int32
) result
;
233 // -------------------------------------------------------------------------
234 /* Create a macabfield out of an OUString and type. Together with the
235 * method fieldToString() (below), it is possible to switch conveniently
236 * between an OUString and a macabfield (for use when creating and handling
239 macabfield
*MacabRecord::createMacabField(const ::rtl::OUString _newFieldString
, const ABPropertyType _abType
)
241 macabfield
*newField
= NULL
;
244 case kABStringProperty
:
245 newField
= new macabfield
;
246 newField
->value
= OUStringToCFString(_newFieldString
);
247 newField
->type
= _abType
;
249 case kABDateProperty
:
251 DateTime aDateTime
= DBTypeConversion::toDateTime(_newFieldString
);
254 if(aDateTime
.Year
== 0 && aDateTime
.Month
== 0 && aDateTime
.Day
== 0)
259 double nTime
= DBTypeConversion::toDouble(aDateTime
, DBTypeConversion::getStandardDate());
260 nTime
-= kCFAbsoluteTimeIntervalSince1970
;
261 newField
= new macabfield
;
262 newField
->value
= CFDateCreate(NULL
, (CFAbsoluteTime
) nTime
);
263 newField
->type
= _abType
;
267 case kABIntegerProperty
:
270 sal_Int64 nVal
= _newFieldString
.toInt64();
272 newField
= new macabfield
;
273 newField
->value
= CFNumberCreate(NULL
,kCFNumberLongType
, &nVal
);
274 newField
->type
= _abType
;
281 case kABRealProperty
:
284 double nVal
= _newFieldString
.toDouble();
286 newField
= new macabfield
;
287 newField
->value
= CFNumberCreate(NULL
,kCFNumberDoubleType
, &nVal
);
288 newField
->type
= _abType
;
301 // -------------------------------------------------------------------------
302 /* Create an OUString out of a macabfield. Together with the method
303 * createMacabField() (above), it is possible to switch conveniently
304 * between an OUString and a macabfield (for use when creating and handling
307 ::rtl::OUString
MacabRecord::fieldToString(const macabfield
*_aField
)
310 return ::rtl::OUString();
312 ::rtl::OUString fieldString
;
314 switch(_aField
->type
)
316 case kABStringProperty
:
317 fieldString
= CFStringToOUString((CFStringRef
) _aField
->value
);
319 case kABDateProperty
:
321 DateTime aTime
= CFDateToDateTime((CFDateRef
) _aField
->value
);
322 fieldString
= DBTypeConversion::toDateTimeString(aTime
);
325 case kABIntegerProperty
:
327 CFNumberType numberType
= CFNumberGetType( (CFNumberRef
) _aField
->value
);
329 // Should we check for the wrong type here, e.g., a float?
330 sal_Bool m_bSuccess
= !CFNumberGetValue((CFNumberRef
) _aField
->value
, numberType
, &nVal
);
331 if(m_bSuccess
!= sal_False
)
332 fieldString
= ::rtl::OUString::valueOf(nVal
);
335 case kABRealProperty
:
337 CFNumberType numberType
= CFNumberGetType( (CFNumberRef
) _aField
->value
);
339 // Should we check for the wrong type here, e.g., an int?
340 sal_Bool m_bSuccess
= !CFNumberGetValue((CFNumberRef
) _aField
->value
, numberType
, &nVal
);
341 if(m_bSuccess
!= sal_False
)
342 fieldString
= ::rtl::OUString::valueOf(nVal
);