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

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

removed the iostream.h and strstream.h headers - were giving warnigns and don't seem to be needed

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