1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_connectivity.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "MacabHeader.hxx"
28*b1cdbd2cSJim Jagielski #include "MacabRecord.hxx"
29*b1cdbd2cSJim Jagielski #include "macabutilities.hxx"
30*b1cdbd2cSJim Jagielski 
31*b1cdbd2cSJim Jagielski #include <math.h>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/sdbc/DataType.hpp>
33*b1cdbd2cSJim Jagielski #include <connectivity/dbconversion.hxx>
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski using namespace connectivity::macab;
36*b1cdbd2cSJim Jagielski using namespace com::sun::star::sdbc;
37*b1cdbd2cSJim Jagielski using namespace com::sun::star::util;
38*b1cdbd2cSJim Jagielski using namespace ::dbtools;
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
MacabHeader(const sal_Int32 _size,macabfield ** _fields)41*b1cdbd2cSJim Jagielski MacabHeader::MacabHeader(const sal_Int32 _size, macabfield **_fields)
42*b1cdbd2cSJim Jagielski {
43*b1cdbd2cSJim Jagielski 	sal_Int32 i;
44*b1cdbd2cSJim Jagielski 	size = _size;
45*b1cdbd2cSJim Jagielski 	fields = new macabfield *[size];
46*b1cdbd2cSJim Jagielski 	for(i = 0; i < size; i++)
47*b1cdbd2cSJim Jagielski 	{
48*b1cdbd2cSJim Jagielski 		if(_fields[i] == NULL)
49*b1cdbd2cSJim Jagielski 		{
50*b1cdbd2cSJim Jagielski 			fields[i] = NULL;
51*b1cdbd2cSJim Jagielski 		}
52*b1cdbd2cSJim Jagielski 		else
53*b1cdbd2cSJim Jagielski 		{
54*b1cdbd2cSJim Jagielski 			/* The constructor duplicates the macabfields it gets because they
55*b1cdbd2cSJim Jagielski 			 * are either deleted later or used for other purposes.
56*b1cdbd2cSJim Jagielski 			 */
57*b1cdbd2cSJim Jagielski 			fields[i] = new macabfield;
58*b1cdbd2cSJim Jagielski 			fields[i]->type = _fields[i]->type;
59*b1cdbd2cSJim Jagielski 			fields[i]->value = _fields[i]->value;
60*b1cdbd2cSJim Jagielski 			if (fields[i]->value)
61*b1cdbd2cSJim Jagielski 				CFRetain(fields[i]->value);
62*b1cdbd2cSJim Jagielski 		}
63*b1cdbd2cSJim Jagielski 	}
64*b1cdbd2cSJim Jagielski 
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
MacabHeader()68*b1cdbd2cSJim Jagielski MacabHeader::MacabHeader()
69*b1cdbd2cSJim Jagielski {
70*b1cdbd2cSJim Jagielski 	size = 0;
71*b1cdbd2cSJim Jagielski 	fields = NULL;
72*b1cdbd2cSJim Jagielski }
73*b1cdbd2cSJim Jagielski 
74*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
~MacabHeader()75*b1cdbd2cSJim Jagielski MacabHeader::~MacabHeader()
76*b1cdbd2cSJim Jagielski {
77*b1cdbd2cSJim Jagielski }
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator +=(const MacabHeader * r)80*b1cdbd2cSJim Jagielski void MacabHeader::operator+= (const MacabHeader *r)
81*b1cdbd2cSJim Jagielski {
82*b1cdbd2cSJim Jagielski 	/* Add one MacabHeader to another. Anything not already in the header is
83*b1cdbd2cSJim Jagielski 	 * added to the end of it.
84*b1cdbd2cSJim Jagielski 	 */
85*b1cdbd2cSJim Jagielski 	sal_Int32 rSize = r->getSize();
86*b1cdbd2cSJim Jagielski 	if(rSize != 0) // If the new header does actually have fields
87*b1cdbd2cSJim Jagielski 	{
88*b1cdbd2cSJim Jagielski 		/* If our header is currently empty, just copy all of the fields from
89*b1cdbd2cSJim Jagielski 		 * the new header to this one.
90*b1cdbd2cSJim Jagielski 		 */
91*b1cdbd2cSJim Jagielski 		if(size == 0)
92*b1cdbd2cSJim Jagielski 		{
93*b1cdbd2cSJim Jagielski 			sal_Int32 i;
94*b1cdbd2cSJim Jagielski 			size = rSize;
95*b1cdbd2cSJim Jagielski 			fields = new macabfield *[size];
96*b1cdbd2cSJim Jagielski 			for(i = 0; i < size; i++)
97*b1cdbd2cSJim Jagielski 			{
98*b1cdbd2cSJim Jagielski 				fields[i] = r->copy(i);
99*b1cdbd2cSJim Jagielski 			}
100*b1cdbd2cSJim Jagielski 		}
101*b1cdbd2cSJim Jagielski 
102*b1cdbd2cSJim Jagielski 		/* Otherwise, only add the duplicates. We do this with a two-pass
103*b1cdbd2cSJim Jagielski 		 * approach. First, find out how many fields to add, then reallocate
104*b1cdbd2cSJim Jagielski 		 * the size of the fields array and add the old ones at the end.
105*b1cdbd2cSJim Jagielski 		 * (More precisely, we create a _new_ fields array with the new length
106*b1cdbd2cSJim Jagielski 		 * allocated to it, then get all of the fields from the current
107*b1cdbd2cSJim Jagielski 		 * fields array to it, then copy the non-duplicates from the new
108*b1cdbd2cSJim Jagielski 		 * header to the end.)
109*b1cdbd2cSJim Jagielski 		 */
110*b1cdbd2cSJim Jagielski 		else
111*b1cdbd2cSJim Jagielski 		{
112*b1cdbd2cSJim Jagielski 			sal_Int32 i;
113*b1cdbd2cSJim Jagielski 			sal_Int32 numToAdd = 0, numAdded = 0;
114*b1cdbd2cSJim Jagielski 			macabfield **newFields;
115*b1cdbd2cSJim Jagielski 			for( i = 0; i < rSize; i++)
116*b1cdbd2cSJim Jagielski 			{
117*b1cdbd2cSJim Jagielski 				if(!contains(r->get(i)))
118*b1cdbd2cSJim Jagielski 				{
119*b1cdbd2cSJim Jagielski 					numToAdd++;
120*b1cdbd2cSJim Jagielski 				}
121*b1cdbd2cSJim Jagielski 			}
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski 			newFields = new macabfield *[size+numToAdd];
124*b1cdbd2cSJim Jagielski 			for(i = 0; i < size; i++)
125*b1cdbd2cSJim Jagielski 			{
126*b1cdbd2cSJim Jagielski 				newFields[i] = copy(i);
127*b1cdbd2cSJim Jagielski 			}
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski 			for( i = 0; i < rSize; i++)
130*b1cdbd2cSJim Jagielski 			{
131*b1cdbd2cSJim Jagielski 				if(!contains(r->get(i)))
132*b1cdbd2cSJim Jagielski 				{
133*b1cdbd2cSJim Jagielski 					newFields[size+numAdded] = r->copy(i);
134*b1cdbd2cSJim Jagielski 					numAdded++;
135*b1cdbd2cSJim Jagielski 					if(numAdded == numToAdd)
136*b1cdbd2cSJim Jagielski 						break;
137*b1cdbd2cSJim Jagielski 				}
138*b1cdbd2cSJim Jagielski 			}
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski 			releaseFields();
141*b1cdbd2cSJim Jagielski 			delete [] fields;
142*b1cdbd2cSJim Jagielski 			size += numAdded;
143*b1cdbd2cSJim Jagielski 			fields = newFields;
144*b1cdbd2cSJim Jagielski 		}
145*b1cdbd2cSJim Jagielski 	}
146*b1cdbd2cSJim Jagielski }
147*b1cdbd2cSJim Jagielski 
148*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
getString(const sal_Int32 i) const149*b1cdbd2cSJim Jagielski ::rtl::OUString MacabHeader::getString(const sal_Int32 i) const
150*b1cdbd2cSJim Jagielski {
151*b1cdbd2cSJim Jagielski 	::rtl::OUString nRet;
152*b1cdbd2cSJim Jagielski 
153*b1cdbd2cSJim Jagielski 	if(i < size)
154*b1cdbd2cSJim Jagielski 	{
155*b1cdbd2cSJim Jagielski 	    if(fields[i] == NULL || fields[i]->value == NULL || CFGetTypeID(fields[i]->value) != CFStringGetTypeID())
156*b1cdbd2cSJim Jagielski         	return ::rtl::OUString();
157*b1cdbd2cSJim Jagielski 	    try
158*b1cdbd2cSJim Jagielski 	    {
159*b1cdbd2cSJim Jagielski         	nRet = CFStringToOUString( (CFStringRef) fields[i]->value);
160*b1cdbd2cSJim Jagielski 	    }
161*b1cdbd2cSJim Jagielski 	    catch(...){ }
162*b1cdbd2cSJim Jagielski 	}
163*b1cdbd2cSJim Jagielski 
164*b1cdbd2cSJim Jagielski 	return nRet;
165*b1cdbd2cSJim Jagielski }
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
sortRecord()168*b1cdbd2cSJim Jagielski void MacabHeader::sortRecord()
169*b1cdbd2cSJim Jagielski {
170*b1cdbd2cSJim Jagielski 	sortRecord(0,size);
171*b1cdbd2cSJim Jagielski }
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
sortRecord(const sal_Int32 _start,const sal_Int32 _length)174*b1cdbd2cSJim Jagielski macabfield **MacabHeader::sortRecord(const sal_Int32 _start, const sal_Int32 _length)
175*b1cdbd2cSJim Jagielski {
176*b1cdbd2cSJim Jagielski 	/* Sort using mergesort. Because it uses mergesort, it is recursive and
177*b1cdbd2cSJim Jagielski 	 * not in place (so it creates a new array at every step of the
178*b1cdbd2cSJim Jagielski 	 * recursion), so if you prefer to use a different sort, please feel
179*b1cdbd2cSJim Jagielski 	 * free to implement it.
180*b1cdbd2cSJim Jagielski 	 */
181*b1cdbd2cSJim Jagielski 	macabfield** sorted = new macabfield *[_length];
182*b1cdbd2cSJim Jagielski 	if(_length <= 2)
183*b1cdbd2cSJim Jagielski 	{
184*b1cdbd2cSJim Jagielski 		if(_length == 2)
185*b1cdbd2cSJim Jagielski 		{
186*b1cdbd2cSJim Jagielski 			if(compareFields(fields[_start], fields[_start+1]) > 0)
187*b1cdbd2cSJim Jagielski 			{
188*b1cdbd2cSJim Jagielski 				sorted[0] = get(_start+1);
189*b1cdbd2cSJim Jagielski 				sorted[1] = get(_start);
190*b1cdbd2cSJim Jagielski 			}
191*b1cdbd2cSJim Jagielski 			else
192*b1cdbd2cSJim Jagielski 			{
193*b1cdbd2cSJim Jagielski 				sorted[0] = get(_start);
194*b1cdbd2cSJim Jagielski 				sorted[1] = get(_start+1);
195*b1cdbd2cSJim Jagielski 			}
196*b1cdbd2cSJim Jagielski 		}
197*b1cdbd2cSJim Jagielski 		else if(_length == 1)
198*b1cdbd2cSJim Jagielski 		{
199*b1cdbd2cSJim Jagielski 			sorted[0] = get(_start);
200*b1cdbd2cSJim Jagielski 		}
201*b1cdbd2cSJim Jagielski 	}
202*b1cdbd2cSJim Jagielski 	else
203*b1cdbd2cSJim Jagielski 	{
204*b1cdbd2cSJim Jagielski 		sal_Int32 halfLength = floor(_length/2);
205*b1cdbd2cSJim Jagielski 		sal_Int32 fp = 0, lp = 0;
206*b1cdbd2cSJim Jagielski 		sal_Int32 i;
207*b1cdbd2cSJim Jagielski 		macabfield **firstHalf = new macabfield *[halfLength];
208*b1cdbd2cSJim Jagielski 		macabfield **lastHalf = new macabfield *[_length - halfLength];
209*b1cdbd2cSJim Jagielski 
210*b1cdbd2cSJim Jagielski 		firstHalf = sortRecord(_start, halfLength);
211*b1cdbd2cSJim Jagielski 		lastHalf = sortRecord(_start+halfLength, _length-halfLength);
212*b1cdbd2cSJim Jagielski 		for(i = 0; i < _length; i++)
213*b1cdbd2cSJim Jagielski 		{
214*b1cdbd2cSJim Jagielski 			if(compareFields(firstHalf[fp],lastHalf[lp]) < 0)
215*b1cdbd2cSJim Jagielski 			{
216*b1cdbd2cSJim Jagielski 				sorted[i] = firstHalf[fp++];
217*b1cdbd2cSJim Jagielski 				if(fp == halfLength)
218*b1cdbd2cSJim Jagielski 				{
219*b1cdbd2cSJim Jagielski 					for( i++; i < _length; i++)
220*b1cdbd2cSJim Jagielski 					{
221*b1cdbd2cSJim Jagielski 						sorted[i] = lastHalf[lp++];
222*b1cdbd2cSJim Jagielski 					}
223*b1cdbd2cSJim Jagielski 					break;
224*b1cdbd2cSJim Jagielski 				}
225*b1cdbd2cSJim Jagielski 			}
226*b1cdbd2cSJim Jagielski 			else
227*b1cdbd2cSJim Jagielski 			{
228*b1cdbd2cSJim Jagielski 				sorted[i] = lastHalf[lp++];
229*b1cdbd2cSJim Jagielski 				if(lp == _length - halfLength)
230*b1cdbd2cSJim Jagielski 				{
231*b1cdbd2cSJim Jagielski 					for( i++; i < _length; i++)
232*b1cdbd2cSJim Jagielski 					{
233*b1cdbd2cSJim Jagielski 						sorted[i] = firstHalf[fp++];
234*b1cdbd2cSJim Jagielski 					}
235*b1cdbd2cSJim Jagielski 					break;
236*b1cdbd2cSJim Jagielski 				}
237*b1cdbd2cSJim Jagielski 			}
238*b1cdbd2cSJim Jagielski 		}
239*b1cdbd2cSJim Jagielski 		if(_length == size)
240*b1cdbd2cSJim Jagielski 		{
241*b1cdbd2cSJim Jagielski 			fields = sorted;
242*b1cdbd2cSJim Jagielski 		}
243*b1cdbd2cSJim Jagielski 	}
244*b1cdbd2cSJim Jagielski 	return sorted;
245*b1cdbd2cSJim Jagielski }
246*b1cdbd2cSJim Jagielski 
compareFields(const macabfield * _field1,const macabfield * _field2)247*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::compareFields(const macabfield *_field1, const macabfield *_field2)
248*b1cdbd2cSJim Jagielski {
249*b1cdbd2cSJim Jagielski 	/* Comparing two fields in a MacabHeader is different than comparing two
250*b1cdbd2cSJim Jagielski 	 * fields in a MacabRecord. It starts in the same way (if one of the two
251*b1cdbd2cSJim Jagielski 	 * fields is NULL, it belongs after the other, so it is considered
252*b1cdbd2cSJim Jagielski 	 * "greater"). But, then, all headers are CFStrings, no matter what
253*b1cdbd2cSJim Jagielski 	 * type they claim to be (since they actually hold the expected type for
254*b1cdbd2cSJim Jagielski 	 * the records with that header). That being said, all we have to do is
255*b1cdbd2cSJim Jagielski 	 * the built-in CFStringCompare.
256*b1cdbd2cSJim Jagielski 	 */
257*b1cdbd2cSJim Jagielski 	if(_field1 == _field2)
258*b1cdbd2cSJim Jagielski 		return 0;
259*b1cdbd2cSJim Jagielski 	if(_field1 == NULL)
260*b1cdbd2cSJim Jagielski 		return 1;
261*b1cdbd2cSJim Jagielski 	if(_field2 == NULL)
262*b1cdbd2cSJim Jagielski 		return -1;
263*b1cdbd2cSJim Jagielski 
264*b1cdbd2cSJim Jagielski 	CFComparisonResult result = CFStringCompare(
265*b1cdbd2cSJim Jagielski 		(CFStringRef) _field1->value,
266*b1cdbd2cSJim Jagielski 		(CFStringRef) _field2->value,
267*b1cdbd2cSJim Jagielski 		0); // 0 = no options (like ignore case)
268*b1cdbd2cSJim Jagielski 
269*b1cdbd2cSJim Jagielski 	return (sal_Int32) result;
270*b1cdbd2cSJim Jagielski }
271*b1cdbd2cSJim Jagielski 
272*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
getColumnNumber(const::rtl::OUString s) const273*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::getColumnNumber(const ::rtl::OUString s) const
274*b1cdbd2cSJim Jagielski {
275*b1cdbd2cSJim Jagielski 	sal_Int32 i;
276*b1cdbd2cSJim Jagielski 	for(i = 0; i < size; i++)
277*b1cdbd2cSJim Jagielski 	{
278*b1cdbd2cSJim Jagielski 		if(getString(i) == s)
279*b1cdbd2cSJim Jagielski 			break;
280*b1cdbd2cSJim Jagielski 	}
281*b1cdbd2cSJim Jagielski 
282*b1cdbd2cSJim Jagielski 	if(i == size)
283*b1cdbd2cSJim Jagielski 		i = -1;
284*b1cdbd2cSJim Jagielski 
285*b1cdbd2cSJim Jagielski 	return i;
286*b1cdbd2cSJim Jagielski }
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
begin()289*b1cdbd2cSJim Jagielski MacabHeader *MacabHeader::begin()
290*b1cdbd2cSJim Jagielski {
291*b1cdbd2cSJim Jagielski 	return this;
292*b1cdbd2cSJim Jagielski }
293*b1cdbd2cSJim Jagielski 
294*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
iterator()295*b1cdbd2cSJim Jagielski MacabHeader::iterator::iterator ()
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski }
298*b1cdbd2cSJim Jagielski 
299*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
~iterator()300*b1cdbd2cSJim Jagielski MacabHeader::iterator::~iterator ()
301*b1cdbd2cSJim Jagielski {
302*b1cdbd2cSJim Jagielski }
303*b1cdbd2cSJim Jagielski 
operator =(MacabHeader * _record)304*b1cdbd2cSJim Jagielski void MacabHeader::iterator::operator= (MacabHeader *_record)
305*b1cdbd2cSJim Jagielski {
306*b1cdbd2cSJim Jagielski 	id = 0;
307*b1cdbd2cSJim Jagielski 	record = _record;
308*b1cdbd2cSJim Jagielski }
309*b1cdbd2cSJim Jagielski 
310*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator ++()311*b1cdbd2cSJim Jagielski void MacabHeader::iterator::operator++ ()
312*b1cdbd2cSJim Jagielski {
313*b1cdbd2cSJim Jagielski 	id++;
314*b1cdbd2cSJim Jagielski }
315*b1cdbd2cSJim Jagielski 
316*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator !=(const sal_Int32 i) const317*b1cdbd2cSJim Jagielski sal_Bool MacabHeader::iterator::operator!= (const sal_Int32 i) const
318*b1cdbd2cSJim Jagielski {
319*b1cdbd2cSJim Jagielski 	return(id != i);
320*b1cdbd2cSJim Jagielski }
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator ==(const sal_Int32 i) const323*b1cdbd2cSJim Jagielski sal_Bool MacabHeader::iterator::operator== (const sal_Int32 i) const
324*b1cdbd2cSJim Jagielski {
325*b1cdbd2cSJim Jagielski 	return(id == i);
326*b1cdbd2cSJim Jagielski }
327*b1cdbd2cSJim Jagielski 
328*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
operator *() const329*b1cdbd2cSJim Jagielski macabfield *MacabHeader::iterator::operator* () const
330*b1cdbd2cSJim Jagielski {
331*b1cdbd2cSJim Jagielski 	return record->get(id);
332*b1cdbd2cSJim Jagielski }
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
end() const335*b1cdbd2cSJim Jagielski sal_Int32 MacabHeader::end() const
336*b1cdbd2cSJim Jagielski {
337*b1cdbd2cSJim Jagielski 	return size;
338*b1cdbd2cSJim Jagielski }
339*b1cdbd2cSJim Jagielski 
340