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

Last change on this file since 4237 was 4237, checked in by kjdon, 21 years ago

changed the cerr error messages a bit

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