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: collatorImpl.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_i18npool.hxx"
34 #include <collatorImpl.hxx>
35 #include <com/sun/star/i18n/CollatorOptions.hpp>
36 #include <rtl/ustrbuf.hxx>
38 using namespace com::sun::star
;
39 using namespace com::sun::star::lang
;
40 using namespace com::sun::star::uno
;
43 namespace com
{ namespace sun
{ namespace star
{ namespace i18n
{
45 CollatorImpl::CollatorImpl( const Reference
< XMultiServiceFactory
>& rxMSF
) : xMSF(rxMSF
)
48 Reference
< XInterface
> xI
=
49 xMSF
->createInstance( OUString::createFromAscii("com.sun.star.i18n.LocaleData"));
51 xI
->queryInterface(::getCppuType((const Reference
< XLocaleData
>*)0)) >>= localedata
;
56 CollatorImpl::~CollatorImpl()
59 for (size_t l
= 0; l
< lookupTable
.size(); l
++)
60 delete lookupTable
[l
];
65 CollatorImpl::compareSubstring( const OUString
& str1
, sal_Int32 off1
, sal_Int32 len1
,
66 const OUString
& str2
, sal_Int32 off2
, sal_Int32 len2
) throw(RuntimeException
)
69 return cachedItem
->xC
->compareSubstring(str1
, off1
, len1
, str2
, off2
, len2
);
71 sal_Unicode
*unistr1
= (sal_Unicode
*) str1
.getStr() + off1
;
72 sal_Unicode
*unistr2
= (sal_Unicode
*) str2
.getStr() + off2
;
73 for (int i
= 0; i
< len1
&& i
< len2
; i
++)
74 if (unistr1
[i
] != unistr2
[i
])
75 return unistr1
[i
] < unistr2
[i
] ? -1 : 1;
76 return len1
== len2
? 0 : (len1
< len2
? -1 : 1);
80 CollatorImpl::compareString( const OUString
& in_str1
, const OUString
& in_str2
) throw(RuntimeException
)
83 return cachedItem
->xC
->compareString(in_str1
, in_str2
);
85 return CollatorImpl::compareSubstring(in_str1
, 0, in_str1
.getLength(), in_str2
, 0, in_str2
.getLength());
90 CollatorImpl::loadDefaultCollator(const lang::Locale
& rLocale
, sal_Int32 collatorOptions
) throw(RuntimeException
)
92 const Sequence
< Implementation
> &imp
= localedata
->getCollatorImplementations(rLocale
);
93 for (sal_Int16 i
= 0; i
< imp
.getLength(); i
++)
95 return loadCollatorAlgorithm(imp
[i
].unoID
, rLocale
, collatorOptions
);
97 throw RuntimeException(); // not default is defined
102 CollatorImpl::loadCollatorAlgorithm(const OUString
& impl
, const lang::Locale
& rLocale
, sal_Int32 collatorOptions
)
103 throw(RuntimeException
)
105 if (! cachedItem
|| ! cachedItem
->equals(rLocale
, impl
))
106 loadCachedCollator(rLocale
, impl
);
109 cachedItem
->xC
->loadCollatorAlgorithm(cachedItem
->algorithm
, nLocale
= rLocale
, collatorOptions
);
111 throw RuntimeException(); // impl could not be loaded
117 CollatorImpl::loadCollatorAlgorithmWithEndUserOption(const OUString
& impl
, const lang::Locale
& rLocale
,
118 const Sequence
< sal_Int32
>& collatorOptions
) throw(RuntimeException
)
120 sal_Int32 options
= 0;
121 for (sal_Int32 i
= 0; i
< collatorOptions
.getLength(); i
++)
122 options
|= collatorOptions
[i
];
123 loadCollatorAlgorithm(impl
, rLocale
, options
);
126 Sequence
< OUString
> SAL_CALL
127 CollatorImpl::listCollatorAlgorithms( const lang::Locale
& rLocale
) throw(RuntimeException
)
130 const Sequence
< Implementation
> &imp
= localedata
->getCollatorImplementations(rLocale
);
131 Sequence
< OUString
> list(imp
.getLength());
133 for (sal_Int32 i
= 0; i
< imp
.getLength(); i
++) {
134 //if the current algorithm is default and the position is not on the first one, then switch
135 if (imp
[i
].isDefault
&& i
) {
137 list
[0] = imp
[i
].unoID
;
140 list
[i
] = imp
[i
].unoID
;
145 Sequence
< sal_Int32
> SAL_CALL
146 CollatorImpl::listCollatorOptions( const OUString
& /*collatorAlgorithmName*/ ) throw(RuntimeException
)
148 Sequence
< OUString
> option_str
= localedata
->getCollationOptions(nLocale
);
149 Sequence
< sal_Int32
> option_int(option_str
.getLength());
151 for (sal_Int32 i
= 0; i
< option_str
.getLength(); i
++)
153 option_str
[i
].equalsAscii("IGNORE_CASE") ? CollatorOptions::CollatorOptions_IGNORE_CASE
:
154 option_str
[i
].equalsAscii("IGNORE_KANA") ? CollatorOptions::CollatorOptions_IGNORE_KANA
:
155 option_str
[i
].equalsAscii("IGNORE_WIDTH") ? CollatorOptions::CollatorOptions_IGNORE_WIDTH
: 0;
161 CollatorImpl::createCollator(const lang::Locale
& rLocale
, const OUString
& serviceName
, const OUString
& rSortAlgorithm
)
162 throw(RuntimeException
)
164 for (size_t l
= 0; l
< lookupTable
.size(); l
++) {
165 cachedItem
= lookupTable
[l
];
166 if (cachedItem
->service
.equals(serviceName
)) {// cross locale sharing
167 lookupTable
.push_back(cachedItem
= new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, cachedItem
->xC
));
172 Reference
< XInterface
> xI
=
173 xMSF
->createInstance(OUString::createFromAscii("com.sun.star.i18n.Collator_") + serviceName
);
176 Reference
< XCollator
> xC
;
177 xI
->queryInterface( getCppuType((const Reference
< XCollator
>*)0) ) >>= xC
;
179 lookupTable
.push_back(cachedItem
= new lookupTableItem(rLocale
, rSortAlgorithm
, serviceName
, xC
));
185 throw RuntimeException();
189 CollatorImpl::loadCachedCollator(const lang::Locale
& rLocale
, const OUString
& rSortAlgorithm
)
190 throw(RuntimeException
)
192 for (size_t i
= 0; i
< lookupTable
.size(); i
++) {
193 cachedItem
= lookupTable
[i
];
194 if (cachedItem
->equals(rLocale
, rSortAlgorithm
)) {
199 static sal_Unicode under
= (sal_Unicode
) '_';
200 static OUString
tw(OUString::createFromAscii("TW"));
201 static OUString
unicode(OUString::createFromAscii("Unicode"));
203 sal_Int32 l
= rLocale
.Language
.getLength();
204 sal_Int32 c
= rLocale
.Country
.getLength();
205 sal_Int32 v
= rLocale
.Variant
.getLength();
206 sal_Int32 a
= rSortAlgorithm
.getLength();
207 OUStringBuffer
aBuf(l
+c
+v
+a
+4);
209 if ((l
> 0 && c
> 0 && v
> 0 && a
> 0 &&
210 // load service with name <base>_<lang>_<country>_<varian>_<algorithm>
211 createCollator(rLocale
, aBuf
.append(rLocale
.Language
).append(under
).append(rLocale
.Country
).append(
212 under
).append(rLocale
.Variant
).append(under
).append(rSortAlgorithm
).makeStringAndClear(),
214 (l
> 0 && c
> 0 && a
> 0 &&
215 // load service with name <base>_<lang>_<country>_<algorithm>
216 createCollator(rLocale
, aBuf
.append(rLocale
.Language
).append(under
).append(rLocale
.Country
).append(
217 under
).append(rSortAlgorithm
).makeStringAndClear(), rSortAlgorithm
)) ||
218 (l
> 0 && c
> 0 && a
> 0 && rLocale
.Language
.equalsAscii("zh") &&
219 (rLocale
.Country
.equalsAscii("HK") ||
220 rLocale
.Country
.equalsAscii("MO")) &&
221 // if the country code is HK or MO, one more step to try TW.
222 createCollator(rLocale
, aBuf
.append(rLocale
.Language
).append(under
).append(tw
).append(under
).append(
223 rSortAlgorithm
).makeStringAndClear(), rSortAlgorithm
)) ||
225 // load service with name <base>_<lang>_<algorithm>
226 createCollator(rLocale
, aBuf
.append(rLocale
.Language
).append(under
).append(rSortAlgorithm
).makeStringAndClear(),
228 // load service with name <base>_<algorithm>
230 createCollator(rLocale
, rSortAlgorithm
, rSortAlgorithm
)) ||
231 // load default service with name <base>_Unicode
232 createCollator(rLocale
, unicode
, rSortAlgorithm
)) {
236 throw RuntimeException(); // could not load any service
240 const sal_Char cCollator
[] = "com.sun.star.i18n.Collator";
243 CollatorImpl::getImplementationName() throw( RuntimeException
)
245 return OUString::createFromAscii(cCollator
);
249 CollatorImpl::supportsService(const OUString
& rServiceName
)
250 throw( RuntimeException
)
252 return rServiceName
.equalsAscii(cCollator
);
255 Sequence
< OUString
> SAL_CALL
256 CollatorImpl::getSupportedServiceNames() throw( RuntimeException
)
258 Sequence
< OUString
> aRet(1);
259 aRet
[0] = OUString::createFromAscii(cCollator
);