1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 #include <rtl/ustrbuf.hxx>
31 #include <indexentrysupplier.hxx>
32 #include <localedata.hxx>
33 
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::lang;
36 using namespace ::rtl;
37 
38 static const sal_Unicode under = sal_Unicode('_');
39 
40 namespace com { namespace sun { namespace star { namespace i18n {
41 
42 IndexEntrySupplier::IndexEntrySupplier( const Reference < XMultiServiceFactory >& rxMSF ) : xMSF( rxMSF )
43 {
44 }
45 
46 Sequence < Locale > SAL_CALL IndexEntrySupplier::getLocaleList() throw (RuntimeException)
47 {
48         return LocaleData().getAllInstalledLocaleNames();
49 }
50 
51 Sequence < OUString > SAL_CALL IndexEntrySupplier::getAlgorithmList( const Locale& rLocale ) throw (RuntimeException)
52 {
53         return LocaleData().getIndexAlgorithm(rLocale);
54 }
55 
56 sal_Bool SAL_CALL IndexEntrySupplier::loadAlgorithm( const Locale& rLocale, const OUString& SortAlgorithm,
57         sal_Int32 collatorOptions ) throw (RuntimeException)
58 {
59         Sequence < OUString > algorithmList = getAlgorithmList( rLocale );
60         for (sal_Int32 i = 0; i < algorithmList.getLength(); i++) {
61             if (algorithmList[i] == SortAlgorithm) {
62                 if (getLocaleSpecificIndexEntrySupplier(rLocale, SortAlgorithm).is())
63                     return xIES->loadAlgorithm(rLocale, SortAlgorithm, collatorOptions);
64             }
65         }
66         return sal_False;
67 }
68 
69 sal_Bool SAL_CALL IndexEntrySupplier::usePhoneticEntry( const Locale& rLocale ) throw (RuntimeException)
70 {
71         return LocaleData().hasPhonetic(rLocale);
72 }
73 
74 OUString SAL_CALL IndexEntrySupplier::getPhoneticCandidate( const OUString& rIndexEntry,
75         const Locale& rLocale ) throw (RuntimeException)
76 {
77         if (getLocaleSpecificIndexEntrySupplier(rLocale, OUString()).is())
78             return xIES->getPhoneticCandidate(rIndexEntry, rLocale);
79         else
80             throw RuntimeException();
81 }
82 
83 OUString SAL_CALL IndexEntrySupplier::getIndexKey( const OUString& rIndexEntry,
84         const OUString& rPhoneticEntry, const Locale& rLocale ) throw (RuntimeException)
85 {
86         if (xIES.is())
87             return xIES->getIndexKey(rIndexEntry, rPhoneticEntry, rLocale);
88         else
89             throw RuntimeException();
90 }
91 
92 sal_Int16 SAL_CALL IndexEntrySupplier::compareIndexEntry(
93         const OUString& rIndexEntry1, const OUString& rPhoneticEntry1, const Locale& rLocale1,
94         const OUString& rIndexEntry2, const OUString& rPhoneticEntry2, const Locale& rLocale2 )
95         throw (com::sun::star::uno::RuntimeException)
96 {
97         if (xIES.is())
98             return xIES->compareIndexEntry(rIndexEntry1, rPhoneticEntry1, rLocale1,
99                                         rIndexEntry2, rPhoneticEntry2, rLocale2);
100         else
101             throw RuntimeException();
102 }
103 
104 OUString SAL_CALL IndexEntrySupplier::getIndexCharacter( const OUString& rIndexEntry,
105         const Locale& rLocale, const OUString& rSortAlgorithm )
106         throw (RuntimeException)
107 {
108         return getLocaleSpecificIndexEntrySupplier(rLocale, rSortAlgorithm)->
109                         getIndexCharacter( rIndexEntry, rLocale, rSortAlgorithm );
110 }
111 
112 sal_Bool SAL_CALL IndexEntrySupplier::createLocaleSpecificIndexEntrySupplier(const OUString& name) throw( RuntimeException )
113 {
114         Reference < XInterface > xI = xMSF->createInstance(
115             OUString::createFromAscii("com.sun.star.i18n.IndexEntrySupplier_") + name);
116 
117         if ( xI.is() ) {
118             xI->queryInterface( ::getCppuType((const Reference< com::sun::star::i18n::XExtendedIndexEntrySupplier>*)0) ) >>= xIES;
119             return xIES.is();
120         }
121         return sal_False;
122 }
123 
124 Reference < com::sun::star::i18n::XExtendedIndexEntrySupplier > SAL_CALL
125 IndexEntrySupplier::getLocaleSpecificIndexEntrySupplier(const Locale& rLocale, const OUString& rSortAlgorithm) throw (RuntimeException)
126 {
127         if (xIES.is() && rSortAlgorithm == aSortAlgorithm && rLocale.Language == aLocale.Language &&
128                 rLocale.Country == aLocale.Country && rLocale.Variant == aLocale.Variant)
129             return xIES;
130         else if (xMSF.is()) {
131             LocaleData ld;
132             aLocale = rLocale;
133             if (rSortAlgorithm.getLength() == 0)
134                 aSortAlgorithm = ld.getDefaultIndexAlgorithm( rLocale );
135             else
136                 aSortAlgorithm = rSortAlgorithm;
137 
138             OUString module = ld.getIndexModuleByAlgorithm(rLocale, aSortAlgorithm);
139             if (module.getLength() > 0 && createLocaleSpecificIndexEntrySupplier(module))
140                 return xIES;
141 
142             sal_Int32 l = rLocale.Language.getLength();
143             sal_Int32 c = rLocale.Country.getLength();
144             sal_Int32 v = rLocale.Variant.getLength();
145             sal_Int32 a = aSortAlgorithm.getLength();
146             OUStringBuffer aBuf(l+c+v+a+4);
147 
148             if ((l > 0 && c > 0 && v > 0 && a > 0 &&
149                         // load service with name <base>_<lang>_<country>_<varian>_<algorithm>
150                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
151                                     rLocale.Country).append(under).append(rLocale.Variant).append(under).append(
152                                     aSortAlgorithm).makeStringAndClear())) ||
153                 (l > 0 && c > 0 && a > 0 &&
154                         // load service with name <base>_<lang>_<country>_<algorithm>
155                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
156                                     rLocale.Country).append(under).append(aSortAlgorithm).makeStringAndClear())) ||
157                 (l > 0 && c > 0 && a > 0 && rLocale.Language.compareToAscii("zh") == 0 &&
158                                             (rLocale.Country.compareToAscii("HK") == 0 ||
159                                             rLocale.Country.compareToAscii("MO") == 0) &&
160                         // if the country code is HK or MO, one more step to try TW.
161                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).appendAscii(
162                                     "TW").append(under).append(aSortAlgorithm).makeStringAndClear())) ||
163                 (l > 0 && a > 0 &&
164                         // load service with name <base>_<lang>_<algorithm>
165                         createLocaleSpecificIndexEntrySupplier(aBuf.append(rLocale.Language).append(under).append(
166                                     aSortAlgorithm).makeStringAndClear())) ||
167                         // load service with name <base>_<algorithm>
168                 (a > 0 && createLocaleSpecificIndexEntrySupplier(aSortAlgorithm)) ||
169                         // load default service with name <base>_Unicode
170                         createLocaleSpecificIndexEntrySupplier(OUString::createFromAscii("Unicode"))) {
171                 return xIES;
172             }
173         }
174         throw RuntimeException();
175 }
176 
177 OUString SAL_CALL IndexEntrySupplier::getIndexFollowPageWord( sal_Bool bMorePages,
178         const Locale& rLocale ) throw (RuntimeException)
179 {
180         Sequence< OUString > aFollowPageWords = LocaleData().getFollowPageWords(rLocale);
181 
182         return (bMorePages && aFollowPageWords.getLength() > 1) ?
183             aFollowPageWords[1] : (aFollowPageWords.getLength() > 0 ?
184             aFollowPageWords[0] : OUString());
185 }
186 
187 #define implementationName "com.sun.star.i18n.IndexEntrySupplier"
188 
189 OUString SAL_CALL
190 IndexEntrySupplier::getImplementationName() throw( RuntimeException )
191 {
192         return OUString::createFromAscii( implementationName );
193 }
194 
195 sal_Bool SAL_CALL
196 IndexEntrySupplier::supportsService(const OUString& rServiceName) throw( RuntimeException )
197 {
198         return rServiceName.compareToAscii(implementationName) == 0;
199 }
200 
201 Sequence< OUString > SAL_CALL
202 IndexEntrySupplier::getSupportedServiceNames() throw( RuntimeException )
203 {
204         Sequence< OUString > aRet(1);
205         aRet[0] = OUString::createFromAscii( implementationName );
206         return aRet;
207 }
208 
209 } } } }
210