1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "MacabRecord.hxx"
22 #include "macabutilities.hxx"
23 #include <com/sun/star/util/DateTime.hpp>
26 #include <Carbon/Carbon.h>
27 #include <AddressBook/ABAddressBookC.h>
29 #include <connectivity/dbconversion.hxx>
31 using namespace connectivity::macab
;
32 using namespace com::sun::star::util
;
33 using namespace ::dbtools
;
35 // -------------------------------------------------------------------------
36 MacabRecord::MacabRecord()
42 // -------------------------------------------------------------------------
43 MacabRecord::MacabRecord(const sal_Int32 _size
)
46 fields
= new macabfield
*[size
];
48 for(i
= 0; i
< size
; i
++)
52 // -------------------------------------------------------------------------
53 MacabRecord::~MacabRecord()
58 for(i
= 0; i
< size
; i
++)
68 // -------------------------------------------------------------------------
69 void MacabRecord::insertAtColumn (CFTypeRef _value
, ABPropertyType _type
, const sal_Int32 _column
)
73 if(fields
[_column
] == NULL
)
74 fields
[_column
] = new macabfield
;
76 fields
[_column
]->value
= _value
;
77 if (fields
[_column
]->value
)
78 CFRetain(fields
[_column
]->value
);
79 fields
[_column
]->type
= _type
;
83 // -------------------------------------------------------------------------
84 sal_Bool
MacabRecord::contains (const macabfield
*_field
) const
89 return contains(_field
->value
);
92 // -------------------------------------------------------------------------
93 sal_Bool
MacabRecord::contains (const CFTypeRef _value
) const
96 for(i
= 0; i
< size
; i
++)
100 if(CFEqual(fields
[i
]->value
, _value
))
110 // -------------------------------------------------------------------------
111 sal_Int32
MacabRecord::getSize() const
116 // -------------------------------------------------------------------------
117 macabfield
*MacabRecord::copy(const sal_Int32 i
) const
119 /* Note: copy(i) creates a new macabfield identical to that at
120 * location i, whereas get(i) returns a pointer to the macabfield
125 macabfield
*_copy
= new macabfield
;
126 _copy
->type
= fields
[i
]->type
;
127 _copy
->value
= fields
[i
]->value
;
129 CFRetain(_copy
->value
);
136 // -------------------------------------------------------------------------
137 macabfield
*MacabRecord::get(const sal_Int32 i
) const
139 /* Note: copy(i) creates a new macabfield identical to that at
140 * location i, whereas get(i) returns a pointer to the macabfield
151 // -------------------------------------------------------------------------
152 void MacabRecord::releaseFields()
154 /* This method is, at the moment, only used in MacabHeader.cxx, but
155 * the idea is simple: if you are not destroying this object but want
156 * to clear it of its macabfields, you should release each field's
160 for(i
= 0; i
< size
; i
++)
161 CFRelease(fields
[i
]->value
);
164 // -------------------------------------------------------------------------
165 sal_Int32
MacabRecord::compareFields(const macabfield
*_field1
, const macabfield
*_field2
)
168 /* When comparing records, if either field is NULL (and the other is
169 * not), that field is considered "greater than" the other, so that it
170 * shows up later in the list when fields are ordered.
172 if(_field1
== _field2
)
179 /* If they aren't the same type, for now, return the one with
180 * the smaller type ID... I don't know of a better way to compare
181 * two different data types.
183 if(_field1
->type
!= _field2
->type
)
184 return(_field1
->type
- _field2
->type
);
186 CFComparisonResult result
;
188 /* Carbon has a unique compare function for each data type: */
189 switch(_field1
->type
)
191 case kABStringProperty
:
192 result
= CFStringCompare(
193 (CFStringRef
) _field1
->value
,
194 (CFStringRef
) _field2
->value
,
195 kCFCompareLocalized
); // Specifies that the comparison should take into account differences related to locale, such as the thousands separator character.
198 case kABDateProperty
:
199 result
= CFDateCompare(
200 (CFDateRef
) _field1
->value
,
201 (CFDateRef
) _field2
->value
,
202 NULL
); // NULL = unused variable
205 case kABIntegerProperty
:
206 case kABRealProperty
:
207 result
= CFNumberCompare(
208 (CFNumberRef
) _field1
->value
,
209 (CFNumberRef
) _field2
->value
,
210 NULL
); // NULL = unused variable
214 result
= kCFCompareEqualTo
; // can't compare
217 return (sal_Int32
) result
;
220 // -------------------------------------------------------------------------
221 /* Create a macabfield out of an OUString and type. Together with the
222 * method fieldToString() (below), it is possible to switch conveniently
223 * between an OUString and a macabfield (for use when creating and handling
226 macabfield
*MacabRecord::createMacabField(const OUString _newFieldString
, const ABPropertyType _abType
)
228 macabfield
*newField
= NULL
;
231 case kABStringProperty
:
232 newField
= new macabfield
;
233 newField
->value
= OUStringToCFString(_newFieldString
);
234 newField
->type
= _abType
;
236 case kABDateProperty
:
238 DateTime aDateTime
= DBTypeConversion::toDateTime(_newFieldString
);
241 if(aDateTime
.Year
== 0 && aDateTime
.Month
== 0 && aDateTime
.Day
== 0)
246 double nTime
= DBTypeConversion::toDouble(aDateTime
, DBTypeConversion::getStandardDate());
247 nTime
-= kCFAbsoluteTimeIntervalSince1970
;
248 newField
= new macabfield
;
249 newField
->value
= CFDateCreate(NULL
, (CFAbsoluteTime
) nTime
);
250 newField
->type
= _abType
;
254 case kABIntegerProperty
:
257 sal_Int64 nVal
= _newFieldString
.toInt64();
259 newField
= new macabfield
;
260 newField
->value
= CFNumberCreate(NULL
,kCFNumberLongType
, &nVal
);
261 newField
->type
= _abType
;
268 case kABRealProperty
:
271 double nVal
= _newFieldString
.toDouble();
273 newField
= new macabfield
;
274 newField
->value
= CFNumberCreate(NULL
,kCFNumberDoubleType
, &nVal
);
275 newField
->type
= _abType
;
288 // -------------------------------------------------------------------------
289 /* Create an OUString out of a macabfield. Together with the method
290 * createMacabField() (above), it is possible to switch conveniently
291 * between an OUString and a macabfield (for use when creating and handling
294 OUString
MacabRecord::fieldToString(const macabfield
*_aField
)
299 OUString fieldString
;
301 switch(_aField
->type
)
303 case kABStringProperty
:
304 fieldString
= CFStringToOUString((CFStringRef
) _aField
->value
);
306 case kABDateProperty
:
308 DateTime aTime
= CFDateToDateTime((CFDateRef
) _aField
->value
);
309 fieldString
= DBTypeConversion::toDateTimeString(aTime
);
312 case kABIntegerProperty
:
314 CFNumberType numberType
= CFNumberGetType( (CFNumberRef
) _aField
->value
);
316 // Should we check for the wrong type here, e.g., a float?
317 sal_Bool m_bSuccess
= !CFNumberGetValue((CFNumberRef
) _aField
->value
, numberType
, &nVal
);
318 if(m_bSuccess
!= sal_False
)
319 fieldString
= OUString::valueOf(nVal
);
322 case kABRealProperty
:
324 CFNumberType numberType
= CFNumberGetType( (CFNumberRef
) _aField
->value
);
326 // Should we check for the wrong type here, e.g., an int?
327 sal_Bool m_bSuccess
= !CFNumberGetValue((CFNumberRef
) _aField
->value
, numberType
, &nVal
);
328 if(m_bSuccess
!= sal_False
)
329 fieldString
= OUString::valueOf(nVal
);
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */