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_i18npool.hxx"
26 #include <rtl/ustrbuf.hxx>
27 #include <indexentrysupplier.hxx>
28 #include <localedata.hxx>
29 
30 using namespace ::com::sun::star::uno;
31 using namespace ::com::sun::star::lang;
32 using namespace ::rtl;
33 
34 static const sal_Unicode under = sal_Unicode('_');
35 
36 namespace com { namespace sun { namespace star { namespace i18n {
37 
IndexEntrySupplier(const Reference<XMultiServiceFactory> & rxMSF)38 IndexEntrySupplier::IndexEntrySupplier( const Reference < XMultiServiceFactory >& rxMSF ) : xMSF( rxMSF )
39 {
40 }
41 
getLocaleList()42 Sequence < Locale > SAL_CALL IndexEntrySupplier::getLocaleList() throw (RuntimeException)
43 {
44         return LocaleData().getAllInstalledLocaleNames();
45 }
46 
getAlgorithmList(const Locale & rLocale)47 Sequence < OUString > SAL_CALL IndexEntrySupplier::getAlgorithmList( const Locale& rLocale ) throw (RuntimeException)
48 {
49         return LocaleData().getIndexAlgorithm(rLocale);
50 }
51 
loadAlgorithm(const Locale & rLocale,const OUString & SortAlgorithm,sal_Int32 collatorOptions)52 sal_Bool SAL_CALL IndexEntrySupplier::loadAlgorithm( const Locale& rLocale, const OUString& SortAlgorithm,
53         sal_Int32 collatorOptions ) throw (RuntimeException)
54 {
55         Sequence < OUString > algorithmList = getAlgorithmList( rLocale );
56         for (sal_Int32 i = 0; i < algorithmList.getLength(); i++) {
57             if (algorithmList[i] == SortAlgorithm) {
58                 if (getLocaleSpecificIndexEntrySupplier(rLocale, SortAlgorithm).is())
59                     return xIES->loadAlgorithm(rLocale, SortAlgorithm, collatorOptions);
60             }
61         }
62         return sal_False;
63 }
64 
usePhoneticEntry(const Locale & rLocale)65 sal_Bool SAL_CALL IndexEntrySupplier::usePhoneticEntry( const Locale& rLocale ) throw (RuntimeException)
66 {
67         return LocaleData().hasPhonetic(rLocale);
68 }
69 
getPhoneticCandidate(const OUString & rIndexEntry,const Locale & rLocale)70 OUString SAL_CALL IndexEntrySupplier::getPhoneticCandidate( const OUString& rIndexEntry,
71         const Locale& rLocale ) throw (RuntimeException)
72 {
73         if (getLocaleSpecificIndexEntrySupplier(rLocale, OUString()).is())
74             return xIES->getPhoneticCandidate(rIndexEntry, rLocale);
75         else
76             throw RuntimeException();
77 }
78 
getIndexKey(const OUString & rIndexEntry,const OUString & rPhoneticEntry,const Locale & rLocale)79 OUString SAL_CALL IndexEntrySupplier::getIndexKey( const OUString& rIndexEntry,
80         const OUString& rPhoneticEntry, const Locale& rLocale ) throw (RuntimeException)
81 {
82         if (xIES.is())
83             return xIES->getIndexKey(rIndexEntry, rPhoneticEntry, rLocale);
84         else
85             throw RuntimeException();
86 }
87 
compareIndexEntry(const OUString & rIndexEntry1,const OUString & rPhoneticEntry1,const Locale & rLocale1,const OUString & rIndexEntry2,const OUString & rPhoneticEntry2,const Locale & rLocale2)88 sal_Int16 SAL_CALL IndexEntrySupplier::compareIndexEntry(
89         const OUString& rIndexEntry1, const OUString& rPhoneticEntry1, const Locale& rLocale1,
90         const OUString& rIndexEntry2, const OUString& rPhoneticEntry2, const Locale& rLocale2 )
91         throw (com::sun::star::uno::RuntimeException)
92 {
93         if (xIES.is())
94             return xIES->compareIndexEntry(rIndexEntry1, rPhoneticEntry1, rLocale1,
95                                         rIndexEntry2, rPhoneticEntry2, rLocale2);
96         else
97             throw RuntimeException();
98 }
99 
getIndexCharacter(const OUString & rIndexEntry,const Locale & rLocale,const OUString & rSortAlgorithm)100 OUString SAL_CALL IndexEntrySupplier::getIndexCharacter( const OUString& rIndexEntry,
101         const Locale& rLocale, const OUString& rSortAlgorithm )
102         throw (RuntimeException)
103 {
104         return getLocaleSpecificIndexEntrySupplier(rLocale, rSortAlgorithm)->
105                         getIndexCharacter( rIndexEntry, rLocale, rSortAlgorithm );
106 }
107 
createLocaleSpecificIndexEntrySupplier(const OUString & name)108 sal_Bool SAL_CALL IndexEntrySupplier::createLocaleSpecificIndexEntrySupplier(const OUString& name) throw( RuntimeException )
109 {
110         Reference < XInterface > xI = xMSF->createInstance(
111             OUString::createFromAscii("com.sun.star.i18n.IndexEntrySupplier_") + name);
112 
113         if ( xI.is() ) {
114             xI->queryInterface( ::getCppuType((const Reference< com::sun::star::i18n::XExtendedIndexEntrySupplier>*)0) ) >>= xIES;
115             return xIES.is();
116         }
117         return sal_False;
118 }
119 
120 Reference < com::sun::star::i18n::XExtendedIndexEntrySupplier > SAL_CALL
getLocaleSpecificIndexEntrySupplier(const Locale & rLocale,const OUString & rSortAlgorithm)121 IndexEntrySupplier::getLocaleSpecificIndexEntrySupplier(const Locale& rLocale, const OUString& rSortAlgorithm) throw (RuntimeException)
122 {
123         if (xIES.is() && rSortAlgorithm == aSortAlgorithm && rLocale.Language == aLocale.Language &&
124                 rLocale.Country == aLocale.Country && rLocale.Variant == aLocale.Variant)
125             return xIES;
126         else if (xMSF.is()) {
127             LocaleData ld;
128             aLocale = rLocale;
129             if (rSortAlgorithm.getLength() == 0)
130                 aSortAlgorithm = ld.getDefaultIndexAlgorithm( rLocale );
131             else
132                 aSortAlgorithm = rSortAlgorithm;
133 
134             OUString module = ld.getIndexModuleByAlgorithm(rLocale, aSortAlgorithm);
135             if (module.getLength() > 0 && createLocaleSpecificIndexEntrySupplier(module))
136                 return xIES;
137 
138             sal_Int32 l = rLocale.Language.getLength();
139             sal_Int32 c = rLocale.Country.getLength();
140             sal_Int32 v = rLocale.Variant.getLength();
141             sal_Int32 a = aSortAlgorithm.getLength();
142             OUStringBuffer aBuf(l+c+v+a+4);
143 
144             if ((l > 0 && c > 0 && v > 0 && a > 0 &&
145                         // load service with name <base>_<lang>_<country>_<varian>_<algorithm>
146                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
147                                     rLocale.Country).append(under).append(rLocale.Variant).append(under).append(
148                                     aSortAlgorithm).makeStringAndClear())) ||
149                 (l > 0 && c > 0 && a > 0 &&
150                         // load service with name <base>_<lang>_<country>_<algorithm>
151                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
152                                     rLocale.Country).append(under).append(aSortAlgorithm).makeStringAndClear())) ||
153                 (l > 0 && c > 0 && a > 0 && rLocale.Language.compareToAscii("zh") == 0 &&
154                                             (rLocale.Country.compareToAscii("HK") == 0 ||
155                                             rLocale.Country.compareToAscii("MO") == 0) &&
156                         // if the country code is HK or MO, one more step to try TW.
157                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).appendAscii(
158                                     "TW").append(under).append(aSortAlgorithm).makeStringAndClear())) ||
159                 (l > 0 && a > 0 &&
160                         // load service with name <base>_<lang>_<algorithm>
161                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
162                                     aSortAlgorithm).makeStringAndClear())) ||
163                         // load service with name <base>_<algorithm>
164                 (a > 0 && createLocaleSpecificIndexEntrySupplier(aSortAlgorithm)) ||
165                         // load default service with name <base>_Unicode
166                         createLocaleSpecificIndexEntrySupplier(OUString::createFromAscii("Unicode"))) {
167                 return xIES;
168             }
169         }
170         throw RuntimeException();
171 }
172 
getIndexFollowPageWord(sal_Bool bMorePages,const Locale & rLocale)173 OUString SAL_CALL IndexEntrySupplier::getIndexFollowPageWord( sal_Bool bMorePages,
174         const Locale& rLocale ) throw (RuntimeException)
175 {
176         Sequence< OUString > aFollowPageWords = LocaleData().getFollowPageWords(rLocale);
177 
178         return (bMorePages && aFollowPageWords.getLength() > 1) ?
179             aFollowPageWords[1] : (aFollowPageWords.getLength() > 0 ?
180             aFollowPageWords[0] : OUString());
181 }
182 
183 #define implementationName "com.sun.star.i18n.IndexEntrySupplier"
184 
185 OUString SAL_CALL
getImplementationName()186 IndexEntrySupplier::getImplementationName() throw( RuntimeException )
187 {
188         return OUString::createFromAscii( implementationName );
189 }
190 
191 sal_Bool SAL_CALL
supportsService(const OUString & rServiceName)192 IndexEntrySupplier::supportsService(const OUString& rServiceName) throw( RuntimeException )
193 {
194         return rServiceName.compareToAscii(implementationName) == 0;
195 }
196 
197 Sequence< OUString > SAL_CALL
getSupportedServiceNames()198 IndexEntrySupplier::getSupportedServiceNames() throw( RuntimeException )
199 {
200         Sequence< OUString > aRet(1);
201         aRet[0] = OUString::createFromAscii( implementationName );
202         return aRet;
203 }
204 
205 } } } }
206