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
;
71 HitItem(const OUString
& aURL
, float fScore
)
75 bool operator < ( const HitItem
& rHitItem
) const
77 return rHitItem
.m_fScore
< m_fScore
;
81 ResultSetForQuery::ResultSetForQuery( const uno::Reference
< uno::XComponentContext
>& rxContext
,
82 const uno::Reference
< XContentProvider
>& xProvider
,
84 const uno::Sequence
< beans::Property
>& seq
,
85 const uno::Sequence
< NumberedSortingInfo
>& seqSort
,
86 URLParameter
& aURLParameter
,
87 Databases
* pDatabases
)
88 : ResultSetBase( rxContext
,xProvider
,nOpenMode
,seq
,seqSort
),
89 m_aURLParameter( aURLParameter
)
91 Reference
< XExtendedTransliteration
> xTrans
= Transliteration::create( rxContext
);
92 Locale
aLocale( aURLParameter
.get_language(),
95 xTrans
->loadModule(TransliterationModules_UPPERCASE_LOWERCASE
,
98 vector
< vector
< OUString
> > queryList
;
101 OUString query
= m_aURLParameter
.get_query();
102 while( !query
.isEmpty() )
104 idx
= query
.indexOf( ' ' );
106 idx
= query
.getLength();
108 vector
< OUString
> currentQuery
;
109 OUString
tmp(query
.copy( 0,idx
));
110 Sequence
<sal_Int32
> aSeq
;
111 OUString toliterate
= xTrans
->transliterate(
112 tmp
,0,tmp
.getLength(),aSeq
);
114 currentQuery
.push_back( toliterate
);
115 queryList
.push_back( currentQuery
);
118 if( nCpy
>= query
.getLength() )
121 query
= query
.copy( 1 + idx
);
125 vector
< OUString
> aCompleteResultVector
;
126 OUString scope
= m_aURLParameter
.get_scope();
127 bool bCaptionsOnly
= scope
== "Heading";
128 sal_Int32 hitCount
= m_aURLParameter
.get_hitCount();
130 IndexFolderIterator
aIndexFolderIt( *pDatabases
, m_aURLParameter
.get_module(), m_aURLParameter
.get_language() );
132 bool bExtension
= false;
134 vector
< vector
<HitItem
>* > aIndexFolderResultVectorVector
;
137 while( !(idxDir
= aIndexFolderIt
.nextIndexFolder( bExtension
, bTemporary
)).isEmpty() )
139 vector
<HitItem
> aIndexFolderResultVector
;
143 vector
< vector
<HitItem
>* > aQueryListResultVectorVector
;
144 set
< OUString
> aSet
,aCurrent
,aResultSet
;
146 int nQueryListSize
= queryList
.size();
147 if( nQueryListSize
> 1 )
150 for( int i
= 0; i
< nQueryListSize
; ++i
)
152 vector
<HitItem
>* pQueryResultVector
;
153 if( nQueryListSize
> 1 )
155 pQueryResultVector
= new vector
<HitItem
>();
156 aQueryListResultVectorVector
.push_back( pQueryResultVector
);
160 pQueryResultVector
= &aIndexFolderResultVector
;
162 pQueryResultVector
->reserve( hitCount
);
164 const std::vector
< OUString
>& aListItem
= queryList
[i
];
165 OUString aNewQueryStr
= aListItem
[0];
167 vector
<float> aScoreVector
;
168 vector
<OUString
> aPathVector
;
172 HelpSearch
searcher(idxDir
);
173 searcher
.query(aNewQueryStr
, bCaptionsOnly
, aPathVector
, aScoreVector
);
175 catch (CLuceneError
&e
)
177 SAL_WARN("xmlhelp", "CLuceneError: " << e
.what());
180 if( nQueryListSize
> 1 )
183 for (unsigned j
= 0; j
< aPathVector
.size(); ++j
) {
184 pQueryResultVector
->push_back(HitItem(aPathVector
[j
], aScoreVector
[j
]));
185 if (nQueryListSize
> 1)
186 aSet
.insert(aPathVector
[j
]);
190 if( nQueryListSize
> 1 )
198 aCurrent
= aResultSet
;
200 set_intersection( aSet
.begin(),aSet
.end(),
201 aCurrent
.begin(),aCurrent
.end(),
202 inserter(aResultSet
,aResultSet
.begin()));
207 // Combine results in aIndexFolderResultVector
208 if( nQueryListSize
> 1 )
210 for( int n
= 0 ; n
< nQueryListSize
; ++n
)
212 vector
<HitItem
>* pQueryResultVector
= aQueryListResultVectorVector
[n
];
213 vector
<HitItem
>& rQueryResultVector
= *pQueryResultVector
;
215 int nItemCount
= rQueryResultVector
.size();
216 for( int i
= 0 ; i
< nItemCount
; ++i
)
218 const HitItem
& rItem
= rQueryResultVector
[ i
];
219 if( (aResultSet
.find( rItem
.m_aURL
)) != aResultSet
.end() )
221 HitItem
aItemCopy( rItem
);
222 aItemCopy
.m_fScore
/= nQueryListSize
; // To get average score
225 // Use first pass to create entry
226 aIndexFolderResultVector
.push_back( aItemCopy
);
230 // Find entry in vector
231 int nCount
= aIndexFolderResultVector
.size();
232 for( int j
= 0 ; j
< nCount
; ++j
)
234 HitItem
& rFindItem
= aIndexFolderResultVector
[ j
];
235 if( rFindItem
.m_aURL
.equals( aItemCopy
.m_aURL
) )
237 rFindItem
.m_fScore
+= aItemCopy
.m_fScore
;
245 delete pQueryResultVector
;
248 sort( aIndexFolderResultVector
.begin(), aIndexFolderResultVector
.end() );
251 vector
<HitItem
>* pIndexFolderHitItemVector
= new vector
<HitItem
>( aIndexFolderResultVector
);
252 aIndexFolderResultVectorVector
.push_back( pIndexFolderHitItemVector
);
253 aIndexFolderResultVector
.clear();
255 catch (const Exception
&e
)
257 SAL_WARN("xmlhelp", "Exception: " << e
.Message
);
263 aIndexFolderIt
.deleteTempIndexFolder( idxDir
);
268 int nVectorCount
= aIndexFolderResultVectorVector
.size();
269 vector
<HitItem
>::size_type
* pCurrentVectorIndex
= new vector
<HitItem
>::size_type
[nVectorCount
];
270 for( int j
= 0 ; j
< nVectorCount
; ++j
)
271 pCurrentVectorIndex
[j
] = 0;
273 sal_Int32 nTotalHitCount
= m_aURLParameter
.get_hitCount();
274 sal_Int32 nHitCount
= 0;
275 while( nHitCount
< nTotalHitCount
)
277 int iVectorWithBestScore
= -1;
278 float fBestScore
= 0.0;
279 for( int k
= 0 ; k
< nVectorCount
; ++k
)
281 vector
<HitItem
>& rIndexFolderVector
= *aIndexFolderResultVectorVector
[k
];
282 if( pCurrentVectorIndex
[k
] < rIndexFolderVector
.size() )
284 const HitItem
& rItem
= rIndexFolderVector
[ pCurrentVectorIndex
[k
] ];
286 if( fBestScore
< rItem
.m_fScore
)
288 fBestScore
= rItem
.m_fScore
;
289 iVectorWithBestScore
= k
;
294 if( iVectorWithBestScore
== -1 ) // No item left at all
297 vector
<HitItem
>& rIndexFolderVector
= *aIndexFolderResultVectorVector
[iVectorWithBestScore
];
298 const HitItem
& rItem
= rIndexFolderVector
[ pCurrentVectorIndex
[iVectorWithBestScore
] ];
300 pCurrentVectorIndex
[iVectorWithBestScore
]++;
302 aCompleteResultVector
.push_back( rItem
.m_aURL
);
306 delete[] pCurrentVectorIndex
;
307 for( int n
= 0 ; n
< nVectorCount
; ++n
)
309 vector
<HitItem
>* pIndexFolderVector
= aIndexFolderResultVectorVector
[n
];
310 delete pIndexFolderVector
;
313 sal_Int32 replIdx
= OUString( "#HLP#" ).getLength();
314 OUString replWith
= "vnd.sun.star.help://";
316 int nResultCount
= aCompleteResultVector
.size();
317 for( int r
= 0 ; r
< nResultCount
; ++r
)
319 OUString aURL
= aCompleteResultVector
[r
];
320 OUString aResultStr
= replWith
+ aURL
.copy(replIdx
);
321 m_aPath
.push_back( aResultStr
);
324 m_aItems
.resize( m_aPath
.size() );
325 m_aIdents
.resize( m_aPath
.size() );
328 aCommand
.Name
= "getPropertyValues";
329 aCommand
.Argument
<<= m_sProperty
;
331 for( m_nRow
= 0; sal::static_int_cast
<sal_uInt32
>( m_nRow
) < m_aPath
.size(); ++m_nRow
)
336 m_aURLParameter
.get_language() +
338 m_aURLParameter
.get_system();
340 uno::Reference
< XContent
> content
= queryContent();
343 uno::Reference
< XCommandProcessor
> cmd( content
,uno::UNO_QUERY
);
344 cmd
->execute( aCommand
,0,uno::Reference
< XCommandEnvironment
>( 0 ) ) >>= m_aItems
[m_nRow
]; //TODO: check return value of operator >>=
350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */