root/main/trunk/greenstone2/common-src/indexers/mg/jni/MGSearchWrapperImpl.c @ 25147

Revision 25147, 20.9 KB (checked in by kjdon, 8 years ago)

merged 64_bit_Greenstone branch into trunk, rev 25139

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 "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 */
144  (*j_env)->SetIntField(j_env, j_obj, FID_mg_data, (long) data);
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{
254  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
519  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
534  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
549  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
572  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
582  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
608  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
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{
617  MGWrapperData* data = (MGWrapperData*) (*j_env)->GetIntField(j_env, j_obj, FID_mg_data);
618  char result[512];  /* Assume this is big enough */
619
620  /* Print the data to a character array */
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",
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 browser.