1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/processfactory.hxx>
21 #include <com/sun/star/ucb/Command.hpp>
22 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
23 #include <com/sun/star/i18n/Transliteration.hpp>
24 #include <com/sun/star/ucb/XCommandProcessor.hpp>
25 #include <com/sun/star/lang/Locale.hpp>
26 #include <com/sun/star/script/XInvocation.hpp>
28 #include <helpcompiler/HelpSearch.hxx>
32 #pragma warning(disable : 4068 4263 4264 4266)
35 #if defined(__GNUC__) && defined(HAVE_GCC_VISIBILITY_FEATURE)
36 # pragma GCC visibility push (default)
39 #if defined(__GNUC__) && defined(HAVE_GCC_VISIBILITY_FEATURE)
40 # pragma GCC visibility pop
47 #include <rtl/ustring.hxx>
51 #include <qe/Query.hxx>
52 #include <qe/DocGenerator.hxx>
53 #include "resultsetforquery.hxx"
54 #include "databases.hxx"
57 using namespace chelp
;
58 using namespace xmlsearch::excep
;
59 using namespace xmlsearch::qe
;
60 using namespace com::sun::star
;
61 using namespace com::sun::star::ucb
;
62 using namespace com::sun::star::i18n
;
63 using namespace com::sun::star::uno
;
64 using namespace com::sun::star::lang
;
72 HitItem( const OUString
& aURL
, float fScore
)
76 bool operator < ( const HitItem
& rHitItem
) const
78 return rHitItem
.m_fScore
< m_fScore
;
82 ResultSetForQuery::ResultSetForQuery( const uno::Reference
< uno::XComponentContext
>& rxContext
,
83 const uno::Reference
< XContentProvider
>& xProvider
,
85 const uno::Sequence
< beans::Property
>& seq
,
86 const uno::Sequence
< NumberedSortingInfo
>& seqSort
,
87 URLParameter
& aURLParameter
,
88 Databases
* pDatabases
)
89 : ResultSetBase( rxContext
,xProvider
,nOpenMode
,seq
,seqSort
),
90 m_aURLParameter( aURLParameter
)
92 Reference
< XExtendedTransliteration
> xTrans
= Transliteration::create( rxContext
);
93 Locale
aLocale( aURLParameter
.get_language(),
96 xTrans
->loadModule(TransliterationModules_UPPERCASE_LOWERCASE
,
99 vector
< vector
< OUString
> > queryList
;
102 OUString query
= m_aURLParameter
.get_query();
103 while( !query
.isEmpty() )
105 idx
= query
.indexOf( sal_Unicode( ' ' ) );
107 idx
= query
.getLength();
109 vector
< OUString
> currentQuery
;
110 OUString
tmp(query
.copy( 0,idx
));
111 rtl:: OUString toliterate
= tmp
;
112 Sequence
<sal_Int32
> aSeq
;
113 toliterate
= xTrans
->transliterate(
114 tmp
,0,tmp
.getLength(),aSeq
);
116 currentQuery
.push_back( toliterate
);
117 queryList
.push_back( currentQuery
);
120 if( nCpy
>= query
.getLength() )
123 query
= query
.copy( 1 + idx
);
127 vector
< OUString
> aCompleteResultVector
;
128 OUString scope
= m_aURLParameter
.get_scope();
129 bool bCaptionsOnly
= ( scope
.compareToAscii( "Heading" ) == 0 );
130 sal_Int32 hitCount
= m_aURLParameter
.get_hitCount();
132 IndexFolderIterator
aIndexFolderIt( *pDatabases
, m_aURLParameter
.get_module(), m_aURLParameter
.get_language() );
134 bool bExtension
= false;
136 vector
< vector
<HitItem
>* > aIndexFolderResultVectorVector
;
139 while( !(idxDir
= aIndexFolderIt
.nextIndexFolder( bExtension
, bTemporary
)).isEmpty() )
141 vector
<HitItem
> aIndexFolderResultVector
;
145 vector
< vector
<HitItem
>* > aQueryListResultVectorVector
;
146 set
< OUString
> aSet
,aCurrent
,aResultSet
;
148 int nQueryListSize
= queryList
.size();
149 if( nQueryListSize
> 1 )
152 for( int i
= 0; i
< nQueryListSize
; ++i
)
154 vector
<HitItem
>* pQueryResultVector
;
155 if( nQueryListSize
> 1 )
157 pQueryResultVector
= new vector
<HitItem
>();
158 aQueryListResultVectorVector
.push_back( pQueryResultVector
);
162 pQueryResultVector
= &aIndexFolderResultVector
;
164 pQueryResultVector
->reserve( hitCount
);
166 OUString aLang
= m_aURLParameter
.get_language();
167 const std::vector
< OUString
>& aListItem
= queryList
[i
];
168 OUString aNewQueryStr
= aListItem
[0];
170 vector
<float> aScoreVector
;
171 vector
<OUString
> aPathVector
;
175 HelpSearch
searcher(aLang
, idxDir
);
176 searcher
.query(aNewQueryStr
, bCaptionsOnly
, aPathVector
, aScoreVector
);
178 catch (CLuceneError
&e
)
180 SAL_WARN("xmlhelp", "CLuceneError: " << e
.what());
183 if( nQueryListSize
> 1 )
186 for (unsigned j
= 0; j
< aPathVector
.size(); ++j
) {
187 pQueryResultVector
->push_back(HitItem(aPathVector
[j
], aScoreVector
[j
]));
188 if (nQueryListSize
> 1)
189 aSet
.insert(aPathVector
[j
]);
193 if( nQueryListSize
> 1 )
201 aCurrent
= aResultSet
;
203 set_intersection( aSet
.begin(),aSet
.end(),
204 aCurrent
.begin(),aCurrent
.end(),
205 inserter(aResultSet
,aResultSet
.begin()));
210 // Combine results in aIndexFolderResultVector
211 if( nQueryListSize
> 1 )
213 for( int n
= 0 ; n
< nQueryListSize
; ++n
)
215 vector
<HitItem
>* pQueryResultVector
= aQueryListResultVectorVector
[n
];
216 vector
<HitItem
>& rQueryResultVector
= *pQueryResultVector
;
218 int nItemCount
= rQueryResultVector
.size();
219 for( int i
= 0 ; i
< nItemCount
; ++i
)
221 const HitItem
& rItem
= rQueryResultVector
[ i
];
222 if( (aResultSet
.find( rItem
.m_aURL
)) != aResultSet
.end() )
224 HitItem
aItemCopy( rItem
);
225 aItemCopy
.m_fScore
/= nQueryListSize
; // To get average score
228 // Use first pass to create entry
229 aIndexFolderResultVector
.push_back( aItemCopy
);
233 // Find entry in vector
234 int nCount
= aIndexFolderResultVector
.size();
235 for( int j
= 0 ; j
< nCount
; ++j
)
237 HitItem
& rFindItem
= aIndexFolderResultVector
[ j
];
238 if( rFindItem
.m_aURL
.equals( aItemCopy
.m_aURL
) )
240 rFindItem
.m_fScore
+= aItemCopy
.m_fScore
;
248 delete pQueryResultVector
;
251 sort( aIndexFolderResultVector
.begin(), aIndexFolderResultVector
.end() );
254 vector
<HitItem
>* pIndexFolderHitItemVector
= new vector
<HitItem
>( aIndexFolderResultVector
);
255 aIndexFolderResultVectorVector
.push_back( pIndexFolderHitItemVector
);
256 aIndexFolderResultVector
.clear();
258 catch (const Exception
&e
)
260 SAL_WARN("xmlhelp", "Exception: " << e
.Message
);
266 aIndexFolderIt
.deleteTempIndexFolder( idxDir
);
271 int nVectorCount
= aIndexFolderResultVectorVector
.size();
272 vector
<HitItem
>::size_type
* pCurrentVectorIndex
= new vector
<HitItem
>::size_type
[nVectorCount
];
273 for( int j
= 0 ; j
< nVectorCount
; ++j
)
274 pCurrentVectorIndex
[j
] = 0;
276 sal_Int32 nTotalHitCount
= m_aURLParameter
.get_hitCount();
277 sal_Int32 nHitCount
= 0;
278 while( nHitCount
< nTotalHitCount
)
280 int iVectorWithBestScore
= -1;
281 float fBestScore
= 0.0;
282 for( int k
= 0 ; k
< nVectorCount
; ++k
)
284 vector
<HitItem
>& rIndexFolderVector
= *aIndexFolderResultVectorVector
[k
];
285 if( pCurrentVectorIndex
[k
] < rIndexFolderVector
.size() )
287 const HitItem
& rItem
= rIndexFolderVector
[ pCurrentVectorIndex
[k
] ];
289 if( fBestScore
< rItem
.m_fScore
)
291 fBestScore
= rItem
.m_fScore
;
292 iVectorWithBestScore
= k
;
297 if( iVectorWithBestScore
== -1 ) // No item left at all
300 vector
<HitItem
>& rIndexFolderVector
= *aIndexFolderResultVectorVector
[iVectorWithBestScore
];
301 const HitItem
& rItem
= rIndexFolderVector
[ pCurrentVectorIndex
[iVectorWithBestScore
] ];
303 pCurrentVectorIndex
[iVectorWithBestScore
]++;
305 aCompleteResultVector
.push_back( rItem
.m_aURL
);
309 delete[] pCurrentVectorIndex
;
310 for( int n
= 0 ; n
< nVectorCount
; ++n
)
312 vector
<HitItem
>* pIndexFolderVector
= aIndexFolderResultVectorVector
[n
];
313 delete pIndexFolderVector
;
316 sal_Int32 replIdx
= OUString( "#HLP#" ).getLength();
317 OUString replWith
= OUString( "vnd.sun.star.help://" );
319 int nResultCount
= aCompleteResultVector
.size();
320 for( int r
= 0 ; r
< nResultCount
; ++r
)
322 OUString aURL
= aCompleteResultVector
[r
];
323 OUString aResultStr
= replWith
+ aURL
.copy(replIdx
);
324 m_aPath
.push_back( aResultStr
);
327 m_aItems
.resize( m_aPath
.size() );
328 m_aIdents
.resize( m_aPath
.size() );
331 aCommand
.Name
= OUString( "getPropertyValues" );
332 aCommand
.Argument
<<= m_sProperty
;
334 for( m_nRow
= 0; sal::static_int_cast
<sal_uInt32
>( m_nRow
) < m_aPath
.size(); ++m_nRow
)
338 OUString( "?Language=" ) +
339 m_aURLParameter
.get_language() +
340 OUString( "&System=" ) +
341 m_aURLParameter
.get_system();
343 uno::Reference
< XContent
> content
= queryContent();
346 uno::Reference
< XCommandProcessor
> cmd( content
,uno::UNO_QUERY
);
347 cmd
->execute( aCommand
,0,uno::Reference
< XCommandEnvironment
>( 0 ) ) >>= m_aItems
[m_nRow
]; //TODO: check return value of operator >>=
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */