1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.help;
25 
26 import com.sun.star.lib.uno.helper.Factory;
27 import com.sun.star.lang.XMultiComponentFactory;
28 import com.sun.star.lang.XSingleComponentFactory;
29 import com.sun.star.lib.uno.helper.WeakBase;
30 import com.sun.star.uno.XComponentContext;
31 import com.sun.star.registry.XRegistryKey;
32 import com.sun.star.lang.XServiceInfo;
33 import com.sun.star.uno.Type;
34 import com.sun.star.uno.Any;
35 import com.sun.star.uno.AnyConverter;
36 
37 import org.apache.lucene.analysis.Analyzer;
38 import org.apache.lucene.analysis.standard.StandardAnalyzer;
39 import org.apache.lucene.analysis.cjk.CJKAnalyzer;
40 import org.apache.lucene.document.Document;
41 import org.apache.lucene.index.IndexReader;
42 import org.apache.lucene.index.Term;
43 import org.apache.lucene.search.TopDocs;
44 import org.apache.lucene.search.IndexSearcher;
45 import org.apache.lucene.search.Query;
46 import org.apache.lucene.search.Searcher;
47 import org.apache.lucene.search.ScoreDoc;
48 import org.apache.lucene.search.TermQuery;
49 import org.apache.lucene.search.WildcardQuery;
50 import org.apache.lucene.util.Version;
51 import org.apache.lucene.store.NIOFSDirectory;
52 
53 import com.sun.star.script.XInvocation;
54 import com.sun.star.beans.XIntrospectionAccess;
55 
56 import java.io.File;
57 
58 /** This class capsulates the class, that implements the minimal component and a
59  * factory for creating the service (<CODE>__getComponentFactory</CODE>).
60  */
61 public class HelpSearch
62 {
63     /** This class implements the component. At least the interfaces XServiceInfo,
64      * XTypeProvider, and XInitialization should be provided by the service.
65      */
66     public static class _HelpSearch extends WeakBase
67         implements XServiceInfo, XInvocation
68 	{
69         /** The service name, that must be used to get an instance of this service.
70          */
71 		static private final String __serviceName =
72 	        "com.sun.star.help.HelpSearch";
73 		static private final String aSearchMethodName = "search";
74 
75         /** The initial component contextr, that gives access to
76          * the service manager, supported singletons, ...
77          * It's often later used
78          */
79         private XComponentContext m_cmpCtx;
80 
81         /** The service manager, that gives access to all registered services.
82          * It's often later used
83          */
84         private XMultiComponentFactory m_xMCF;
85 
86         /** The constructor of the inner class has a XMultiServiceFactory parameter.
87          * @param xmultiservicefactoryInitialization A special service factory
88          * could be introduced while initializing.
89          */
_HelpSearch(XComponentContext xCompContext)90         public _HelpSearch(XComponentContext xCompContext)
91 		{
92             try {
93                 m_cmpCtx = xCompContext;
94                 m_xMCF = m_cmpCtx.getServiceManager();
95             }
96             catch( Exception e ) {
97                 e.printStackTrace();
98             }
99         }
100 
101         /** This method returns an array of all supported service names.
102          * @return Array of supported service names.
103          */
getSupportedServiceNames()104         public String[] getSupportedServiceNames()
105 		{
106             return getServiceNames();
107         }
108 
109         /** This method is a simple helper function to used in the
110          * static component initialisation functions as well as in
111          * getSupportedServiceNames.
112          */
getServiceNames()113         public static String[] getServiceNames()
114 		{
115             String[] sSupportedServiceNames = { __serviceName };
116             return sSupportedServiceNames;
117         }
118 
119         /** This method returns true, if the given service will be
120          * supported by the component.
121          * @param sServiceName Service name.
122          * @return True, if the given service name will be supported.
123          */
supportsService( String sServiceName )124         public boolean supportsService( String sServiceName )
125 		{
126             return sServiceName.equals( __serviceName );
127         }
128 
129         /** Return the class name of the component.
130          * @return Class name of the component.
131          */
getImplementationName()132         public String getImplementationName()
133 		{
134             return  _HelpSearch.class.getName();
135         }
136 
137 		//===================================================
138 		// XInvocation
getIntrospection()139 		public XIntrospectionAccess getIntrospection()
140 		{
141             return  null;
142         }
143 
invoke( String aFunctionName, java.lang.Object[] aParams, short[][] aOutParamIndex, java.lang.Object[][] aOutParam )144 		public Object invoke( String aFunctionName, java.lang.Object[] aParams,
145 			short[][] aOutParamIndex, java.lang.Object[][] aOutParam )
146 				throws	com.sun.star.lang.IllegalArgumentException,
147 						com.sun.star.script.CannotConvertException,
148 						com.sun.star.reflection.InvocationTargetException
149 		{
150 			String[] aRet = null;
151 			if( !aFunctionName.equals( aSearchMethodName ) )
152 			    throw new com.sun.star.lang.IllegalArgumentException();
153 
154 			Object[] aScoreOutArray = new Object[1];
155 			aScoreOutArray[0] = null;
156 			try
157 			{
158 			    aRet =  doQuery( aParams, aScoreOutArray );
159 			}
160 			catch( Exception e )
161 			{
162 			    aRet = null;
163 			}
164 
165 			Object aScoreArray = aScoreOutArray[0];
166 			if( aScoreArray == null )
167 			{
168 				aOutParamIndex[0] = new short[0];
169 				aOutParam[0] = new Object[0];
170 			}
171 			else
172 			{
173 				short nInParamCount = (short)aParams.length;
174 				aOutParamIndex[0] = new short[1];
175 				aOutParamIndex[0][0] = nInParamCount;
176 				aOutParam[0] = new Object[1];
177 				aOutParam[0][0] = aScoreArray;
178 			}
179 
180 			Any aRetAny = new Any( new Type( String[].class ), aRet );
181 			return aRetAny;
182 		}
183 
setValue( String aPropertyName, java.lang.Object aValue )184 		public void setValue( String aPropertyName, java.lang.Object aValue )
185 			throws	com.sun.star.beans.UnknownPropertyException,
186 					com.sun.star.script.CannotConvertException,
187 					com.sun.star.reflection.InvocationTargetException {
188 			throw new com.sun.star.beans.UnknownPropertyException();
189 		}
190 
getValue( String aPropertyName )191 		public Object getValue( String aPropertyName )
192 			throws com.sun.star.beans.UnknownPropertyException {
193 			throw new com.sun.star.beans.UnknownPropertyException();
194 		}
195 
hasMethod( String aMethodName )196 		public boolean hasMethod( String aMethodName ) {
197 			boolean bRet = (aMethodName.equals( aSearchMethodName ) );
198 			return bRet;
199 		}
hasProperty( String aName )200 		public boolean hasProperty( String aName ) {
201 			return false;
202 		}
203 
204 		// Command line interface for testing
doQuery( Object[] args, Object[] aScoreOutArray )205 		private static String[] doQuery( Object[] args, Object[] aScoreOutArray ) throws Exception
206 		{
207  			String aLanguageStr = "";
208  			String aIndexStr = "";
209 			String aQueryStr = "";
210 			boolean bCaptionOnly = false;
211 
212 			int nParamCount = args.length;
213 			String aStrs[] = new String[nParamCount];
214 			for( int i = 0 ; i < nParamCount ; i++ )
215 			{
216 				try
217 				{
218 					aStrs[i] = AnyConverter.toString( args[i] );
219 				}
220 				catch( IllegalArgumentException e )
221 				{
222 					aStrs[i] = "";
223 				}
224 			}
225 
226 			// TODO: Error handling
227 			for( int i = 0 ; i < nParamCount ; i++ )
228 			{
229                 if ("-lang".equals(aStrs[i]) )
230 				{
231                     aLanguageStr = aStrs[i + 1];
232                     i++;
233 				}
234 				else if( "-index".equals(aStrs[i]) )
235 				{
236 					aIndexStr = aStrs[i+1];
237 					i++;
238 				}
239 				else if( "-query".equals(aStrs[i]) )
240 				{
241 					aQueryStr = aStrs[i+1];
242 					i++;
243 				}
244 				else if( "-caption".equals(aStrs[i]) )
245 				{
246 					bCaptionOnly = true;
247 				}
248 			}
249 			String[] aDocs = queryImpl( aLanguageStr, aIndexStr, aQueryStr, bCaptionOnly, aScoreOutArray );
250 
251 			return aDocs;
252         }
253 
queryImpl( String aLanguageStr, String aIndexStr, String aQueryStr, boolean bCaptionOnly, Object[] aScoreOutArray )254 		private static String[] queryImpl( String aLanguageStr, String aIndexStr, String aQueryStr,
255 			boolean bCaptionOnly, Object[] aScoreOutArray ) throws Exception
256 		{
257 			File aIndexFile = new File( aIndexStr );
258 			IndexReader reader = IndexReader.open( NIOFSDirectory.open( aIndexFile ), true );
259 			Searcher searcher = new IndexSearcher( reader );
260 			Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer(Version.LUCENE_29) : (Analyzer)new StandardAnalyzer(Version.LUCENE_29);
261 
262 			String aField;
263 			if( bCaptionOnly )
264 				aField = "caption";
265 			else
266 				aField = "content";
267 
268 			Query aQuery;
269 			if( aQueryStr.endsWith( "*" ) )
270 				aQuery = new WildcardQuery( new Term( aField, aQueryStr ) );
271 			else
272 				aQuery = new TermQuery( new Term( aField, aQueryStr ) );
273 
274 			// Perform search
275 			TopDocs aHits = searcher.search( aQuery, 100 );
276 			int nHitCount = aHits.scoreDocs.length;
277 
278 			String aDocs[] = new String[nHitCount];
279 			float aScores[] = null;
280 			aScores = new float[nHitCount];
281 			for( int iHit = 0 ; iHit < nHitCount ; iHit++ )
282 			{
283 				ScoreDoc aDoc = aHits.scoreDocs[iHit];
284 				String aPath = searcher.doc(aDoc.doc).get( "path" );
285 				aDocs[iHit] = ( aPath != null ) ? aPath : "";
286 				aScores[iHit] = aDoc.score;
287 			}
288 			aScoreOutArray[0] = aScores;
289 
290 			reader.close();
291 
292 			return aDocs;
293 		}
294     }
295 
296     /**
297      * Gives a factory for creating the service.
298      * This method is called by the <code>JavaLoader</code>
299      * <p>
300      * @return  returns a <code>XSingleComponentFactory</code> for creating
301      *          the component
302      * @param   sImplName the name of the implementation for which a
303      *          service is desired
304      * @see     com.sun.star.comp.loader.JavaLoader
305      */
__getComponentFactory(String sImplName)306     public static XSingleComponentFactory __getComponentFactory(String sImplName)
307     {
308         XSingleComponentFactory xFactory = null;
309 
310         if ( sImplName.equals( _HelpSearch.class.getName() ) )
311             xFactory = Factory.createComponentFactory(_HelpSearch.class,
312                                              _HelpSearch.getServiceNames());
313 
314         return xFactory;
315     }
316 
317         /** This method is a member of the interface for initializing an object
318          * directly after its creation.
319          * @param object This array of arbitrary objects will be passed to the
320          * component after its creation.
321          * @throws Exception Every exception will not be handled, but will be
322          * passed to the caller.
323          */
initialize( Object[] object )324         public void initialize( Object[] object )
325             throws com.sun.star.uno.Exception {
326             /* The component describes what arguments it expects and in which
327              * order! At this point you can read the objects and can initialize
328              * your component using these objects.
329              */
330         }
331 }
332