source: trunk/indexers/mg/jni/MGWrapperImpl.c@ 3981

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

Updated comments and a constant.

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