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

Last change on this file since 10015 was 10015, checked in by cs025, 19 years ago

Fixes for Mac OS X/Darwin

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