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

Last change on this file since 25244 was 25244, checked in by ak19, 12 years ago

GS3 tomcat server crashes because java crashes owing to some error in the JNI code. The error may be related to pointers having been stored as int rather than long, an issue that's become noticeable on 64 bit linux machines. Changes have been made in the JNI code where these pointers that are transferred between Java and C++ code are stored (GetIntField and SetIntField to GetLongField and SetLongField, as well as declaration of data_ptr as jlong not jint). Committing code first without debug statements so the commits can easily be done separately.

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