source: trunk/gsdl3/src/packages/mg/jni/MGWrapperImpl.c@ 3743

Last change on this file since 3743 was 3743, checked in by mdewsnip, 21 years ago

Initial implementation of MG JNI wrapper (C side).

  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/*
2 * MGWrapperImpl.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 "MGWrapperImpl.h"
22#include <jni.h>
23#include "org_greenstone_mg_MGWrapper.h"
24
25#include "backend.h"
26#include "environment.h"
27
28
29/*************************************************************************
30 NOTES
31
32 - Features supported by MGPP but not by MG (AFAIK)
33
34 - Sorting results by rank.
35 Done here as a post-processing operation. Could be more efficient in
36 some cases: the current solution is not very good when the number of
37 matching documents is large and the number of desired matches is
38 small. In this case it would be better to iterate through the array
39 picking out the best documents rather than sorting them all.
40
41 - Asking for query term frequencies to be returned.
42 This cannot be turned off in MG. If the term frequencies are not
43 required, they are simply not passed bassed to the Java side.
44
45 - Choosing the index for queries.
46 It is possible for MG to build Section and Document indexes (for
47 example), but these are two separate indexes, and must be loaded
48 separately. This module can load more than one index at a time, thus
49 processing queries to different indexes more quickly.
50 NOTE: This replaces TWO options in the MGPP version: returnLevel and
51 queryLevel.
52
53 - "Some" (boolean OR) queries.
54 In boolean querying mode, MG assumes query terms are joined by ANDs.
55 There is no way to tell MG to treat the query terms as if they were
56 joined by ORs. Here, "some" queries are handled by explicitly
57 inserting OR ("|") characters between the query terms.
58
59 *************************************************************************
60 TO DO
61
62 - Find out about necessity of other query term information
63 (eg. equivalent terms).
64
65 *************************************************************************/
66
67
68#define MAX_INDEXES_CACHED 2
69
70
71/*********************************************
72 initialisation stuff
73 *********************************************/
74
75/* cached ids for java stuff */
76jfieldID FID_mg_data = NULL; /* MGWrapperData */
77jfieldID FID_query_result = NULL; /* MGQueryResult */
78jmethodID MID_addDoc = NULL; /* MGQueryResult.addDoc() */
79jmethodID MID_addTerm = NULL; /* MGQueryResult.addTerm() */
80jmethodID MID_setTotalDocs = NULL; /* MGQueryResult.setTotalDocs() */
81jmethodID MID_clearResult = NULL; /* MGQueryResult.clear() */
82
83
84/* to access objects and methods on java side, need their field/method ids -
85 this initialises them at the start to avoid recalculating them each time they
86 are needed
87Note: the descriptors need to be exactly right, otherwise you get an error
88saying "no such field" but no reference to the fact that it has the right
89name but the wrong type.
90Note: apparently the jclass is a local ref and should only work
91in the method that created it. It seems to work ok, but I'll make it
92global cos the book said I should, and it may avoid future hassles.
93*/
94JNIEXPORT void JNICALL
95Java_org_greenstone_mg_MGWrapper_initIDs(JNIEnv *j_env, jclass j_cls)
96{
97 jclass JC_MGQueryResult;
98
99 /* a long-"J" */
100 FID_mg_data = (*j_env)->GetFieldID(j_env, j_cls, "mg_data_ptr_", "J");
101 assert(FID_mg_data != NULL);
102
103 /* an object -"L<class name>;" */
104 FID_query_result = (*j_env)->GetFieldID(j_env, j_cls, "mg_query_result_",
105 "Lorg/greenstone/mg/MGQueryResult;");
106 assert(FID_query_result != NULL);
107
108 /* the methods we want to use */
109 JC_MGQueryResult = (*j_env)->FindClass(j_env, "org/greenstone/mg/MGQueryResult");
110
111 /* addDoc(long doc, float rank) */
112 MID_addDoc = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addDoc", "(JF)V");
113 assert(MID_addDoc != NULL);
114
115 /* addTerm(String term, String tag, int stem, long match, long freq, String[] equivs) */
116 MID_addTerm = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "addTerm", "(Ljava/lang/String;Ljava/lang/String;IJJ[Ljava/lang/String;)V");
117 assert(MID_addTerm != NULL);
118
119 /* setTotalDocs(long) */
120 MID_setTotalDocs = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "setTotalDocs", "(J)V");
121 assert(MID_setTotalDocs != NULL);
122
123 /* clear(void) */
124 MID_clearResult = (*j_env)->GetMethodID(j_env, JC_MGQueryResult, "clear", "()V");
125 assert(MID_clearResult != NULL);
126}
127
128
129/* the java side MGWrapper has a pointer to a C object - MGWrapperData
130 initialise this and set the pointer
131*/
132JNIEXPORT jboolean JNICALL
133Java_org_greenstone_mg_MGWrapper_initCSide(JNIEnv *j_env, jobject j_obj)
134{
135 /* Allocate a MGWrapperData object to store query parameters */
136 MGWrapperData* data = (MGWrapperData*) malloc(sizeof(MGWrapperData));
137 assert(data != NULL);
138
139 /* Set default values - no stemming, no case-folding, boolean OR queries */
140 data->defaultStemMethod = 0;
141 data->defaultBoolCombine = 0;
142
143 /* Allocate a QueryInfo object to store more query parameters */
144 data->queryInfo = (QueryInfo*) malloc(sizeof(QueryInfo));
145 assert(data->queryInfo != NULL);
146
147 /* Set default values - 50 documents max, return term freqs, sort by rank */
148 data->queryInfo->index = NULL;
149 data->queryInfo->maxDocs = 50;
150 data->queryInfo->needTermFreqs = 1;
151 data->queryInfo->sortByRank = 1;
152
153 /* Save the object on the Java side */
154 (*j_env)->SetIntField(j_env, j_obj, FID_mg_data, (long) data);
155
156 /* Initialise MG environment variables */
157 InitEnv();
158 SetEnv("expert", "true", NULL);
159 SetEnv("mode", "docnums", NULL);
160 return 1; /* true - no errors */
161}
162
163
164/*******************************************
165 Index caching
166 *******************************************/
167
168query_data* cached_indexes[MAX_INDEXES_CACHED] = { NULL };
169
170
171/* Get the index data necessary to perform a query or document retrieval */
172query_data*
173loadIndexData(char* base_dir, char* index_path, char* text_path)
174{
175 char* index_path_name;
176 char* text_path_name;
177 query_data* qd;
178 int i = 0;
179
180 /* Form the path name of the desired indexes */
181 index_path_name = (char*) malloc(strlen(base_dir) + strlen(index_path) + 1);
182 assert(index_path_name != NULL);
183 strcpy(index_path_name, base_dir);
184 strcat(index_path_name, index_path);
185 printf("Index pathname: %s\n", index_path_name);
186
187 text_path_name = (char*) malloc(strlen(base_dir) + strlen(text_path) + 1);
188 assert(text_path_name != NULL);
189 strcpy(text_path_name, base_dir);
190 strcat(text_path_name, text_path);
191 printf("Text pathname: %s\n", text_path_name);
192
193 /* Search through the cached indexes for the desired one */
194 while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
195 printf("(Cached) Pathname: %s\n", cached_indexes[i]->pathname);
196 printf("(Cached) Textpathname: %s\n", cached_indexes[i]->textpathname);
197
198 /* Check if the index has already been loaded */
199 if ((strcmp(index_path_name, cached_indexes[i]->pathname) == 0) &&
200 (strcmp(text_path_name, cached_indexes[i]->textpathname) == 0)) {
201 /* Index has already been loaded and cached, so return it */
202 printf("Found index!\n");
203 free(index_path_name);
204 free(text_path_name);
205 return cached_indexes[i];
206 }
207
208 i++;
209 }
210
211 /* Text strings no longer needed */
212 free(index_path_name);
213 free(text_path_name);
214
215 /* The index is not cached, so load it now */
216 qd = InitQuerySystem(base_dir, index_path, text_path, NULL);
217 if (!qd) {
218 printf("Error: Could not InitQuerySystem()...\n");
219 return NULL;
220 }
221
222 /* The index loaded OK, so cache it */
223 /* This could be a little more sophisticated, eg. replace least frequently used index */
224 if (i >= MAX_INDEXES_CACHED)
225 i = MAX_INDEXES_CACHED - 1;
226
227 /* Free the index being replaced */
228 if (cached_indexes[i] != NULL)
229 FinishQuerySystem(cached_indexes[i]);
230
231 /* Cache the loaded index, and return it */
232 cached_indexes[i] = qd;
233 return cached_indexes[i];
234}
235
236
237/* Clean up by unloading all cached indexes */
238JNIEXPORT jboolean JNICALL
239Java_org_greenstone_mg_MGWrapper_unloadIndexData(JNIEnv* j_env, jobject j_obj)
240{
241 /* Free all the loaded indexes */
242 int i = 0;
243 while (i < MAX_INDEXES_CACHED && cached_indexes[i] != NULL) {
244 FinishQuerySystem(cached_indexes[i]);
245 cached_indexes[i] = NULL;
246 i++;
247 }
248
249 return 1; /* true - no errors */
250}
251
252
253/****************************************************
254 retrieve a document
255 ****************************************************/
256
257/* Returns a document from mg as a string */
258JNIEXPORT jstring JNICALL
259Java_org_greenstone_mg_MGWrapper_getDocument(JNIEnv *j_env, jobject j_obj,
260 jstring j_base_dir, jstring j_text_path,
261 jlong j_docnum)
262{
263 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
264
265 char* index_path;
266 const char* base_dir;
267 const char* text_path;
268 query_data* qd;
269
270 u_long pos, len;
271 u_char* c_buffer = NULL;
272 u_char* uc_buffer = NULL;
273 int ULen;
274
275 jstring result;
276
277 /* Make sure an index has been specified */
278 index_path = data->queryInfo->index;
279 assert(index_path != NULL);
280
281 /* Obtain C versions of the two string parameters */
282 base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
283 if (base_dir == NULL) {
284 return NULL;
285 }
286 text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
287 if (text_path == NULL) {
288 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
289 return NULL;
290 }
291
292 /* Load the appropriate index for satisfying this request */
293 qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
294
295 /* The C text strings are no longer needed */
296 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
297 (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
298
299 /* Check that the index was loaded successfully */
300 assert(qd != NULL);
301
302 /* Get the document position and length in the text file */
303 printf("Fetching document number %ld...\n", (unsigned long) j_docnum);
304 FetchDocStart(qd, (unsigned long) j_docnum, &pos, &len);
305 printf("Fetched document start. Pos: %ld, Len: %ld\n", pos, len);
306
307 /* Allocate memory for the document text (from mg/src/text/mgquery.c:RawDocOutput()) */
308 c_buffer = (u_char*) malloc(len);
309 assert(c_buffer != NULL);
310 uc_buffer = (u_char*) malloc((int) (qd->td->cth.ratio * 1.01 * len) + 100);
311 assert(uc_buffer != NULL);
312
313 /* Seek to the correct position in the file and read the document text */
314 Fseek (qd->td->TextFile, pos, 0);
315 Fread (c_buffer, 1, len, qd->td->TextFile);
316
317 /* Decode (?) the document text into another buffer, and terminate it */
318 DecodeText (qd->cd, c_buffer, len, uc_buffer, &ULen);
319 uc_buffer[ULen] = '\0';
320
321 /* Load the document text into a Java string */
322 result = (*j_env)->NewStringUTF(j_env, uc_buffer);
323 assert(result != NULL);
324
325 /* Free C buffers */
326 free(c_buffer);
327 free(uc_buffer);
328
329 /* Return the document text */
330 return result;
331}
332
333
334/*******************************************
335 do a query
336 *******************************************/
337
338/* Comparison function for sorting documents by their weight (decreasing order) */
339int
340document_weight_comp(const void *A, const void *B)
341{
342 const DocEntry *a = A;
343 const DocEntry *b = B;
344
345 /* Compare on weight, highest wins */
346 if (a->Weight < b->Weight)
347 return 1;
348 if (a->Weight > b->Weight)
349 return -1;
350 return 0;
351}
352
353
354/* do the actual query - the results are written to query_result held on the Java side */
355JNIEXPORT void JNICALL
356Java_org_greenstone_mg_MGWrapper_runQuery(JNIEnv *j_env, jobject j_obj,
357 jstring j_base_dir, jstring j_text_path,
358 jstring j_query)
359{
360 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
361
362 char* index_path;
363 const char* base_dir;
364 const char* text_path;
365 query_data* qd;
366
367 jobject result_ptr;
368 char* query;
369 BooleanQueryInfo bqi;
370 int i, j;
371
372 jthrowable exc;
373
374 /* Make sure an index has been specified */
375 index_path = data->queryInfo->index;
376 assert(index_path != NULL);
377
378 /* Obtain C versions of the two string parameters */
379 base_dir = (*j_env)->GetStringUTFChars(j_env, j_base_dir, NULL);
380 if (base_dir == NULL) {
381 return;
382 }
383 text_path = (*j_env)->GetStringUTFChars(j_env, j_text_path, NULL);
384 if (text_path == NULL) {
385 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
386 return;
387 }
388
389 /* Load the appropriate index for satisfying this request */
390 qd = loadIndexData((char*) base_dir, (char*) index_path, (char*) text_path);
391
392 /* The C text strings are no longer needed */
393 (*j_env)->ReleaseStringUTFChars(j_env, j_base_dir, base_dir);
394 (*j_env)->ReleaseStringUTFChars(j_env, j_text_path, text_path);
395
396 /* Check that the index was loaded successfully */
397 assert(qd != NULL);
398
399 /* Remove anything hanging around from last time */
400 FreeQueryDocs(qd);
401
402 /* The result to write to */
403 result_ptr = (*j_env)->GetObjectField(j_env, j_obj, FID_query_result);
404 assert(result_ptr != NULL);
405
406 /* Clear any previous query results */
407 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_clearResult);
408 exc = (*j_env)->ExceptionOccurred(j_env);
409 if (exc) {
410 (*j_env)->ExceptionDescribe(j_env);
411 return;
412 }
413
414 /* Obtain a C version of the query string */
415 query = (char*) (*j_env)->GetStringUTFChars(j_env, j_query, NULL);
416 assert(query != NULL);
417 printf("Searching for query \"%s\"...\n", query);
418
419 /* Make sure the query isn't empty */
420 if (strlen(query) == 0) {
421 printf("Warning: Empty query.\n");
422 return;
423 }
424
425 /* Boolean OR ("some") queries: must manually insert OR ("|") tokens */
426 if (data->defaultBoolCombine == 0) {
427 int in_space = 0;
428 for (i = 0; i < strlen(query); i++) {
429 if (in_space) {
430 if (query[i] == '|') /* OR character already inserted, so remove others */
431 query[i] = ' ';
432 else if (!isspace(query[i])) /* moving out of a space region */
433 in_space = 0;
434 }
435 else if (!in_space && isspace(query[i])) { /* moving into a space region */
436 in_space = 1;
437 query[i] = '|'; /* insert an OR character */
438 }
439 }
440 printf("Boolean OR query string: %s\n", query);
441 }
442
443 /* If the documents need to be sorted by rank, all of them must be retrieved */
444 bqi.MaxDocsToRetrieve = ((data->queryInfo->sortByRank) ? -1 : data->queryInfo->maxDocs);
445
446 /* Perform query */
447 /* Had to add "words$o" to LIB_OBJS in mg/src/text/Makefile and recompile mg for this */
448 BooleanQuery(qd, (char*) query, &bqi, data->defaultStemMethod);
449
450 /* Finished with the C query string */
451 (*j_env)->ReleaseStringUTFChars(j_env, j_query, query);
452
453 /* Check the query was processed successfully */
454 assert(qd->DL != NULL);
455 assert(qd->QTL != NULL);
456 assert(qd->TL != NULL);
457
458 /* Record the total number of matching documents */
459 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_setTotalDocs, (jlong) qd->DL->num);
460 exc = (*j_env)->ExceptionOccurred(j_env);
461 if (exc) {
462 (*j_env)->ExceptionDescribe(j_env);
463 return;
464 }
465
466 /* Sort the documents by rank, if desired */
467 if (data->queryInfo->sortByRank) {
468 qsort(qd->DL->DE, qd->DL->num, sizeof(DocEntry), document_weight_comp);
469 }
470
471 /* Record the matching documents, but only the number requested */
472 printf("Number of matching documents: %d\n", qd->DL->num);
473 for (i = 0; (i < qd->DL->num && i < data->queryInfo->maxDocs); i++) {
474 int doc_num = qd->DL->DE[i].DocNum;
475 float doc_weight = qd->DL->DE[i].Weight;
476
477 /* Call the addDoc function (Java side) to record a matching document */
478 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addDoc,
479 (jlong) doc_num, (jfloat) doc_weight);
480 exc = (*j_env)->ExceptionOccurred(j_env);
481 if (exc) {
482 (*j_env)->ExceptionDescribe(j_env);
483 return;
484 }
485 }
486
487 /* Record the term information, if desired */
488 if (data->queryInfo->needTermFreqs) {
489 printf("Number of terms: %d\n", qd->TL->num);
490 printf("Number of query terms: %d\n", qd->QTL->num);
491
492 /* Find each query term in the term list, and grab its frequency */
493 for (i = 0; i < qd->QTL->num; i++) {
494 unsigned int query_term_length = (unsigned int) qd->QTL->QTE[i].Term[0];
495 unsigned char* query_term;
496 jstring j_query_term;
497 jint stem = qd->QTL->QTE[i].stem_method;
498 jlong match;
499 jlong freq;
500
501 /* Allocate memory to store this query term, and fill it */
502 query_term = (unsigned char*) malloc(query_term_length + 1);
503 assert(query_term != NULL);
504 strncpy(query_term, &(qd->QTL->QTE[i].Term[1]), query_term_length);
505 query_term[query_term_length] = '\0';
506 printf("Query term: %s\n", query_term);
507
508 /* Allocate a new jstring for the query term */
509 j_query_term = (*j_env)->NewStringUTF(j_env, query_term);
510 assert(j_query_term != NULL);
511
512 /* Find the matching term in the term list */
513 for (j = 0; j < qd->TL->num; j++) {
514 unsigned int term_length = (unsigned int) qd->TL->TE[j].Word[0];
515
516 /* Stemming and case-folding mean both comparisons are necessary */
517 if ((strncmp(query_term, &(qd->TL->TE[j].Word[1]), term_length) == 0) &&
518 (strncmp(query_term, &(qd->TL->TE[j].Word[1]), query_term_length) == 0)) {
519 /* Get the document count and total frequency of the term */
520 match = qd->TL->TE[j].WE.doc_count;
521 freq = qd->TL->TE[j].WE.count;
522
523 /* Call the addTerm function (Java side) to record term information */
524 (*j_env)->CallVoidMethod(j_env, result_ptr, MID_addTerm,
525 j_query_term, NULL, stem, match, freq, NULL);
526 exc = (*j_env)->ExceptionOccurred(j_env);
527 if (exc) {
528 (*j_env)->ExceptionDescribe(j_env);
529 return;
530 }
531
532 /* There can only be one match */
533 break;
534 }
535 }
536
537 /* Finished with this query term */
538 free(query_term);
539 }
540 }
541}
542
543
544/*******************************************
545 set query options
546 *******************************************/
547
548/* Turn casefolding on or off */
549JNIEXPORT void JNICALL
550Java_org_greenstone_mg_MGWrapper_setCase(JNIEnv *j_env, jobject j_obj,
551 jboolean j_on)
552{
553 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
554
555 if (j_on) {
556 data->defaultStemMethod |= 1;
557 } else {
558 data->defaultStemMethod &= 0xe;
559 }
560}
561
562
563/* Turn stemming on or off */
564JNIEXPORT void JNICALL
565Java_org_greenstone_mg_MGWrapper_setStem(JNIEnv *j_env, jobject j_obj,
566 jboolean j_on)
567{
568 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
569
570 if (j_on) {
571 data->defaultStemMethod |= 2;
572 } else {
573 data->defaultStemMethod &= 0xd;
574 }
575}
576
577
578/* Set the maximum number of documents to return from a query */
579JNIEXPORT void JNICALL
580Java_org_greenstone_mg_MGWrapper_setMaxDocs(JNIEnv *j_env, jobject j_obj,
581 jint j_max)
582{
583 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
584 data->queryInfo->maxDocs = j_max;
585}
586
587
588/* Turn sorting by rank on or off */
589JNIEXPORT void JNICALL
590Java_org_greenstone_mg_MGWrapper_setSortByRank(JNIEnv *j_env, jobject j_obj,
591 jboolean j_on)
592{
593 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
594 data->queryInfo->sortByRank = j_on;
595}
596
597
598/* Turn term frequency recording on or off */
599JNIEXPORT void JNICALL
600Java_org_greenstone_mg_MGWrapper_setReturnTerms(JNIEnv *j_env, jobject j_obj,
601 jboolean j_on)
602{
603 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
604 data->queryInfo->needTermFreqs = j_on;
605}
606
607
608/* Choose MG index to search */
609JNIEXPORT void JNICALL
610Java_org_greenstone_mg_MGWrapper_setIndex(JNIEnv *j_env, jobject j_obj,
611 jstring j_index)
612{
613 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
614
615 /* Get the index name as a C string */
616 const char* index = (*j_env)->GetStringUTFChars(j_env, j_index, NULL);
617 assert(index != NULL);
618 printf("Choosing index %s...\n", index);
619
620 /* Free the previous index name */
621 if (data->queryInfo->index)
622 free(data->queryInfo->index);
623
624 /* Allocate memory for the index name, and fill it */
625 data->queryInfo->index = (char*) malloc(strlen(index) + 1);
626 assert(data->queryInfo->index != NULL);
627 strcpy(data->queryInfo->index, index);
628
629 /* Release the index string */
630 (*j_env)->ReleaseStringUTFChars(j_env, j_index, index);
631}
632
633
634/* Choose boolean AND or boolean OR queries */
635JNIEXPORT void JNICALL
636Java_org_greenstone_mg_MGWrapper_setMatchMode(JNIEnv *j_env, jobject j_obj,
637 jint j_mode)
638{
639 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
640 data->defaultBoolCombine = j_mode;
641}
642
643
644/* Get a text representation of the current parameter values */
645JNIEXPORT jstring JNICALL
646Java_org_greenstone_mg_MGWrapper_getQueryParams(JNIEnv *j_env, jobject j_obj)
647{
648 MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
649 char result[512]; /* Assume this is big enough */
650
651 /* Print the data to a character array */
652 sprintf(result, "Query params:\nindex\t\t%s\ncasefold\t%d\nstem\t\t%d\norder by rank\t%d\nquery type\t%s\nmax docs\t%d\n",
653 (data->queryInfo->index == NULL ? "<none loaded>" : data->queryInfo->index),
654 (data->defaultStemMethod & 1),
655 (data->defaultStemMethod & 2),
656 (data->queryInfo->sortByRank),
657 (data->defaultBoolCombine == 1 ? "all" : "some"),
658 (data->queryInfo->maxDocs));
659
660 /* Convert to a jstring, and return */
661 return (*j_env)->NewStringUTF(j_env, result);
662}
Note: See TracBrowser for help on using the repository browser.