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

Last change on this file since 37383 was 37383, checked in by davidb, 14 months ago

Mac compiler is stricter about about function externs

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