source: trunk/mgpp/jni/MGPPWrapperImpl.cpp@ 3365

Last change on this file since 3365 was 3365, checked in by kjdon, 22 years ago

Initial revision

  • Property svn:keywords set to Author Date Id Revision
File size: 14.5 KB
Line 
1#include <jni.h>
2#include "org_greenstone_mgpp_MGPPWrapper.h"
3#include "MGPPWrapperImpl.h"
4#include "TextGet.h"
5#include "GSDLQueryParser.h"
6#include "MGQuery.h"
7#include <iostream.h>
8#include <strstream.h>
9
10MGPPWrapperData::MGPPWrapperData() {
11 indexData = new IndexData();
12 queryInfo = new QueryInfo();
13
14 if (queryInfo==NULL) {
15 cerr<<"couldn't allocate new query info\n";
16 if (indexData!=NULL) {
17 delete indexData;
18 }
19 }
20
21 // set all the default params
22 SetCStr(queryInfo->docLevel, "Section"); // the level to search at
23 queryInfo->maxDocs = 50;
24 queryInfo->sortByRank = true;
25 queryInfo->exactWeights = false;
26 queryInfo->needRankInfo = true;
27 queryInfo->needTermFreqs = true;
28
29 UCArrayClear(level);
30 SetCStr(level, "Section"); // the level to return docs at
31 defaultStemMethod=0;
32 defaultBoolCombine=0;
33
34}
35
36MGPPWrapperData::~MGPPWrapperData() {
37 if (indexData !=NULL) {
38 delete indexData;
39 }
40 if (queryInfo !=NULL) {
41 delete queryInfo;
42 }
43}
44
45// ********************************************
46// initialisation stuff
47// ********************************************
48
49// cached ids for java stuff
50jfieldID FID_mgpp_data = NULL; // MGPPWrapperData
51jfieldID FID_query_result = NULL; // MGPPQueryResult
52jmethodID MID_addDoc=NULL; // MGPPQueryResult.addDoc()
53jmethodID MID_addTerm=NULL; // MGPPQueryResult.addTerm()
54jmethodID MID_setTotalDocs=NULL; // MGPPQueryResult.setTotalDocs()
55jmethodID MID_clearResult=NULL; //MGPPQueryResult.clear()
56jclass CID_String=NULL; // class ID of String
57
58/* to access objects and methods on java side, need their field/method ids -
59 this initialises them at the start to avoid recalculating them each time they
60 are needed
61Note: the descriptors need to be exactly right, otherwise you get an error
62saying "no such field" but no reference to the fact that it has the right
63name but the wrong type.
64Note: apparently the jclass is a local ref and should only work
65in the method that created it. It seems to work ok, but I'll make it
66 global cos the book said I should, and it may avoid future hassles.
67*/
68JNIEXPORT void JNICALL
69Java_org_greenstone_mgpp_MGPPWrapper_initIDs (JNIEnv *j_env, jclass j_cls) {
70
71 FID_mgpp_data = j_env->GetFieldID(j_cls, "mgpp_data_ptr_", "J"); //a long-"J"
72 if (FID_mgpp_data==NULL) {
73 cerr <<"field mgpp_data_ptr_ not found"<<endl;
74 }
75
76 FID_query_result = j_env->GetFieldID(j_cls, "mgpp_query_result_", "Lorg/greenstone/mgpp/MGPPQueryResult;"); // an object -"L<class name>;"
77 if (FID_query_result==NULL) {
78 cerr <<"field mgpp_query_result_ not found"<<endl;
79 }
80 // the methods we want to use
81
82 // addDoc(long doc, float rank)
83 jclass JC_MGPPQueryResult = j_env->FindClass("org/greenstone/mgpp/MGPPQueryResult");
84 MID_addDoc = j_env->GetMethodID(JC_MGPPQueryResult, "addDoc", "(JF)V");
85 if (MID_addDoc==NULL) {
86 cerr <<"method not found"<<endl;
87 }
88 // addTerm(String term, String tag, int stem_method, long match_docs,
89 // long term_freq, String[] equiv_terms)
90 MID_addTerm = j_env->GetMethodID(JC_MGPPQueryResult, "addTerm", "(Ljava/lang/String;Ljava/lang/String;IJJ[Ljava/lang/String;)V");
91 if (MID_addTerm==NULL) {
92 cerr <<"method addTerm not found"<<endl;
93 }
94
95 // setTotalDocs(long)
96 MID_setTotalDocs = j_env->GetMethodID(JC_MGPPQueryResult, "setTotalDocs", "(J)V");
97 if (MID_setTotalDocs==NULL) {
98 cerr <<"method setTotalDocs not found"<<endl;
99 }
100
101 MID_clearResult = j_env->GetMethodID(JC_MGPPQueryResult, "clear", "()V");
102 if (MID_clearResult==NULL) {
103 cerr <<"method clear not found"<<endl;
104 }
105
106 // get the class for String to use in NewObjectArray in runQuery()
107 // FindClass returns a local reference - have to convert it to a global one
108 jclass local_CID_String = j_env->FindClass("java/lang/String");
109 if (local_CID_String==NULL) {
110 cerr <<"java String class not found"<<endl;
111 } else {
112 /* create a global ref */
113 CID_String = (jclass)j_env->NewGlobalRef(local_CID_String);
114 /* The local reference is no longer useful */
115 j_env->DeleteLocalRef(local_CID_String);
116
117 /* Is the global reference created successfully? */
118 if (CID_String == NULL) {
119 return; /* out of memory exception thrown */
120 }
121 }
122
123}
124
125/* the java side MGPPWrapper has a pointer to a C++ object - MGPPWrapperData
126 initialise this and set the pointer
127*/
128JNIEXPORT jboolean JNICALL
129Java_org_greenstone_mgpp_MGPPWrapper_initCppSide (JNIEnv *j_env, jobject j_obj){
130
131 MGPPWrapperData * data = new MGPPWrapperData();
132 j_env->SetIntField(j_obj, FID_mgpp_data, (long)data);
133
134 return true;
135
136}
137
138//****************************************************
139// retrieve a document
140//****************************************************
141
142/* returns a document from mgpp as a string
143Note: TextData isn't cached - just reloaded each time
144*/
145JNIEXPORT jstring JNICALL
146Java_org_greenstone_mgpp_MGPPWrapper_getDocument (JNIEnv *j_env,
147 jobject j_obj, jstring j_base_dir,
148 jstring j_text_name, jstring j_level, jlong j_docnum) {
149
150
151 const char * base_dir = j_env->GetStringUTFChars(j_base_dir, NULL);
152 if (base_dir==NULL) {
153 return NULL; // exception already thrown
154 }
155 const char * text_name = j_env->GetStringUTFChars(j_text_name, NULL);
156
157 if (text_name==NULL) {
158 j_env->ReleaseStringUTFChars(j_base_dir, base_dir);
159 return NULL;
160 }
161
162 const char * level = j_env->GetStringUTFChars( j_level, NULL);
163 if (level==NULL) {
164 j_env->ReleaseStringUTFChars(j_base_dir, base_dir);
165 j_env->ReleaseStringUTFChars(j_text_name, text_name);
166 return NULL;
167 }
168
169 // does this work alright? j_docnum is a long (64 bit)
170 unsigned long docnum = j_docnum;
171 TextData td;
172
173 // cast to char* otherwise complains about const
174 td.LoadData((char *)base_dir, (char *)text_name);
175
176 UCArray mg_level;
177 SetCStr(mg_level, level);
178 UCArray docText;
179 docText.clear();
180 // get the actual text
181 if (!GetDocText(td, mg_level, docnum, docText)) {
182 cerr <<"couldn't retrieve doc text"<<endl;
183 }
184
185 td.UnloadData();
186
187 char * doc = GetCStr(docText); // do I need to free this char *??
188 jstring result = j_env->NewStringUTF(doc);
189 // release any gets
190 j_env->ReleaseStringUTFChars(j_base_dir, base_dir);
191 j_env->ReleaseStringUTFChars(j_text_name, text_name);
192 j_env->ReleaseStringUTFChars(j_level, level);
193
194 // free any C++ stuff
195 delete doc;
196
197 return result;
198
199}
200
201//******************************************
202// do a query
203// ****************************************
204
205/* load the IndexData - cached for querying
206 */
207JNIEXPORT jboolean JNICALL
208Java_org_greenstone_mgpp_MGPPWrapper_loadIndexData (JNIEnv *j_env, jobject j_obj, jstring j_base_dir, jstring j_index_name) {
209
210 jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
211 MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
212
213 const char * base_dir = j_env->GetStringUTFChars( j_base_dir, NULL);
214 if (base_dir==NULL) {
215 return false; // exception already thrown
216 }
217
218 const char * index_name = j_env->GetStringUTFChars( j_index_name, NULL);
219 if (index_name==NULL) {
220 j_env->ReleaseStringUTFChars(j_base_dir, base_dir);
221 return false;
222 }
223
224 jboolean j_result=false;
225
226 // why doesn't this complain about const??
227 if (data->indexData->LoadData(base_dir, index_name)) {
228 j_result=true;
229 }
230
231 // release any gets
232 j_env->ReleaseStringUTFChars(j_base_dir, base_dir);
233 j_env->ReleaseStringUTFChars(j_index_name, index_name);
234
235 return j_result;
236}
237
238/* unload the data
239 */
240JNIEXPORT jboolean JNICALL
241Java_org_greenstone_mgpp_MGPPWrapper_unloadIndexData (JNIEnv *j_env, jobject j_obj) {
242
243 jint data_ptr = j_env->GetIntField(j_obj, FID_mgpp_data);
244 MGPPWrapperData * data = (MGPPWrapperData *)data_ptr;
245
246 data->indexData->UnloadData();
247 return true;
248
249}
250
251/* do the actual query - the results are written to query_result held on the
252 java side */
253JNIEXPORT void JNICALL
254Java_org_greenstone_mgpp_MGPPWrapper_runQuery (JNIEnv *j_env, jobject j_obj, jstring j_query){
255
256 jthrowable exc; // an exception - check if something funny has happened
257 const char *query = j_env->GetStringUTFChars(j_query, NULL);
258 if (query==NULL) {
259 return; // exception already thrown
260 }
261 // turn to UCArray for mgpp and then release the string
262 UCArray queryArray;
263 SetCStr(queryArray, query);
264 j_env->ReleaseStringUTFChars(j_query, query);
265
266 // the query data
267 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
268
269 // the result to write to
270 jobject result_ptr = j_env->GetObjectField(j_obj, FID_query_result);
271 if (result_ptr==NULL) {
272 cerr <<"couldn't access the result to write to"<<endl;
273 return;
274 }
275
276 // clear the result
277 j_env->CallVoidMethod(result_ptr, MID_clearResult);
278 exc = j_env->ExceptionOccurred(); // this catches teh exception I think - it
279 //wont be thrown any further
280 if (exc) {
281 j_env->ExceptionDescribe();
282 return;
283 }
284 // the mgpp QueryResult that we will use
285 ExtQueryResult queryResult;
286
287 QueryNode * queryTree = NULL;
288 // parse the query string into a tree structure
289 queryTree = ParseQuery(queryArray, data->defaultBoolCombine,
290 data->defaultStemMethod);
291 // print the query
292 PrintNode (cout, queryTree);
293 // finally, do the query
294 MGQuery(*(data->indexData), *(data->queryInfo), queryTree, queryResult, data->level);
295
296 delete queryTree;
297
298 // convert queryResult to the java side version
299 // use levels rather than docs of ExtQueryResult
300 // CallVoidMethod(obj, method id, args to method)
301 for (int i=0; i<queryResult.levels.size(); i++) {
302 jlong doc = queryResult.levels[i];
303 jfloat rank = queryResult.ranks[i];
304 j_env->CallVoidMethod(result_ptr, MID_addDoc, doc, rank);
305 exc = j_env->ExceptionOccurred();
306 if (exc) {
307 j_env->ExceptionDescribe();
308 return;
309 }
310
311 }
312
313 // actual num of docs
314 jlong total = queryResult.actualNumDocs;
315 j_env->CallVoidMethod(result_ptr, MID_setTotalDocs, total);
316 exc = j_env->ExceptionOccurred();
317 if (exc) {
318 j_env->ExceptionDescribe();
319 return;
320 }
321
322 // the terms
323 for (int j=0; j<queryResult.termFreqs.size(); j++) {
324
325 TermFreqData tf = queryResult.termFreqs[j];
326 jstring term = j_env->NewStringUTF(GetCStr(tf.term));
327 jstring tag = j_env->NewStringUTF(GetCStr(tf.tag));
328 jint stem = tf.stemMethod;
329 jlong match = tf.matchDocs;
330 jlong freq = tf.termFreq;
331
332 jobjectArray equivs=NULL;
333 jstring empty = j_env->NewStringUTF(""); // the initial object to fill the array
334 jint num_equivs = tf.equivTerms.size();
335 equivs = j_env->NewObjectArray(num_equivs, CID_String, empty);
336 if (equivs==NULL) {
337 cerr<<"couldn't create object array"<<endl;
338
339 } else {
340 for (int k=0; k<num_equivs;k++) {
341 jstring equiv = j_env->NewStringUTF(GetCStr(tf.equivTerms[k]));
342 j_env->SetObjectArrayElement(equivs, k, equiv);
343 }
344
345
346 j_env->CallVoidMethod(result_ptr, MID_addTerm, term, tag, stem, match, freq, equivs);
347 exc = j_env->ExceptionOccurred();
348 if (exc) {
349 j_env->ExceptionDescribe();
350 return;
351 }
352 }
353 }
354
355
356}
357
358JNIEXPORT void JNICALL
359Java_org_greenstone_mgpp_MGPPWrapper_setStem (JNIEnv *j_env,
360 jobject j_obj,
361 jboolean j_on) {
362 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
363 if (j_on) {
364 data->defaultStemMethod |= 2;
365 } else {
366 data->defaultStemMethod &= 0xd;
367 }
368
369}
370
371JNIEXPORT void JNICALL
372Java_org_greenstone_mgpp_MGPPWrapper_setCase (JNIEnv *j_env,
373 jobject j_obj,
374 jboolean j_on) {
375 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
376
377 if (j_on) {
378 data->defaultStemMethod |= 1;
379 } else {
380 data->defaultStemMethod &= 0xe;
381 }
382}
383
384JNIEXPORT void JNICALL
385Java_org_greenstone_mgpp_MGPPWrapper_setMaxDocs (JNIEnv *j_env,
386 jobject j_obj,
387 jint j_max) {
388 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
389 data->queryInfo->maxDocs=j_max;
390}
391
392JNIEXPORT void JNICALL
393Java_org_greenstone_mgpp_MGPPWrapper_setSortByRank (JNIEnv *j_env,
394 jobject j_obj,
395 jboolean j_on) {
396 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
397
398 data->queryInfo->sortByRank=j_on;
399}
400
401JNIEXPORT void JNICALL
402Java_org_greenstone_mgpp_MGPPWrapper_setReturnTerms(JNIEnv *j_env,
403 jobject j_obj,
404 jboolean j_on) {
405 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
406 data->queryInfo->needTermFreqs = j_on;
407
408}
409
410JNIEXPORT void JNICALL
411Java_org_greenstone_mgpp_MGPPWrapper_setQueryLevel(JNIEnv *j_env,
412 jobject j_obj,
413 jstring j_level){
414
415 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
416
417 const char * level = j_env->GetStringUTFChars(j_level, NULL);
418 if (level==NULL) {
419 return; // exception already thrown
420 }
421
422 data->queryInfo->docLevel.clear();
423 SetCStr(data->queryInfo->docLevel, level);
424
425 // release the java stuff
426 j_env->ReleaseStringUTFChars(j_level, level);
427
428}
429
430JNIEXPORT void JNICALL
431Java_org_greenstone_mgpp_MGPPWrapper_setReturnLevel(JNIEnv *j_env,
432 jobject j_obj,
433 jstring j_level){
434
435 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
436
437 const char * level = j_env->GetStringUTFChars(j_level, NULL);
438 if (level==NULL) {
439 return; // exception already thrown
440 }
441
442 data->level.clear();
443 SetCStr(data->level, level);
444
445 // release the java stuff
446 j_env->ReleaseStringUTFChars(j_level, level);
447
448
449}
450
451JNIEXPORT void JNICALL
452Java_org_greenstone_mgpp_MGPPWrapper_setMatchMode (JNIEnv *j_env,
453 jobject j_obj,
454 jint j_mode){
455
456 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
457 data->defaultBoolCombine=j_mode;
458
459}
460
461JNIEXPORT jstring JNICALL
462Java_org_greenstone_mgpp_MGPPWrapper_getQueryParams (JNIEnv *j_env,
463 jobject j_obj){
464
465 MGPPWrapperData * data = (MGPPWrapperData *)j_env->GetIntField(j_obj, FID_mgpp_data);
466
467 // print the data to an output string stream, then convert to char*, then to
468 //jstring
469
470 ostrstream output;
471 output << "Query params:"<<endl
472 // need to change this to use platform specific separator for niceness
473 << "index\t\t"<<data->indexData->basePath<<"/"<<data->indexData->filename<<endl
474 <<"search level\t"<<GetCStr(data->queryInfo->docLevel)<<endl
475 <<"result level\t"<<GetCStr(data->level)<<endl
476 <<"casefold\t"<<(data->defaultStemMethod&1)<<endl
477 <<"stem\t\t"<<(data->defaultStemMethod&2)<<endl
478 <<"order by rank\t"<<data->queryInfo->sortByRank<<endl
479 <<"query type\t"<<(data->defaultBoolCombine==1?"all":"some")<<endl
480 <<"max docs\t"<<data->queryInfo->maxDocs<<endl<<ends;
481
482 char *result = output.str();
483 jstring j_result = j_env->NewStringUTF(result);
484 delete result;
485 return j_result;
486}
Note: See TracBrowser for help on using the repository browser.