/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
package com.sun.star.help;
import com.sun.star.lib.uno.helper.Factory;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.uno.XComponentContext;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.uno.Type;
import com.sun.star.uno.Any;
import com.sun.star.uno.AnyConverter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.Version;
import org.apache.lucene.store.NIOFSDirectory;
import com.sun.star.script.XInvocation;
import com.sun.star.beans.XIntrospectionAccess;
import java.io.File;
/** This class capsulates the class, that implements the minimal component and a
* factory for creating the service (__getComponentFactory
).
*/
public class HelpSearch
{
/** This class implements the component. At least the interfaces XServiceInfo,
* XTypeProvider, and XInitialization should be provided by the service.
*/
public static class _HelpSearch extends WeakBase
implements XServiceInfo, XInvocation
{
/** The service name, that must be used to get an instance of this service.
*/
static private final String __serviceName =
"com.sun.star.help.HelpSearch";
static private final String aSearchMethodName = "search";
/** The initial component contextr, that gives access to
* the service manager, supported singletons, ...
* It's often later used
*/
private XComponentContext m_cmpCtx;
/** The service manager, that gives access to all registered services.
* It's often later used
*/
private XMultiComponentFactory m_xMCF;
/** The constructor of the inner class has a XMultiServiceFactory parameter.
* @param xmultiservicefactoryInitialization A special service factory
* could be introduced while initializing.
*/
public _HelpSearch(XComponentContext xCompContext)
{
try {
m_cmpCtx = xCompContext;
m_xMCF = m_cmpCtx.getServiceManager();
}
catch( Exception e ) {
e.printStackTrace();
}
}
/** This method returns an array of all supported service names.
* @return Array of supported service names.
*/
public String[] getSupportedServiceNames()
{
return getServiceNames();
}
/** This method is a simple helper function to used in the
* static component initialisation functions as well as in
* getSupportedServiceNames.
*/
public static String[] getServiceNames()
{
String[] sSupportedServiceNames = { __serviceName };
return sSupportedServiceNames;
}
/** This method returns true, if the given service will be
* supported by the component.
* @param sServiceName Service name.
* @return True, if the given service name will be supported.
*/
public boolean supportsService( String sServiceName )
{
return sServiceName.equals( __serviceName );
}
/** Return the class name of the component.
* @return Class name of the component.
*/
public String getImplementationName()
{
return _HelpSearch.class.getName();
}
//===================================================
// XInvocation
public XIntrospectionAccess getIntrospection()
{
return null;
}
public Object invoke( String aFunctionName, java.lang.Object[] aParams,
short[][] aOutParamIndex, java.lang.Object[][] aOutParam )
throws com.sun.star.lang.IllegalArgumentException,
com.sun.star.script.CannotConvertException,
com.sun.star.reflection.InvocationTargetException
{
String[] aRet = null;
if( !aFunctionName.equals( aSearchMethodName ) )
throw new com.sun.star.lang.IllegalArgumentException();
Object[] aScoreOutArray = new Object[1];
aScoreOutArray[0] = null;
try
{
aRet = doQuery( aParams, aScoreOutArray );
}
catch( Exception e )
{
aRet = null;
}
Object aScoreArray = aScoreOutArray[0];
if( aScoreArray == null )
{
aOutParamIndex[0] = new short[0];
aOutParam[0] = new Object[0];
}
else
{
short nInParamCount = (short)aParams.length;
aOutParamIndex[0] = new short[1];
aOutParamIndex[0][0] = nInParamCount;
aOutParam[0] = new Object[1];
aOutParam[0][0] = aScoreArray;
}
Any aRetAny = new Any( new Type( String[].class ), aRet );
return aRetAny;
}
public void setValue( String aPropertyName, java.lang.Object aValue )
throws com.sun.star.beans.UnknownPropertyException,
com.sun.star.script.CannotConvertException,
com.sun.star.reflection.InvocationTargetException {
throw new com.sun.star.beans.UnknownPropertyException();
}
public Object getValue( String aPropertyName )
throws com.sun.star.beans.UnknownPropertyException {
throw new com.sun.star.beans.UnknownPropertyException();
}
public boolean hasMethod( String aMethodName ) {
boolean bRet = (aMethodName.equals( aSearchMethodName ) );
return bRet;
}
public boolean hasProperty( String aName ) {
return false;
}
// Command line interface for testing
private static String[] doQuery( Object[] args, Object[] aScoreOutArray ) throws Exception
{
String aLanguageStr = "";
String aIndexStr = "";
String aQueryStr = "";
boolean bCaptionOnly = false;
int nParamCount = args.length;
String aStrs[] = new String[nParamCount];
for( int i = 0 ; i < nParamCount ; i++ )
{
try
{
aStrs[i] = AnyConverter.toString( args[i] );
}
catch( IllegalArgumentException e )
{
aStrs[i] = "";
}
}
// TODO: Error handling
for( int i = 0 ; i < nParamCount ; i++ )
{
if ("-lang".equals(aStrs[i]) )
{
aLanguageStr = aStrs[i + 1];
i++;
}
else if( "-index".equals(aStrs[i]) )
{
aIndexStr = aStrs[i+1];
i++;
}
else if( "-query".equals(aStrs[i]) )
{
aQueryStr = aStrs[i+1];
i++;
}
else if( "-caption".equals(aStrs[i]) )
{
bCaptionOnly = true;
}
}
String[] aDocs = queryImpl( aLanguageStr, aIndexStr, aQueryStr, bCaptionOnly, aScoreOutArray );
return aDocs;
}
private static String[] queryImpl( String aLanguageStr, String aIndexStr, String aQueryStr,
boolean bCaptionOnly, Object[] aScoreOutArray ) throws Exception
{
File aIndexFile = new File( aIndexStr );
IndexReader reader = IndexReader.open( NIOFSDirectory.open( aIndexFile ), true );
Searcher searcher = new IndexSearcher( reader );
Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer(Version.LUCENE_29) : (Analyzer)new StandardAnalyzer(Version.LUCENE_29);
String aField;
if( bCaptionOnly )
aField = "caption";
else
aField = "content";
Query aQuery;
if( aQueryStr.endsWith( "*" ) )
aQuery = new WildcardQuery( new Term( aField, aQueryStr ) );
else
aQuery = new TermQuery( new Term( aField, aQueryStr ) );
// Perform search
TopDocs aHits = searcher.search( aQuery, 100 );
int nHitCount = aHits.totalHits;
String aDocs[] = new String[nHitCount];
float aScores[] = null;
aScores = new float[nHitCount];
for( int iHit = 0 ; iHit < nHitCount ; iHit++ )
{
ScoreDoc aDoc = aHits.scoreDocs[iHit];
String aPath = searcher.doc(aDoc.doc).get( "path" );
aDocs[iHit] = ( aPath != null ) ? aPath : "";
aScores[iHit] = aDoc.score;
}
aScoreOutArray[0] = aScores;
reader.close();
return aDocs;
}
}
/**
* Gives a factory for creating the service.
* This method is called by the JavaLoader
*
* @return returns a XSingleComponentFactory
for creating
* the component
* @param sImplName the name of the implementation for which a
* service is desired
* @see com.sun.star.comp.loader.JavaLoader
*/
public static XSingleComponentFactory __getComponentFactory(String sImplName)
{
XSingleComponentFactory xFactory = null;
if ( sImplName.equals( _HelpSearch.class.getName() ) )
xFactory = Factory.createComponentFactory(_HelpSearch.class,
_HelpSearch.getServiceNames());
return xFactory;
}
/** This method is a member of the interface for initializing an object
* directly after its creation.
* @param object This array of arbitrary objects will be passed to the
* component after its creation.
* @throws Exception Every exception will not be handled, but will be
* passed to the caller.
*/
public void initialize( Object[] object )
throws com.sun.star.uno.Exception {
/* The component describes what arguments its expected and in which
* order!At this point you can read the objects and can intialize
* your component using these objects.
*/
}
}