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

Last change on this file since 8948 was 8934, checked in by kjdon, 19 years ago

changed strstream to stringstream, cos strstream is deprecated

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