source: main/trunk/greenstone2/common-src/indexers/mg/jni/MGSearchWrapperImpl.c@ 26662

Last change on this file since 26662 was 26662, checked in by davidb, 11 years ago

Support for cross-compilation added. This particular set of changes focus on flags that assist cross-compilation with JNI. Comparable set of changes to the mgpp ones. Note the additional type-casting (intptr_t)

File size: 21.3 KB
Line 
1/*
2 * MGSearchWrapperImpl.c
3 * Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20
21#include <jni.h>
22
23#ifdef __MINGW32__
24
25/* Cross compiling for Windows
26 Want the type definitions in *win32* version of jni_md.h but
27 this then leads to C-mangled style functions which we *don't*
28 want. The following achieves this */
29
30#undef JNIEXPORT
31#undef JNIIMPORT
32#undef JNICALL
33
34#define JNIEXPORT
35#define JNIIMPORT
36#define JNICALL
37#endif
38
39#include "MGWrapperImpl.h"
40#include "org_greenstone_mg_MGSearchWrapper.h"
41
42#include "backend.h"
43#include "environment.h"
44#include "text_get.h"
45#include "stemmer.h"
46
47
48#define MAX_INDEXES_CACHED 3
49
50/* copied from mgquery, needed to convert paragraph numbers to document numbers
51 for greenstone */
52#if defined(PARADOCNUM) || defined(NZDL)
53static int GetDocNumFromParaNum(query_data *qd, int paranum) {
54 int Documents = qd->td->cth.num_of_docs;
55 int *Paragraph = qd->paragraph;
56 int low = 1, high = Documents;
57 int mid = (low+high)/2;
58
59 while ((mid = (low+high)/2) >=1 && mid <= Documents)
60 {
61 if (paranum > Paragraph[mid])
62 low = mid+1;
63 else if (paranum <= Paragraph[mid-1])
64 high = mid-1;
65 else
66 return mid;
67 }
68 FatalError(1, "Bad paragraph number.\n");
69 return 0;
70}
71#endif
72
73
74/*********************************************
75 initialisation stuff
76 *********************************************/
77
78/* cached ids for java stuff */
79jfieldID FID_mg_data = NULL; /* MGWrapperData */
80jfieldID FID_query_result = NULL; /* MGQueryResult */
81jmethodID MID_addDoc = NULL; /* MGQueryResult.addDoc() */
82jmethodID MID_addTerm = NULL; /* MGQueryResult.addTerm() */
83jmethodID MID_addEquivTerm = NULL; /* MGQueryResult.addEquivTerm() */
84jmethodID MID_setTotalDocs = NULL; /* MGQueryResult.setTotalDocs() */
85jmethodID MID_clearResult = NULL; /* MGQueryResult.clear() */
86
87
88/* to access objects and methods on java side, need their field/method ids -
89 this initialises them at the start to avoid recalculating them each time they
90 are needed
91Note: the descriptors need to be exactly right, otherwise you get an error
92saying "no such field" but no reference to the fact that it has the right
93name but the wrong type.
94Note: apparently the jclass is a local ref and should only work
95in the method that created it. It seems to work ok, but I'll make it
96global cos the book said I should, and it may avoid future hassles.
97*/
98JNIEXPORT void JNICALL
99Java_org_greenstone_mg_MGSearchWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
100{
101 jclass JC_MGQueryResult;
102
103 /* a long-"J" */
104 FID_mg_data = (*j_env)->GetFieldID(j_env, j_cls, "mg_data_ptr_", "J");
105 assert(FID_mg_data != NULL);
106
107 /* an object -"L<class name>;" */
108 FID_query_result = (*j_env)->GetFieldID(j_env, j_cls, "mg_query_result_",
109 "Lorg/greenstone/mg/MGQueryResult;");
110 assert(FID_query_result != NULL);
111
112 /* the methods we want to use */
113 JC_MGQueryResult = (*j_env)->FindClass(j_env, "org/greenstone/mg/MGQueryResult");
114
115 /* addDoc(long doc, float rank) */
116 MID_addDoc = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addDoc", "(JF)V");
117 assert(MID_addDoc != NULL);
118
119 /* addTerm(String term, int stem) */
120 MID_addTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addTerm", "(Ljava/lang/String;I)V");
121 assert(MID_addTerm != NULL);
122
123 /* addEquivTerm(String term, String equivTerm, long match, long freq) */
124 MID_addEquivTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addEquivTerm", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
125 assert(MID_addEquivTerm != NULL);
126
127 /* setTotalDocs(long) */
128 MID_setTotalDocs = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "setTotalDocs", "(J)V");
129 assert(MID_setTotalDocs != NULL);
130
131 /* clear(void) */
132 MID_clearResult = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "clear", "()V");
133 assert(MID_clearResult != NULL);
134}
135
136
137/* the java side MGSearchWrapper has a pointer to a C object - MGWrapperData
138 initialise this and set the pointer
139*/
140JNIEXPORT jboolean JNICALL
141Java_org_greenstone_mg_MGSearchWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
142{
143 /* Allocate a MGWrapperData object to store query parameters */
144 MGWrapperData* data = (MGWrapperData*) malloc(sizeof(MGWrapperData));
145 assert(data != NULL);
146
147 /* Set default values - no stemming, no case-folding, boolean OR queries */
148 data->defaultStemMethod = 0;
149 data->defaultBoolCombine = 0;
150
151 /* Allocate a QueryInfo object to store more query parameters */
152 data->queryInfo = (QueryInfo*) malloc(sizeof(QueryInfo));
153 assert(data->queryInfo != NULL);
154
155 /* Set default values - 50 documents max, return term freqs, sort by rank */
156 data->queryInfo->index = NULL;
157 data->queryInfo->maxDocs = 50;
158 data->queryInfo->needTermFreqs = 1;
159
160 /* Save the object on the Java side */
161 (*j_env)->SetLongField(j_env, j_obj, FID_mg_data, (long) data);
162
163 /* Initialise MG environment variables */
164 InitEnv();
165 SetEnv("expert", "true", NULL);
166 SetEnv("mode", "docnums", NULL);
167
168 return 1; /* true - no errors */
169}
170
171
172/*******************************************
173 Index caching
174 *******************************************/
175
176query_data* cached_indexes[MAX_INDEXES_CACHED] = { NULL };
177
178
179/* Get the index data necessary to perform a query or document retrieval */
180query_data*
181loadIndexData(char* base_dir, char* index_path, char* text_path)
182{
183 char* index_path_name;
184 char* text_path_name;
185 query_data* qd;
186 int i = 0;
187
188 /* Form the path name of the desired indexes */
189 index_path_name = (char*) malloc(strlen(base_dir) + strlen(index_path) + 1);
190 assert(index_path_name != NULL);
191 strcpy(index_path_name, base_dir);
192 strcat(index_path_name, index_path);
193 printf("Index pathname: %s\n", index_path_name);
194
195 text_path_name = (char*) malloc(strlen(base_dir) + strlen(text_path) + 1);
196 assert(text_path_name != NULL);
197 strcpy(text_path_name, base_dir);
198 strcat(text_path_name, text_path);
199 printf("Text pathname: %s\n", text_path_name);
200
201 /* Search through the cached indexes for the desired one */
202 while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
203 printf("(Cached) Pathname: %s\n", cached_indexes[i]->pathname);
204 printf("(Cached) Textpathname: %s\n", cached_indexes[i]->textpathname);
205
206 /* Check if the index has already been loaded */
207 if ((strcmp(index_path_name, cached_indexes[i]->pathname) == 0) &&
208 (strcmp(text_path_name, cached_indexes[i]->textpathname) == 0)) {
209 /* Index has already been loaded and cached, so return it */
210 printf("Found index!\n");
211 free(index_path_name);
212 free(text_path_name);
213 return cached_indexes[i];
214 }
215
216 i++;
217 }
218
219 /* Text strings no longer needed */
220 free(index_path_name);
221 free(text_path_name);
222
223 /* The index is not cached, so load it now */
224 qd = InitQuerySystem(base_dir, index_path, text_path, NULL);
225 if (!qd) {
226 printf("Error: Could not InitQuerySystem()...\n");
227 return NULL;
228 }
229
230 /* The index loaded OK, so cache it */
231 /* This could be a little more sophisticated, eg. replace least frequently used index */
232 if (i >= MAX_INDEXES_CACHED)
233 i = MAX_INDEXES_CACHED - 1;
234
235 /* Free the index being replaced */
236 if (cached_indexes[i] != NULL)
237 FinishQuerySystem(cached_indexes[i]);
238
239 /* Cache the loaded index, and return it */
240 cached_indexes[i] = qd;
241 return cached_indexes[i];
242}
243
244
245/* Clean up by unloading all cached indexes */
246JNIEXPORT jboolean JNICALL
247Java_org_greenstone_mg_MGSearchWrapper_unloadIndexData(JNIEnv* j_env, jobject j_obj)
248{
249 /* Free all the loaded indexes */
250 int i = 0;
251 while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
252 FinishQuerySystem(cached_indexes[i]);
253 cached_indexes[i] = NULL;
254 i++;
255 }
256
257 return 1; /* true - no errors */
258}
259
260
261/*******************************************
262 do a query
263 *******************************************/
264
265/* do the actual query - the results are written to query_result held on the Java side */
266JNIEXPORT void JNICALL
267Java_org_greenstone_mg_MGSearchWrapper_runQuery(JNIEnv *j_env, jobject j_obj,
268 jstring j_base_dir, jstring j_text_path,
269 jstring j_query)
270{
271 MGWrapperData* data = (MGWrapperData*) (intptr_t)(*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
272
273 char* index_path;
274 const char* base_dir;
275 const char* text_path;
276 query_data* qd;
277
278 jobject result_ptr;
279 char* query;
280 int i, j;
281
282 jthrowable exc;
283 /* First of all, clear the previous result */
284 /* The result to write to */
285 result_ptr = (*j_env)->GetObjectField(j_env, j_obj, FID_query_result);
286 assert(result_ptr != NULL);
287
288 /* Clear any previous query results */
289 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_clearResult);
290 exc = (*j_env)->ExceptionOccurred(j_env);
291 if (exc) {
292 (*j_env)->ExceptionDescribe(j_env);
293 return;
294 }
295
296 /* Make sure an index has been specified */
297 index_path = data->queryInfo->index;
298 if (index_path == NULL) {
299 return;
300 }
301
302 /* Obtain C versions of the two string parameters */
303 base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
304 if (base_dir == NULL) {
305 return;
306 }
307 text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
308 if (text_path == NULL) {
309 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
310 return;
311 }
312
313 /* Load the appropriate index for satisfying this request */
314 qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
315
316 /* The C text strings are no longer needed */
317 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
318 (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
319
320 /* Check that the index was loaded successfully */
321 if (qd == NULL) {
322 return;
323 }
324
325 /* Remove anything hanging around from last time */
326 FreeQueryDocs(qd);
327
328 /* Obtain a C version of the query string */
329 query = (char*) (*j_env)->GetStringUTFChars(j_env, j_query, NULL);
330 if (query == NULL) {
331 return;
332 }
333 printf("Searching for query \"%s\"...\n", query);
334
335 /* Make sure the query isn't empty */
336 if (strlen(query) == 0) {
337 printf("Warning: Empty query.\n");
338 return;
339 }
340
341 /* "Some" queries are done as ranked queries */
342 if (data->defaultBoolCombine == 0) {
343 RankedQueryInfo rqi;
344 rqi.QueryFreqs = 1; /* Use the frequency of each query term in the query - OK? */
345 rqi.Exact = 1; /* Perform exact ranking */
346 rqi.MaxDocsToRetrieve = data->queryInfo->maxDocs; /* Get only the desired number */
347 rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve; /* OK? */
348 /* we may need to get more paragraphs to get enough documents. I copied the following from mgquery. it seems to work, not sure why - kjdon */
349 if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas")) {
350 rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas"));
351 }
352
353 rqi.Sort = 1; /* Sort the query terms by frequency before ranking */
354 rqi.AccumMethod = 'L'; /* Use a list when accumulating (has bugs though...) */
355 /* rqi.MaxAccums = -1; */ /* Use as many accumulators as necessary - CRASHES with list */
356 rqi.MaxAccums = 100000;
357 rqi.MaxTerms = -1; /* Use all the query terms */
358 /* rqi.StopAtMaxAccum = 0;*/ /* Don't care (using as many accumulators as necessary) */
359 rqi.StopAtMaxAccum = 1;
360 rqi.HashTblSize = 1000; /* Don't care (not using a hash table) */
361 rqi.skip_dump = NULL; /* Don't dump skip information */
362
363 /* RankedQuery() reads 'casefold' and 'stem' parameters from the environment */
364 SetEnv("casefold", ((data->defaultStemMethod & 1) ? "on" : "off"), NULL);
365 SetEnv("stem", ((data->defaultStemMethod & 2) ? "on" : "off"), NULL);
366
367 RankedQuery(qd, query, &rqi);
368 }
369 /* "All" queries are done as boolean queries */
370 else {
371 BooleanQueryInfo bqi;
372 bqi.MaxDocsToRetrieve = data->queryInfo->maxDocs;
373
374 /* Had to add "words$o" to LIB_OBJS in mg/src/text/Makefile and recompile mg for this */
375 BooleanQuery(qd, query, &bqi, data->defaultStemMethod);
376 }
377
378 /* Finished with the C query string */
379 (*j_env)->ReleaseStringUTFChars(j_env, j_query, query);
380
381 /* Check the query was processed successfully */
382 if (qd->DL == NULL || qd->QTL == NULL || qd->TL == NULL) {
383 return;
384 }
385
386 /* Record the total number of matching documents */
387 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_setTotalDocs, (jlong) qd->DL->num);
388 exc = (*j_env)->ExceptionOccurred(j_env);
389 if (exc) {
390 (*j_env)->ExceptionDescribe(j_env);
391 return;
392 }
393
394 /* Record the matching documents, but only the number requested */
395 printf("Number of matching documents: %d\n", qd->DL->num);
396
397 for (i = 0; (i < qd->DL->num && i < data->queryInfo->maxDocs); i++) {
398 int doc_num = qd->DL->DE[i].DocNum;
399 float doc_weight = qd->DL->DE[i].Weight;
400
401#if defined(PARADOCNUM) || defined(NZDL)
402 if (qd->id->ifh.InvfLevel == 3) {
403 /* pararaph level, need to convert to doc level*/
404 doc_num = GetDocNumFromParaNum(qd, doc_num);
405 }
406#endif
407
408
409 /* Call the addDoc function (Java side) to record a matching document */
410 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addDoc,
411 (jlong) doc_num, (jfloat) doc_weight);
412 exc = (*j_env)->ExceptionOccurred(j_env);
413 if (exc) {
414 (*j_env)->ExceptionDescribe(j_env);
415 return;
416 }
417 }
418
419 /* Record the term information, if desired */
420 if (data->queryInfo->needTermFreqs) {
421 /* The following code is a lot more complicated than it could be, but it is necessary
422 to compensate for an oddity in MG. */
423 unsigned char** stemmed_terms = malloc(sizeof(unsigned char*) * qd->TL->num);
424
425 printf("Number of terms: %d\n", qd->TL->num);
426 printf("Number of query terms: %d\n", qd->QTL->num);
427
428 /* Generate the stemmed form of each of the relevant terms */
429 for (i = 0; i < qd->TL->num; i++) {
430 u_char* raw_term = qd->TL->TE[i].Word;
431 unsigned int term_length = raw_term[0];
432
433 u_char* raw_stemmed_term = malloc(term_length + 1);
434 unsigned int stemmed_term_length;
435
436 /* Copy the term, and stem it */
437 for (j = 0; j <= term_length; j++)
438 raw_stemmed_term[j] = raw_term[j];
439 stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_term);
440
441 /* Allocate memory to store the stemmed term, and fill it */
442 stemmed_term_length = raw_stemmed_term[0];
443 stemmed_terms[i] = malloc(stemmed_term_length + 1);
444 assert(stemmed_terms[i] != NULL);
445 strncpy(stemmed_terms[i], &(raw_stemmed_term[1]), stemmed_term_length);
446 stemmed_terms[i][stemmed_term_length] = '\0';
447 }
448
449 /* Record every query term, along with their equivalent terms */
450 for (i = 0; i < qd->QTL->num; i++) {
451 u_char* raw_query_term = qd->QTL->QTE[i].Term;
452 unsigned int query_term_length = raw_query_term[0];
453 unsigned char* query_term;
454 jstring j_query_term;
455
456 u_char* raw_stemmed_query_term = malloc(query_term_length + 1);
457 unsigned int stemmed_query_term_length;
458 unsigned char* stemmed_query_term;
459
460 /* Allocate memory to store the query term, and fill it */
461 query_term = malloc(query_term_length + 1);
462 assert(query_term != NULL);
463 strncpy(query_term, &(raw_query_term[1]), query_term_length);
464 query_term[query_term_length] = '\0';
465
466 /* Allocate a new jstring for the query term */
467 j_query_term = (*j_env)->NewStringUTF(j_env, query_term);
468 assert(j_query_term != NULL);
469
470 /* Call the addTerm function (Java side) to record the query term */
471 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addTerm,
472 j_query_term, (jint) data->defaultStemMethod);
473 exc = (*j_env)->ExceptionOccurred(j_env);
474 if (exc) {
475 (*j_env)->ExceptionDescribe(j_env);
476 return;
477 }
478
479 /* Copy the query term, and stem it */
480 for (j = 0; j <= query_term_length; j++)
481 raw_stemmed_query_term[j] = raw_query_term[j];
482 stemmer(data->defaultStemMethod, qd->sd->sdh.stemmer_num, raw_stemmed_query_term);
483
484 /* Allocate memory to store the stemmed query term, and fill it */
485 stemmed_query_term_length = raw_stemmed_query_term[0];
486 stemmed_query_term = malloc(stemmed_query_term_length + 1);
487 assert(stemmed_query_term != NULL);
488 strncpy(stemmed_query_term, &(raw_stemmed_query_term[1]), stemmed_query_term_length);
489 stemmed_query_term[stemmed_query_term_length] = '\0';
490
491 /* Find all the terms equivalent to the query term */
492 for (j = 0; j < qd->TL->num; j++) {
493 /* Check if the stemmed query term matches the stemmed term */
494 if (strcmp(stemmed_query_term, stemmed_terms[j]) == 0) {
495 u_char* raw_term = qd->TL->TE[j].Word;
496 unsigned int term_length = raw_term[0];
497 unsigned char* term;
498 jstring j_term;
499
500 /* Allocate memory to store the query term, and fill it */
501 term = malloc(term_length + 1);
502 assert(term != NULL);
503 strncpy(term, &(raw_term[1]), term_length);
504 term[term_length] = '\0';
505
506 /* Allocate a new jstring for the query term */
507 j_term = (*j_env)->NewStringUTF(j_env, term);
508 assert(j_term != NULL);
509
510 /* Call the addEquivTerm function (Java side) to record the equivalent term */
511 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addEquivTerm,
512 j_query_term, j_term,
513 (jlong) qd->TL->TE[j].WE.doc_count,
514 (jlong) qd->TL->TE[j].WE.count);
515 exc = (*j_env)->ExceptionOccurred(j_env);
516 if (exc) {
517 (*j_env)->ExceptionDescribe(j_env);
518 return;
519 }
520 }
521 }
522 }
523 }
524}
525
526
527/*******************************************
528 set query options
529 *******************************************/
530
531/* Turn casefolding on or off */
532JNIEXPORT void JNICALL
533Java_org_greenstone_mg_MGSearchWrapper_setCase(JNIEnv *j_env, jobject j_obj,
534 jboolean j_on)
535{
536 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
537
538 if (j_on) {
539 data->defaultStemMethod |= 1;
540 } else {
541 data->defaultStemMethod &= 0xe;
542 }
543}
544
545
546/* Turn stemming on or off */
547JNIEXPORT void JNICALL
548Java_org_greenstone_mg_MGSearchWrapper_setStem(JNIEnv *j_env, jobject j_obj,
549 jboolean j_on)
550{
551 MGWrapperData* data = (MGWrapperData*) (intptr_t)(*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
552
553 if (j_on) {
554 data->defaultStemMethod |= 2;
555 } else {
556 data->defaultStemMethod &= 0xd;
557 }
558}
559
560
561/* Set the maximum number of documents to return from a query */
562JNIEXPORT void JNICALL
563Java_org_greenstone_mg_MGSearchWrapper_setMaxDocs(JNIEnv *j_env, jobject j_obj,
564 jint j_max)
565{
566 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
567 data->queryInfo->maxDocs = j_max;
568}
569
570/* set the maximum number of numeric to split*/
571JNIEXPORT void JNICALL
572Java_org_greenstone_mg_MGSearchWrapper_setMaxNumeric (JNIEnv *j_env,
573 jobject j_obj,
574 jint j_max) {
575
576 char text[20];
577 char* maxnumeric;
578 sprintf(text,"%d",j_max);
579 maxnumeric = text;
580 SetEnv("maxnumeric",maxnumeric, NULL);
581}
582
583
584/* Turn term frequency recording on or off */
585JNIEXPORT void JNICALL
586Java_org_greenstone_mg_MGSearchWrapper_setReturnTerms(JNIEnv *j_env, jobject j_obj,
587 jboolean j_on)
588{
589 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
590 data->queryInfo->needTermFreqs = j_on;
591}
592
593
594/* Choose MG index to search */
595JNIEXPORT void JNICALL
596Java_org_greenstone_mg_MGSearchWrapper_setIndex(JNIEnv *j_env, jobject j_obj,
597 jstring j_index)
598{
599 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
600
601 /* Get the index name as a C string */
602 const char* index = (*j_env)->GetStringUTFChars(j_env, j_index, NULL);
603 assert(index != NULL);
604 printf("Choosing index %s...\n", index);
605
606 /* Free the previous index name */
607 if (data->queryInfo->index)
608 free(data->queryInfo->index);
609
610 /* Allocate memory for the index name, and fill it */
611 data->queryInfo->index = (char*) malloc(strlen(index) + 1);
612 assert(data->queryInfo->index != NULL);
613 strcpy(data->queryInfo->index, index);
614
615 /* Release the index string */
616 (*j_env)->ReleaseStringUTFChars(j_env, j_index, index);
617}
618
619
620/* Choose boolean AND or boolean OR queries */
621JNIEXPORT void JNICALL
622Java_org_greenstone_mg_MGSearchWrapper_setMatchMode(JNIEnv *j_env, jobject j_obj,
623 jint j_mode)
624{
625 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
626 data->defaultBoolCombine = j_mode;
627}
628
629
630/* Get a text representation of the current parameter values */
631JNIEXPORT jstring JNICALL
632Java_org_greenstone_mg_MGSearchWrapper_getQueryParams(JNIEnv *j_env, jobject j_obj)
633{
634 MGWrapperData* data = (MGWrapperData*)(intptr_t) (*j_env)->GetLongField(j_env, j_obj, FID_mg_data);
635 char result[512]; /* Assume this is big enough */
636
637 /* Print the data to a character array */
638 sprintf(result, "Query params:\nindex\t\t%s\ncasefold\t%d\nstem\t\t%d\nquery type\t%s\nmax docs\t%d\n",
639 (data->queryInfo->index == NULL ? "<none loaded>" : data->queryInfo->index),
640 (data->defaultStemMethod & 1),
641 (data->defaultStemMethod & 2),
642 (data->defaultBoolCombine == 1 ? "all" : "some"),
643 (data->queryInfo->maxDocs));
644
645 /* Convert to a jstring, and return */
646 return (*j_env)->NewStringUTF(j_env, result);
647}
648
Note: See TracBrowser for help on using the repository browser.