Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/ucb/Command.hpp>
30 : : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
31 : : #include <com/sun/star/i18n/XExtendedTransliteration.hpp>
32 : : #include <com/sun/star/ucb/XCommandProcessor.hpp>
33 : : #include <com/sun/star/lang/Locale.hpp>
34 : : #include <com/sun/star/script/XInvocation.hpp>
35 : :
36 : : #include <l10ntools/HelpSearch.hxx>
37 : :
38 : : #if defined _MSC_VER
39 : : #pragma warning(push)
40 : : #pragma warning(disable : 4068 4263 4264 4266)
41 : : #endif
42 : :
43 : : #include <CLucene.h>
44 : :
45 : : #if defined _MSC_VER
46 : : #pragma warning(pop)
47 : : #endif
48 : :
49 : : #include <rtl/oustringostreaminserter.hxx>
50 : :
51 : : #include <algorithm>
52 : : #include <set>
53 : :
54 : : #include <qe/Query.hxx>
55 : : #include <qe/DocGenerator.hxx>
56 : : #include "resultsetforquery.hxx"
57 : : #include "databases.hxx"
58 : :
59 : : using namespace std;
60 : : using namespace chelp;
61 : : using namespace xmlsearch::excep;
62 : : using namespace xmlsearch::qe;
63 : : using namespace com::sun::star;
64 : : using namespace com::sun::star::ucb;
65 : : using namespace com::sun::star::i18n;
66 : : using namespace com::sun::star::uno;
67 : : using namespace com::sun::star::lang;
68 : :
69 : 0 : struct HitItem
70 : : {
71 : : rtl::OUString m_aURL;
72 : : float m_fScore;
73 : :
74 : : HitItem( void ) {}
75 : 0 : HitItem( const rtl::OUString& aURL, float fScore )
76 : : : m_aURL( aURL )
77 : 0 : , m_fScore( fScore )
78 : 0 : {}
79 : 0 : bool operator < ( const HitItem& rHitItem ) const
80 : : {
81 : 0 : return rHitItem.m_fScore < m_fScore;
82 : : }
83 : : };
84 : :
85 : 0 : ResultSetForQuery::ResultSetForQuery( const uno::Reference< lang::XMultiServiceFactory >& xMSF,
86 : : const uno::Reference< XContentProvider >& xProvider,
87 : : sal_Int32 nOpenMode,
88 : : const uno::Sequence< beans::Property >& seq,
89 : : const uno::Sequence< NumberedSortingInfo >& seqSort,
90 : : URLParameter& aURLParameter,
91 : : Databases* pDatabases )
92 : : : ResultSetBase( xMSF,xProvider,nOpenMode,seq,seqSort ),
93 : 0 : m_aURLParameter( aURLParameter )
94 : : {
95 : : Reference< XTransliteration > xTrans(
96 [ # # ]: 0 : xMSF->createInstance( rtl::OUString( "com.sun.star.i18n.Transliteration" ) ),
97 [ # # ][ # # ]: 0 : UNO_QUERY );
98 : : Locale aLocale( aURLParameter.get_language(),
99 : : rtl::OUString(),
100 [ # # ]: 0 : rtl::OUString() );
101 [ # # ]: 0 : if(xTrans.is())
102 [ # # ]: 0 : xTrans->loadModule(TransliterationModules_UPPERCASE_LOWERCASE,
103 [ # # ]: 0 : aLocale );
104 : :
105 [ # # ]: 0 : vector< vector< rtl::OUString > > queryList;
106 : : {
107 : : sal_Int32 idx;
108 : 0 : rtl::OUString query = m_aURLParameter.get_query();
109 [ # # ]: 0 : while( !query.isEmpty() )
110 : : {
111 : 0 : idx = query.indexOf( sal_Unicode( ' ' ) );
112 [ # # ]: 0 : if( idx == -1 )
113 : 0 : idx = query.getLength();
114 : :
115 [ # # ]: 0 : vector< rtl::OUString > currentQuery;
116 : 0 : rtl::OUString tmp(query.copy( 0,idx ));
117 : 0 : rtl:: OUString toliterate = tmp;
118 [ # # ]: 0 : if(xTrans.is()) {
119 [ # # ]: 0 : Sequence<sal_Int32> aSeq;
120 [ # # ]: 0 : toliterate = xTrans->transliterate(
121 [ # # ][ # # ]: 0 : tmp,0,tmp.getLength(),aSeq);
122 : : }
123 : :
124 [ # # ]: 0 : currentQuery.push_back( toliterate );
125 [ # # ]: 0 : queryList.push_back( currentQuery );
126 : :
127 : 0 : int nCpy = 1 + idx;
128 [ # # ]: 0 : if( nCpy >= query.getLength() )
129 : 0 : query = rtl::OUString();
130 : : else
131 : 0 : query = query.copy( 1 + idx );
132 : 0 : }
133 : : }
134 : :
135 [ # # ]: 0 : vector< rtl::OUString > aCompleteResultVector;
136 : 0 : rtl::OUString scope = m_aURLParameter.get_scope();
137 : 0 : bool bCaptionsOnly = ( scope.compareToAscii( "Heading" ) == 0 );
138 : 0 : sal_Int32 hitCount = m_aURLParameter.get_hitCount();
139 : :
140 [ # # ][ # # ]: 0 : IndexFolderIterator aIndexFolderIt( *pDatabases, m_aURLParameter.get_module(), m_aURLParameter.get_language() );
141 : 0 : rtl::OUString idxDir;
142 : 0 : bool bExtension = false;
143 : 0 : int iDir = 0;
144 [ # # ]: 0 : vector< vector<HitItem>* > aIndexFolderResultVectorVector;
145 : :
146 : : bool bTemporary;
147 [ # # ][ # # ]: 0 : while( !(idxDir = aIndexFolderIt.nextIndexFolder( bExtension, bTemporary )).isEmpty() )
148 : : {
149 [ # # ]: 0 : vector<HitItem> aIndexFolderResultVector;
150 : :
151 : : try
152 : : {
153 [ # # ]: 0 : vector< vector<HitItem>* > aQueryListResultVectorVector;
154 [ # # ][ # # ]: 0 : set< rtl::OUString > aSet,aCurrent,aResultSet;
[ # # ]
155 : :
156 : 0 : int nQueryListSize = queryList.size();
157 [ # # ]: 0 : if( nQueryListSize > 1 )
158 : 0 : hitCount = 2000;
159 : :
160 [ # # ]: 0 : for( int i = 0; i < nQueryListSize; ++i )
161 : : {
162 : : vector<HitItem>* pQueryResultVector;
163 [ # # ]: 0 : if( nQueryListSize > 1 )
164 : : {
165 [ # # ][ # # ]: 0 : pQueryResultVector = new vector<HitItem>();
166 [ # # ]: 0 : aQueryListResultVectorVector.push_back( pQueryResultVector );
167 : : }
168 : : else
169 : : {
170 : 0 : pQueryResultVector = &aIndexFolderResultVector;
171 : : }
172 [ # # ]: 0 : pQueryResultVector->reserve( hitCount );
173 : :
174 [ # # ]: 0 : rtl::OUString aLang = m_aURLParameter.get_language();
175 : 0 : const std::vector< rtl::OUString >& aListItem = queryList[i];
176 : 0 : ::rtl::OUString aNewQueryStr = aListItem[0];
177 : :
178 [ # # ]: 0 : vector<float> aScoreVector;
179 [ # # ]: 0 : vector<rtl::OUString> aPathVector;
180 : :
181 : : try
182 : : {
183 [ # # ]: 0 : HelpSearch searcher(aLang, idxDir);
184 [ # # ][ # # ]: 0 : searcher.query(aNewQueryStr, bCaptionsOnly, aPathVector, aScoreVector);
[ # # ]
185 : : }
186 : 0 : catch (CLuceneError &e)
187 : : {
188 : : SAL_WARN("xmlhelp", "CLuceneError: " << e.what());
189 : : }
190 : :
191 [ # # ]: 0 : if( nQueryListSize > 1 )
192 : 0 : aSet.clear();
193 : :
194 [ # # ]: 0 : for (unsigned j = 0; j < aPathVector.size(); ++j) {
195 [ # # ][ # # ]: 0 : pQueryResultVector->push_back(HitItem(aPathVector[j], aScoreVector[j]));
196 [ # # ]: 0 : if (nQueryListSize > 1)
197 [ # # ]: 0 : aSet.insert(aPathVector[j]);
198 : : }
199 : :
200 : : // intersect
201 [ # # ]: 0 : if( nQueryListSize > 1 )
202 : : {
203 [ # # ]: 0 : if( i == 0 )
204 : : {
205 [ # # ]: 0 : aResultSet = aSet;
206 : : }
207 : : else
208 : : {
209 [ # # ]: 0 : aCurrent = aResultSet;
210 : 0 : aResultSet.clear();
211 : : set_intersection( aSet.begin(),aSet.end(),
212 : : aCurrent.begin(),aCurrent.end(),
213 [ # # ][ # # ]: 0 : inserter(aResultSet,aResultSet.begin()));
214 : : }
215 : : }
216 : 0 : }
217 : :
218 : : // Combine results in aIndexFolderResultVector
219 [ # # ]: 0 : if( nQueryListSize > 1 )
220 : : {
221 [ # # ]: 0 : for( int n = 0 ; n < nQueryListSize ; ++n )
222 : : {
223 : 0 : vector<HitItem>* pQueryResultVector = aQueryListResultVectorVector[n];
224 : 0 : vector<HitItem>& rQueryResultVector = *pQueryResultVector;
225 : :
226 : 0 : int nItemCount = rQueryResultVector.size();
227 [ # # ]: 0 : for( int i = 0 ; i < nItemCount ; ++i )
228 : : {
229 : 0 : const HitItem& rItem = rQueryResultVector[ i ];
230 : 0 : set< rtl::OUString >::iterator it;
231 [ # # ][ # # ]: 0 : if( (it = aResultSet.find( rItem.m_aURL )) != aResultSet.end() )
232 : : {
233 : 0 : HitItem aItemCopy( rItem );
234 : 0 : aItemCopy.m_fScore /= nQueryListSize; // To get average score
235 [ # # ]: 0 : if( n == 0 )
236 : : {
237 : : // Use first pass to create entry
238 [ # # ]: 0 : aIndexFolderResultVector.push_back( aItemCopy );
239 : : }
240 : : else
241 : : {
242 : : // Find entry in vector
243 : 0 : int nCount = aIndexFolderResultVector.size();
244 [ # # ]: 0 : for( int j = 0 ; j < nCount ; ++j )
245 : : {
246 : 0 : HitItem& rFindItem = aIndexFolderResultVector[ j ];
247 [ # # ]: 0 : if( rFindItem.m_aURL.equals( aItemCopy.m_aURL ) )
248 : : {
249 : 0 : rFindItem.m_fScore += aItemCopy.m_fScore;
250 : 0 : break;
251 : : }
252 : : }
253 : 0 : }
254 : : }
255 : : }
256 : :
257 [ # # ]: 0 : delete pQueryResultVector;
258 : : }
259 : :
260 [ # # ]: 0 : sort( aIndexFolderResultVector.begin(), aIndexFolderResultVector.end() );
261 : : }
262 : :
263 [ # # ][ # # ]: 0 : vector<HitItem>* pIndexFolderHitItemVector = new vector<HitItem>( aIndexFolderResultVector );
264 [ # # ]: 0 : aIndexFolderResultVectorVector.push_back( pIndexFolderHitItemVector );
265 [ # # ]: 0 : aIndexFolderResultVector.clear();
266 : : }
267 [ # # ]: 0 : catch (const Exception &e)
268 : : {
269 : : SAL_WARN("xmlhelp", "Exception: " << e.Message);
270 : : }
271 : :
272 : 0 : ++iDir;
273 : :
274 [ # # ]: 0 : if( bTemporary )
275 [ # # ]: 0 : aIndexFolderIt.deleteTempIndexFolder( idxDir );
276 : :
277 : 0 : } // Iterator
278 : :
279 : :
280 : 0 : int nVectorCount = aIndexFolderResultVectorVector.size();
281 [ # # ]: 0 : vector<HitItem>::size_type* pCurrentVectorIndex = new vector<HitItem>::size_type[nVectorCount];
282 [ # # ]: 0 : for( int j = 0 ; j < nVectorCount ; ++j )
283 : 0 : pCurrentVectorIndex[j] = 0;
284 : :
285 : 0 : sal_Int32 nTotalHitCount = m_aURLParameter.get_hitCount();
286 : 0 : sal_Int32 nHitCount = 0;
287 [ # # ]: 0 : while( nHitCount < nTotalHitCount )
288 : : {
289 : 0 : int iVectorWithBestScore = -1;
290 : 0 : float fBestScore = 0.0;
291 [ # # ]: 0 : for( int k = 0 ; k < nVectorCount ; ++k )
292 : : {
293 : 0 : vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[k];
294 [ # # ]: 0 : if( pCurrentVectorIndex[k] < rIndexFolderVector.size() )
295 : : {
296 : 0 : const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[k] ];
297 : :
298 [ # # ]: 0 : if( fBestScore < rItem.m_fScore )
299 : : {
300 : 0 : fBestScore = rItem.m_fScore;
301 : 0 : iVectorWithBestScore = k;
302 : : }
303 : : }
304 : : }
305 : :
306 [ # # ]: 0 : if( iVectorWithBestScore == -1 ) // No item left at all
307 : 0 : break;
308 : :
309 : 0 : vector<HitItem>& rIndexFolderVector = *aIndexFolderResultVectorVector[iVectorWithBestScore];
310 : 0 : const HitItem& rItem = rIndexFolderVector[ pCurrentVectorIndex[iVectorWithBestScore] ];
311 : :
312 : 0 : pCurrentVectorIndex[iVectorWithBestScore]++;
313 : :
314 [ # # ]: 0 : aCompleteResultVector.push_back( rItem.m_aURL );
315 : 0 : ++nHitCount;
316 : : }
317 : :
318 [ # # ]: 0 : delete[] pCurrentVectorIndex;
319 [ # # ]: 0 : for( int n = 0 ; n < nVectorCount ; ++n )
320 : : {
321 : 0 : vector<HitItem>* pIndexFolderVector = aIndexFolderResultVectorVector[n];
322 [ # # ]: 0 : delete pIndexFolderVector;
323 : : }
324 : :
325 : 0 : sal_Int32 replIdx = rtl::OUString( "#HLP#" ).getLength();
326 : 0 : rtl::OUString replWith = rtl::OUString( "vnd.sun.star.help://" );
327 : :
328 : 0 : int nResultCount = aCompleteResultVector.size();
329 [ # # ]: 0 : for( int r = 0 ; r < nResultCount ; ++r )
330 : : {
331 : 0 : rtl::OUString aURL = aCompleteResultVector[r];
332 : 0 : rtl::OUString aResultStr = replWith + aURL.copy(replIdx);
333 [ # # ]: 0 : m_aPath.push_back( aResultStr );
334 : 0 : }
335 : :
336 [ # # ]: 0 : m_aItems.resize( m_aPath.size() );
337 [ # # ]: 0 : m_aIdents.resize( m_aPath.size() );
338 : :
339 : 0 : Command aCommand;
340 : 0 : aCommand.Name = rtl::OUString( "getPropertyValues" );
341 [ # # ]: 0 : aCommand.Argument <<= m_sProperty;
342 : :
343 [ # # ]: 0 : for( m_nRow = 0; sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aPath.size(); ++m_nRow )
344 : : {
345 : 0 : m_aPath[m_nRow] =
346 : 0 : m_aPath[m_nRow] +
347 : : rtl::OUString( "?Language=" ) +
348 : : m_aURLParameter.get_language() +
349 : : rtl::OUString( "&System=" ) +
350 [ # # ]: 0 : m_aURLParameter.get_system();
351 : :
352 [ # # ]: 0 : uno::Reference< XContent > content = queryContent();
353 [ # # ]: 0 : if( content.is() )
354 : : {
355 [ # # ]: 0 : uno::Reference< XCommandProcessor > cmd( content,uno::UNO_QUERY );
356 [ # # ][ # # ]: 0 : cmd->execute( aCommand,0,uno::Reference< XCommandEnvironment >( 0 ) ) >>= m_aItems[m_nRow]; //TODO: check return value of operator >>=
[ # # ][ # # ]
357 : : }
358 : 0 : }
359 [ # # ]: 0 : m_nRow = 0xffffffff;
360 : 0 : }
361 : :
362 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|