#include "LCFieldCacheImpl.h"
#include "GNUstep.h"
@interface LCIntParserImpl: LCIntParser
@end
@interface LCFloatParserImpl: LCFloatParser
@end
/**
* Expert: The default cache implementation, storing all values in memory.
* A WeakHashMap is used for storage.
*
*
Created: May 19, 2004 4:40:36 PM
*
* @author Tim Jones (Nacimiento Software)
* @since lucene 1.4
* @version $Id: LCFieldCacheImpl.m 827 2006-05-19 21:39:10Z yjchen $
*/
/** Expert: Every key in the internal cache is of this type. */
@implementation LCEntry
- (id) initWithField: (NSString *) f
type: (LCSortFieldType) t
locale: (id) l
{
self = [super init];
ASSIGN(field, f);
type = t;
custom = nil;
locale = l;
return self;
}
- (id) initWithField: (NSString *) f
custom: (id) c
{
self = [self initWithField: f type: LCSortField_CUSTOM locale: nil];
ASSIGN(custom, c);
return self;
}
- (NSString *) field { return field; }
- (LCSortFieldType) type { return type; }
- (id) custom { return custom; }
- (id) locale { return locale; }
- (void) setField: (NSString *) f { ASSIGN(field, f); }
- (void) setType: (LCSortFieldType) t { type = t; }
- (void) setCustom: (id) c { ASSIGN(custom, c); }
- (void) setLocale: (id) l { ASSIGN(locale, l); }
- (BOOL) isEqual: (id) o
{
if ([o isKindOfClass: [self class]])
{
LCEntry *other = (LCEntry *) o;
if ([[other field] isEqualToString: field] && ([other type] == type))
{
if (([other locale] == nil) ? (locale == nil) : [[other locale] isEqual: locale]) {
if (([other custom] == nil) && (custom == nil))
{
return YES;
}
else if ([[other custom] isEqual: custom])
{
return YES;
}
}
}
}
return NO;
}
- (unsigned) hash
{
return [field hash] ^ type ^ ((custom == nil) ? 0 : [custom hash]) ^ ((locale == nil) ? 0 : [locale hash]);
}
- (id) copyWithZone: (NSZone *) zone
{
LCEntry *entry = [[LCEntry allocWithZone: zone] initWithField: AUTORELEASE([[self field] copy]) type: [self type] locale: [self locale]];
[entry setCustom: [self custom]];
return entry;
}
@end
/** Indicator for StringIndex values in the cache. */
// NOTE: the value assigned to this constant must not be
// the same as any of those in SortField!!
//
static int LCFieldCache_STRING_INDEX = -1;
@implementation LCFieldCacheImpl
- (id) init
{
self = [super init];
cache = [[NSMutableDictionary alloc] init];
return self;
}
- (void) dealloc
{
DESTROY(cache);
[super dealloc];
}
/** See if an object is in the cache. */
- (id) lookup: (LCIndexReader *) reader field: (NSString *) field
type: (LCSortFieldType) type
locale: (id) locale
{
LCEntry *entry = [[LCEntry alloc] initWithField: field type: type locale: locale];
// synchronized (this) {
NSDictionary *readerCache = [cache objectForKey: reader];
if (readerCache == nil) return nil;
AUTORELEASE(entry);
return [readerCache objectForKey: entry];
// }
}
/** See if a custom object is in the cache. */
- (id) lookup: (LCIndexReader *) reader field: (NSString *) field
comparer: (id) comparer
{
LCEntry *entry = [[LCEntry alloc] initWithField: field custom: comparer];
// synchronized (this) {
NSDictionary *readerCache = [cache objectForKey: reader];
if (readerCache == nil) return nil;
AUTORELEASE(entry);
return [readerCache objectForKey: entry];
// }
}
/** Put an object into the cache. */
- (id) store: (LCIndexReader *) reader field: (NSString *) field
type: (LCSortFieldType) type locale: (id) locale
custom: (id) value
{
LCEntry *entry = [[LCEntry alloc] initWithField: field type: type locale: locale];
// synchronized (this) {
NSMutableDictionary *readerCache = [cache objectForKey: reader];
if (readerCache == nil)
{
readerCache = [[NSMutableDictionary alloc] init];
AUTORELEASE(readerCache);
}
[readerCache setObject: value forKey: entry];
[cache setObject: readerCache forKey: reader];
AUTORELEASE(entry);
return readerCache;
// }
}
/** Put a custom object into the cache. */
- (id) store: (LCIndexReader *) reader field: (NSString *) field
comparer: (id) comparer custom: (id) value
{
LCEntry *entry = [[LCEntry alloc] initWithField: field custom: comparer];
// synchronized (this) {
NSMutableDictionary *readerCache = [cache objectForKey: reader];
if (readerCache == nil)
{
readerCache = [[NSMutableDictionary alloc] init];
AUTORELEASE(readerCache);
}
[readerCache setObject: value forKey: entry];
[cache setObject: readerCache forKey: reader];
AUTORELEASE(entry);
return readerCache;
// }
}
- (NSDictionary *) ints: (LCIndexReader *) reader field: (NSString *) field
{
return [self ints: reader field: field parser: AUTORELEASE([[LCIntParserImpl alloc] init])];
}
- (NSDictionary *) ints: (LCIndexReader *) reader field: (NSString *) field
parser: (LCIntParser *) parser
{
id ret = [self lookup: reader field: field comparer: parser];
if (ret == nil) {
NSMutableDictionary *retDic = [[NSMutableDictionary alloc] init];
id termDocs = [reader termDocuments];
LCTerm *t = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *termEnum = [reader termEnumeratorWithTerm: t];
do {
LCTerm *term = [termEnum term];
if (term == nil || [[term field] isEqualToString: field] == NO) break;
int termval = [parser parseInt: [term text]];
[termDocs seekTermEnumerator: termEnum];
while ([termDocs hasNextDocument]) {
[retDic setObject: [NSNumber numberWithInt: termval]
forKey: [NSNumber numberWithInt: [termDocs document]]];
}
} while ([termEnum hasNextTerm]);
[termDocs close];
[termEnum close];
[self store: reader field: field comparer: parser custom: retDic];
return retDic;
}
return ret;
}
- (NSDictionary *) floats: (LCIndexReader *) reader field: (NSString *) field
{
return [self floats: reader field: field parser: AUTORELEASE([[LCFloatParserImpl alloc] init])];
}
- (NSDictionary *) floats: (LCIndexReader *) reader field: (NSString *) field
parser: (LCFloatParser *) parser
{
id ret = [self lookup: reader field: field comparer: parser];
if (ret == nil) {
NSMutableDictionary *retDic = [[NSMutableDictionary alloc] init];
id termDocs = [reader termDocuments];
LCTerm *t = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *termEnum = [reader termEnumeratorWithTerm: t];
do {
LCTerm *term = [termEnum term];
if (term == nil || [[term field] isEqualToString: field] == NO) break;
float termval = [parser parseFloat: [term text]];
[termDocs seekTermEnumerator: termEnum];
while ([termDocs hasNextDocument]) {
[retDic setObject: [NSNumber numberWithFloat: termval]
forKey: [NSNumber numberWithInt: [termDocs document]]];
}
} while ([termEnum hasNextTerm]);
[termDocs close];
[termEnum close];
[self store: reader field: field comparer: parser custom: retDic];
return retDic;
}
return ret;
}
- (NSDictionary *) strings: (LCIndexReader *) reader field: (NSString *) field
{
id ret = [self lookup: reader field: field type: LCSortField_STRING locale: nil];
if (ret == nil) {
NSMutableDictionary *retDic = [[NSMutableDictionary alloc] init];
id termDocs = [reader termDocuments];
LCTerm *t = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *termEnum = [reader termEnumeratorWithTerm: t];
do {
LCTerm *term = [termEnum term];
if (term == nil || [[term field] isEqualToString: field] == NO) break;
NSString *termval = [[term text] copy];
[termDocs seekTermEnumerator: termEnum];
while ([termDocs hasNextDocument]) {
[retDic setObject: AUTORELEASE(termval)
forKey: [NSNumber numberWithInt: [termDocs document]]];
}
} while ([termEnum hasNextTerm]);
[termDocs close];
[termEnum close];
[self store: reader field: field type: LCSortField_STRING locale: nil custom: retDic];
return retDic;
}
return ret;
}
- (LCStringIndex *) stringIndex: (LCIndexReader *) reader
field: (NSString *) field
{
id ret = [self lookup: reader field: field type: LCFieldCache_STRING_INDEX locale: nil];
if (ret == nil) {
NSMutableDictionary *retDic = [[NSMutableDictionary alloc] init];
NSMutableArray *mterms = [[NSMutableArray alloc] init];
#if 0
final int[] retArray = new int[reader.maxDoc()];
String[] mterms = new String[reader.maxDoc()+1];
#endif
id termDocs = [reader termDocuments];
LCTerm *tm = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *termEnum = [reader termEnumeratorWithTerm: tm];
RELEASE(tm);
int t = 0; // current term number
// an entry for documents that have no terms in this field
// should a document with no terms be at top or bottom?
// this puts them at the top - if it is changed, FieldDocSortedHitQueue
// needs to change as well.
/* LuceneKit: insert a non-NSString object */
//[mterms addObject: AUTORELEASE([[NSObject alloc] init])];
[mterms addObject: [NSNull null]];
do {
LCTerm *term = [termEnum term];
if (term == nil || [[term field] isEqualToString: field] == NO) break;
// store term text
// we expect that there is at most one term per document
// if (t >= mterms.length) throw new RuntimeException ("there are more terms than documents in field \"" + field + "\"");
[mterms addObject: AUTORELEASE([term text])];
[termDocs seekTermEnumerator: termEnum];
while ([termDocs hasNextDocument]) {
[retDic setObject: [NSNumber numberWithInt: t]
forKey: [NSNumber numberWithInt: [termDocs document]]];
}
t++;
} while ([termEnum hasNextTerm]);
[termDocs close];
[termEnum close];
if (t == 0) {
// if there are no terms, make the term array
// have a single null entry
/* LuceneKit: This is not going to happend */
[mterms addObject: [NSNull null]];
} else if (t < [reader maximalDocument]+1) {
// if there are less terms than documents,
// trim off the dead array space
/* LuceneKit: not necessary
String[] terms = new String[t];
System.arraycopy (mterms, 0, terms, 0, t);
mterms = terms;
*/
}
LCStringIndex *value = [[LCStringIndex alloc] initWithOrder: retDic
lookup: mterms];
[self store: reader field: field type: LCFieldCache_STRING_INDEX
locale: nil custom: value];
return AUTORELEASE(value);
}
return ret;
}
/** The pattern used to detect integer values in a field */
/** removed for java 1.3 compatibility
protected static final Pattern pIntegers = Pattern.compile ("[0-9\\-]+");
**/
/** The pattern used to detect float values in a field */
/**
* removed for java 1.3 compatibility
* protected static final Object pFloats = Pattern.compile ("[0-9+\\-\\.eEfFdD]+");
*/
- (id) objects: (LCIndexReader *) reader field: (NSString *) field
{
id ret = [self lookup: reader field: field type: LCSortField_AUTO locale: nil];
if (ret == nil) {
LCTerm *t = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *enumerator = [reader termEnumeratorWithTerm: t];
LCTerm *term = [enumerator term];
if (term == nil) {
NSLog(@"No terms in field %@ - cannot determin sort type", field);
return nil;
}
if ([[term field] isEqualToString: field]) {
NSString *termtext = [[term text] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
/**
* Java 1.4 level code:
if (pIntegers.matcher(termtext).matches())
return IntegerSortedHitQueue.comparator (reader, enumerator, field);
else if (pFloats.matcher(termtext).matches())
return FloatSortedHitQueue.comparator (reader, enumerator, field);
*/
// Java 1.3 level code:
/* May not be accurate */
int test_int = [termtext intValue];
/* FIXME */
if (test_int != 0)
{
ret = [self ints: reader field: field];
}
else
{
float test_float = [termtext floatValue];
/* FIXME */
if (test_float != 0.0)
{
ret = [self floats: reader field: field];
}
else
{
ret = [self stringIndex: reader field: field];
}
}
if (ret != nil) {
[self store: reader field: field type: LCSortField_AUTO locale: nil custom: ret];
}
} else {
NSLog(@"field \"%@\" does not apper to be indexed", field);
return nil;
}
[enumerator close];
}
return ret;
}
// inherit javadocs
- (NSDictionary *) custom: (LCIndexReader *) reader field: (NSString *) field
sortComparator: (LCSortComparator *) comparator
{
id ret = [self lookup: reader field: field comparer: comparator];
if (ret == nil) {
NSMutableDictionary *retDic = [[NSMutableDictionary alloc] init];
id termDocs = [reader termDocuments];
LCTerm *t = [[LCTerm alloc] initWithField: field text: @""];
LCTermEnumerator *termEnum = [reader termEnumeratorWithTerm: t];
do {
LCTerm *term = [termEnum term];
if (term == nil || [[term field] isEqualToString: field] == NO) break;
id termval = [comparator comparable: [term text]];
[termDocs seekTermEnumerator: termEnum];
while ([termDocs hasNextDocument]) {
[retDic setObject: termval
forKey: [NSNumber numberWithInt: [termDocs document]]];
}
} while ([termEnum hasNextTerm]);
[termDocs close];
[termEnum close];
[self store: reader field: field comparer: comparator custom: retDic];
return retDic;
}
return ret;
}
@end
@implementation LCIntParserImpl
- (int) parseInt: (NSString *) value
{
return [value intValue];
}
@end
@implementation LCFloatParserImpl
- (float) parseFloat: (NSString *) value
{
return [value floatValue];
}
@end