Author: navssurtani
Date: 2008-06-16 12:58:35 -0400 (Mon, 16 Jun 2008)
New Revision: 5990
Added:
searchable/trunk/src/main/java/org/jboss/cache/search/InvalidFqnException.java
searchable/trunk/src/test/java/org/
searchable/trunk/src/test/java/org/jboss/
searchable/trunk/src/test/java/org/jboss/cache/
searchable/trunk/src/test/java/org/jboss/cache/search/
searchable/trunk/src/test/java/org/jboss/cache/search/BlackBoxTest.java
searchable/trunk/src/test/java/org/jboss/cache/search/TransformerTest.java
searchable/trunk/src/test/java/org/jboss/cache/search/test/
searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java
Removed:
searchable/trunk/src/main/java/org/jboss/cache/search/QueryResult.java
searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultImpl.java
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java
searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java
searchable/trunk/src/main/java/org/jboss/cache/search/NodeModifiedTransactionContext.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCache.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java
searchable/trunk/src/main/java/org/jboss/cache/search/Transformer.java
Log:
Renamed stuff
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/CacheQuery.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -3,12 +3,13 @@
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Sort;
import org.hibernate.search.FullTextFilter;
+
/**
@author Navin Surtani - navin(a)surtani.org
*/
+// TODO: Can we remove this?
public interface CacheQuery
{
- //TODO: Figure out where we got this interface from ... then get the methods from the
impl of THAT impl and copy it into CacheQuery impl.
/**
* Allows to let lucene sort the results. This is useful when you have
* additional sort requirements on top of the default lucene ranking.
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/CacheQueryImpl.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -2,64 +2,80 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.*;
+import org.apache.lucene.search.Query;
import org.apache.lucene.search.Filter;
-import org.apache.lucene.search.Hits;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.Sort;
-import org.hibernate.HibernateException;
+import org.hibernate.*;
+import org.hibernate.type.Type;
+import org.hibernate.transform.ResultTransformer;
import org.hibernate.search.FullTextFilter;
+import org.hibernate.search.FullTextQuery;
import org.hibernate.search.SearchException;
+import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.engine.FilterDef;
import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.hibernate.search.filter.ChainedFilter;
+import org.hibernate.search.filter.FilterKey;
import org.hibernate.search.impl.SearchFactoryImpl;
import org.hibernate.search.query.FullTextFilterImpl;
-import org.hibernate.search.util.ContextHelper;
+import org.hibernate.search.reader.ReaderProvider;
+import static org.hibernate.search.reader.ReaderProviderHelper.getIndexReaders;
+import org.hibernate.search.store.DirectoryProvider;
import org.jboss.cache.Cache;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import java.math.BigDecimal;
+import java.math.BigInteger;
/**
* @author Navin Surtani - navin(a)surtani.org
*/
-public class CacheQueryImpl implements CacheQuery
+public class CacheQueryImpl implements FullTextQuery
{
//TODO: Javadoc all these methods
- private Query query;
private Cache cache;
private Class[] classes;
private Sort sort;
private Filter filter;
private Map<String, FullTextFilterImpl> filterDefinitions;
- private SearchFactoryImplementor searchFactoryImplementor;
+ private SearchFactoryImpl searchFactory;
private Integer firstResult;
private Integer resultSize;
private Integer maxResults;
private static final Log log = LogFactory.getLog(CacheQueryImpl.class);
+ private Set<Class> classesAndSubclasses;
+ private boolean needClassFilterClause;
+ private Query luceneQuery;
+ private int fetchSize;
- public CacheQueryImpl(Query luceneQuery, Cache cache)
+ public CacheQueryImpl(Query luceneQuery, SearchFactoryImpl searchFactory, Cache
cache)
{
- this.query = luceneQuery;
+ this.luceneQuery = luceneQuery;
this.cache = cache;
+ this.searchFactory = searchFactory;
}
- public CacheQueryImpl(Query luceneQuery, Cache cache, Class... classes)
+ public CacheQueryImpl(Query luceneQuery, SearchFactoryImpl searchFactory, Cache cache,
Class... classes)
{
- this.query = luceneQuery;
+ this.luceneQuery = luceneQuery;
this.cache = cache;
this.classes = classes;
+ this.searchFactory = searchFactory;
}
- public CacheQuery setSort(Sort sort)
+ public FullTextQuery setSort(Sort sort)
{
this.sort = sort;
return this;
}
- public CacheQuery setFilter(Filter filter)
+ public FullTextQuery setFilter(Filter filter)
{
this.filter = filter;
return this;
@@ -70,8 +86,7 @@
if (resultSize == null)
{
//get result size without object initialization
- SearchFactoryImplementor searchFactoryImplementor =
ContextHelper.getSearchFactoryBySFI(session);
- IndexSearcher searcher = buildSearcher(searchFactoryImplementor);
+ IndexSearcher searcher = buildSearcher(searchFactory);
if (searcher == null)
{
resultSize = 0;
@@ -93,12 +108,12 @@
//searcher cannot be null
try
{
- closeSearcher(searcher, searchFactoryImplementor.getReaderProvider());
+ closeSearcher(searcher, searchFactory.getReaderProvider());
//searchFactoryImplementor.getReaderProvider().closeReader(
searcher.getIndexReader() );
}
catch (SearchException e)
{
- log.warn("Unable to properly close searcher during lucene query:
" + getQueryString(), e);
+ log.warn("Unable to properly close searcher during lucene query:
" + e);
}
}
}
@@ -106,6 +121,24 @@
return this.resultSize;
}
+ public FullTextQuery setCriteriaQuery(Criteria criteria)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public FullTextQuery setProjection(String... strings)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ private void closeSearcher(Searcher searcher, ReaderProvider readerProvider) {
+ Set<IndexReader> indexReaders = getIndexReaders( searcher );
+
+ for (IndexReader indexReader : indexReaders) {
+ readerProvider.closeReader( indexReader );
+ }
+ }
+
public FullTextFilter enableFullTextFilter(String name)
{
if (filterDefinitions == null)
@@ -117,7 +150,7 @@
filterDefinition = new FullTextFilterImpl();
filterDefinition.setName(name);
- FilterDef filterDef = getSearchFactoryImplementor().getFilterDefinition(name);
+ FilterDef filterDef = searchFactory.getFilterDefinition(name);
if (filterDef == null)
{
throw new SearchException("Unkown @FullTextFilter: " + name);
@@ -126,44 +159,653 @@
return filterDefinition;
}
- private SearchFactoryImplementor getSearchFactoryImplementor()
+ public void disableFullTextFilter(String name)
{
- if (searchFactoryImplementor == null)
+ filterDefinitions.remove(name);
+ }
+
+ public FullTextQuery setFirstResult(int firstResult)
+ {
+ if (firstResult < 0)
{
- searchFactoryImplementor = createNewSearchFactoryImpl();
+ throw new IllegalArgumentException("'first' pagination parameter
less than 0");
}
- return searchFactoryImplementor;
+ this.firstResult = firstResult;
+ return this;
}
- private synchronized SearchFactoryImplementor createNewSearchFactoryImpl()
+ public org.hibernate.Query setReadOnly(boolean b)
{
- if (searchFactoryImplementor == null) searchFactoryImplementor = new
SearchFactoryImpl(null); // TODO: This really expects a Hibernate Config object. How can
we work around that?@??
- return searchFactoryImplementor;
+ return null; //TODO: Generated method. Do we need this method?
}
+ public org.hibernate.Query setCacheable(boolean b)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
- public void disableFullTextFilter(String name)
+ public org.hibernate.Query setCacheRegion(String s)
{
- filterDefinitions.remove(name);
+ return null; //TODO: Generated method. Do we need this method?
}
- public CacheQuery setFirstResult(int firstResult)
+ public org.hibernate.Query setTimeout(int i)
{
- if (firstResult < 0)
- {
- throw new IllegalArgumentException("'first' pagination parameter
less than 0");
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public String getQueryString()
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public Type[] getReturnTypes() throws HibernateException
+ {
+ return new Type[0]; //TODO: Generated method. Do we need this method?
+ }
+
+ public String[] getReturnAliases() throws HibernateException
+ {
+ return new String[0]; //TODO: Generated method. Do we need this method?
+ }
+
+ public String[] getNamedParameters() throws HibernateException
+ {
+ return new String[0]; //TODO: Generated method. Do we need this method?
+ }
+
+ public Iterator iterate() throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public ScrollableResults scroll() throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public List list() throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public Object uniqueResult() throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public int executeUpdate() throws HibernateException
+ {
+ return 0; //TODO: Generated method. Do we need this method?
+ }
+
+ public FullTextQuery setMaxResults(int maxResults) {
+ if ( maxResults < 0 ) {
+ throw new IllegalArgumentException( "'max' pagination parameter
less than 0" );
}
- this.firstResult = firstResult;
+ this.maxResults = maxResults;
return this;
}
- public CacheQuery setMaxResults(int maxResults)
+ public FullTextQuery setFetchSize(int fetchSize) {
+ if ( fetchSize <= 0 ) {
+ throw new IllegalArgumentException( "'fetch size' parameter less
than or equals to 0" );
+ }
+ this.fetchSize = fetchSize;
+ return this;
+ }
+
+ public org.hibernate.Query setLockMode(String s, LockMode lockMode)
{
- return null; //To change body of implemented methods use File | Settings | File
Templates.
+ return null; //TODO: Generated method. Do we need this method?
}
- public CacheQuery setFetchSize(int i)
+ public org.hibernate.Query setComment(String s)
{
- return null; //To change body of implemented methods use File | Settings | File
Templates.
+ return null; //TODO: Generated method. Do we need this method?
}
+
+ public org.hibernate.Query setFlushMode(FlushMode flushMode)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCacheMode(CacheMode cacheMode)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameter(int i, Object o, Type type)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameter(String s, Object o, Type type)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameter(int i, Object o) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameter(String s, Object o) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameters(Object[] objects, Type[] types) throws
HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameterList(String s, Collection collection, Type
type) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameterList(String s, Collection collection) throws
HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameterList(String s, Object[] objects, Type type)
throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setParameterList(String s, Object[] objects) throws
HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setProperties(Object o) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setProperties(Map map) throws HibernateException
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setString(int i, String s)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCharacter(int i, char c)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBoolean(int i, boolean b)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setByte(int i, byte b)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setShort(int i, short i1)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setInteger(int i, int i1)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setLong(int i, long l)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setFloat(int i, float v)
+ {
+ throw new UnsupportedOperationException("Not supported in
SearchableCache!");
+ }
+
+ public org.hibernate.Query setDouble(int i, double v)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBinary(int i, byte[] bytes)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setText(int i, String s)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setSerializable(int i, Serializable serializable)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setLocale(int i, Locale locale)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBigDecimal(int i, BigDecimal bigDecimal)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBigInteger(int i, BigInteger bigInteger)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setDate(int i, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setTime(int i, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setTimestamp(int i, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCalendar(int i, Calendar calendar)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCalendarDate(int i, Calendar calendar)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setString(String s, String s1)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCharacter(String s, char c)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBoolean(String s, boolean b)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setByte(String s, byte b)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setShort(String s, short i)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setInteger(String s, int i)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setLong(String s, long l)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setFloat(String s, float v)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setDouble(String s, double v)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBinary(String s, byte[] bytes)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setText(String s, String s1)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setSerializable(String s, Serializable serializable)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setLocale(String s, Locale locale)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBigDecimal(String s, BigDecimal bigDecimal)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setBigInteger(String s, BigInteger bigInteger)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setDate(String s, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setTime(String s, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setTimestamp(String s, Date date)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCalendar(String s, Calendar calendar)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setCalendarDate(String s, Calendar calendar)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setEntity(int i, Object o)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public org.hibernate.Query setEntity(String s, Object o)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ public FullTextQuery setResultTransformer(ResultTransformer resultTransformer)
+ {
+ return null; //TODO: Generated method. Do we need this method?
+ }
+
+ private IndexSearcher buildSearcher(SearchFactoryImplementor
searchFactoryImplementor)
+ {
+ Map<Class, DocumentBuilder<Object>> builders =
searchFactoryImplementor.getDocumentBuilders();
+ List<DirectoryProvider> directories = new
ArrayList<DirectoryProvider>();
+
+ Similarity searcherSimilarity = null;
+
+ if (classes == null || classes.length == 0)
+ {
+ //no class means all classes
+ for (DocumentBuilder builder : builders.values())
+ {
+ searcherSimilarity = checkSimilarity(searcherSimilarity, builder);
+ final DirectoryProvider[] directoryProviders =
builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
+ populateDirectories(directories, directoryProviders,
searchFactoryImplementor);
+ }
+ classesAndSubclasses = null;
+ }
+ else
+ {
+ Set<Class> involvedClasses = new HashSet<Class>(classes.length);
+ Collections.addAll(involvedClasses, classes);
+ for (Class clazz : classes)
+ {
+ DocumentBuilder builder = builders.get(clazz);
+ if (builder != null) involvedClasses.addAll(builder.getMappedSubclasses());
+ }
+
+ for (Class clazz : involvedClasses)
+ {
+ DocumentBuilder builder = builders.get(clazz);
+ if (builder == null)
+ throw new HibernateException("Not a mapped entity (don't forget
to add @Indexed): " + clazz);
+
+ final DirectoryProvider[] directoryProviders =
builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
+ searcherSimilarity = checkSimilarity(searcherSimilarity, builder);
+ populateDirectories(directories, directoryProviders,
searchFactoryImplementor);
+ }
+ classesAndSubclasses = involvedClasses;
+ }
+
+ //compute optimization needClassFilterClause
+ //if at least one DP contains one class that is not part of the targeted
classesAndSubclasses we can't optimize
+ if (classesAndSubclasses != null)
+ {
+ for (DirectoryProvider dp : directories)
+ {
+ final Set<Class> classesInDirectoryProvider =
searchFactoryImplementor.getClassesInDirectoryProvider(dp);
+ // if a DP contains only one class, we know for sure it's part of
classesAndSubclasses
+ if (classesInDirectoryProvider.size() > 1)
+ {
+ //risk of needClassFilterClause
+ for (Class clazz : classesInDirectoryProvider)
+ {
+ if (!classesAndSubclasses.contains(clazz))
+ {
+ this.needClassFilterClause = true;
+ break;
+ }
+ }
+ }
+ if (this.needClassFilterClause) break;
+ }
+ }
+
+ //set up the searcher
+ final DirectoryProvider[] directoryProviders = directories.toArray(new
DirectoryProvider[directories.size()]);
+ IndexSearcher is = new
IndexSearcher(searchFactoryImplementor.getReaderProvider().openReader(directoryProviders));
+ is.setSimilarity(searcherSimilarity);
+ return is;
+ }
+
+ private Similarity checkSimilarity(Similarity similarity, DocumentBuilder builder)
+ {
+ if (similarity == null)
+ {
+ similarity = builder.getSimilarity();
+ }
+ else if (!similarity.getClass().equals(builder.getSimilarity().getClass()))
+ {
+ throw new HibernateException("Cannot perform search on two entities with
differing Similarity implementations (" + similarity.getClass().getName() + "
& " + builder.getSimilarity().getClass().getName() + ")");
+ }
+
+ return similarity;
+ }
+
+ private void populateDirectories(List<DirectoryProvider> directories,
DirectoryProvider[] directoryProviders,
+ SearchFactoryImplementor searchFactoryImplementor)
+ {
+ for (DirectoryProvider provider : directoryProviders)
+ {
+ if (!directories.contains(provider))
+ {
+ directories.add(provider);
+ }
+ }
+ }
+
+ private Hits getHits(Searcher searcher) throws IOException
+ {
+ Hits hits;
+ org.apache.lucene.search.Query query = filterQueryByClasses(luceneQuery);
+ buildFilters();
+ hits = searcher.search(query, filter, sort);
+ setResultSize(hits);
+ return hits;
+ }
+
+ private void setResultSize(Hits hits)
+ {
+ resultSize = hits.length();
+ }
+
+ private org.apache.lucene.search.Query
filterQueryByClasses(org.apache.lucene.search.Query luceneQuery)
+ {
+ if (!needClassFilterClause)
+ {
+ return luceneQuery;
+ }
+ else
+ {
+ //A query filter is more practical than a manual class filtering post query (esp
on scrollable resultsets)
+ //it also probably minimise the memory footprint
+ BooleanQuery classFilter = new BooleanQuery();
+ //annihilate the scoring impact of DocumentBuilder.CLASS_FIELDNAME
+ classFilter.setBoost(0);
+ for (Class clazz : classesAndSubclasses)
+ {
+ Term t = new Term(DocumentBuilder.CLASS_FIELDNAME, clazz.getName());
+ TermQuery termQuery = new TermQuery(t);
+ classFilter.add(termQuery, BooleanClause.Occur.SHOULD);
+ }
+ BooleanQuery filteredQuery = new BooleanQuery();
+ filteredQuery.add(luceneQuery, BooleanClause.Occur.MUST);
+ filteredQuery.add(classFilter, BooleanClause.Occur.MUST);
+ return filteredQuery;
+ }
+ }
+
+ private void buildFilters()
+ {
+ if (filterDefinitions != null && filterDefinitions.size() > 0)
+ {
+ ChainedFilter chainedFilter = new ChainedFilter();
+ for (FullTextFilterImpl filterDefinition : filterDefinitions.values())
+ {
+ FilterDef def =
searchFactory.getFilterDefinition(filterDefinition.getName());
+ Class implClass = def.getImpl();
+ Object instance;
+ try
+ {
+ instance = implClass.newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new SearchException("Unable to create @FullTextFilterDef:
" + def.getImpl(), e);
+ }
+ for (Map.Entry<String, Object> entry :
filterDefinition.getParameters().entrySet())
+ {
+ def.invoke(entry.getKey(), instance, entry.getValue());
+ }
+ if (def.isCache() && def.getKeyMethod() == null &&
filterDefinition.getParameters().size() > 0)
+ {
+ throw new SearchException("Filter with parameters and no @Key method:
" + filterDefinition.getName());
+ }
+ FilterKey key = null;
+ if (def.isCache())
+ {
+ if (def.getKeyMethod() == null)
+ {
+ key = new FilterKey()
+ {
+ public int hashCode()
+ {
+ return getImpl().hashCode();
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof FilterKey)) return false;
+ FilterKey that = (FilterKey) obj;
+ return this.getImpl().equals(that.getImpl());
+ }
+ };
+ }
+ else
+ {
+ try
+ {
+ key = (FilterKey) def.getKeyMethod().invoke(instance);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new SearchException("Unable to access @Key method:
"
+ + def.getImpl().getName() + "." +
def.getKeyMethod().getName());
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new SearchException("Unable to access @Key method:
"
+ + def.getImpl().getName() + "." +
def.getKeyMethod().getName());
+ }
+ catch (ClassCastException e)
+ {
+ throw new SearchException("@Key method does not return
FilterKey: "
+ + def.getImpl().getName() + "." +
def.getKeyMethod().getName());
+ }
+ }
+ key.setImpl(def.getImpl());
+ }
+
+ Filter filter = def.isCache() ?
+ searchFactory.getFilterCachingStrategy().getCachedFilter(key) :
+ null;
+ if (filter == null)
+ {
+ if (def.getFactoryMethod() != null)
+ {
+ try
+ {
+ filter = (Filter) def.getFactoryMethod().invoke(instance);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new SearchException("Unable to access @Factory method:
"
+ + def.getImpl().getName() + "." +
def.getFactoryMethod().getName());
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new SearchException("Unable to access @Factory method:
"
+ + def.getImpl().getName() + "." +
def.getFactoryMethod().getName());
+ }
+ catch (ClassCastException e)
+ {
+ throw new SearchException("@Key method does not return a
org.apache.lucene.search.Filter class: "
+ + def.getImpl().getName() + "." +
def.getFactoryMethod().getName());
+ }
+ }
+ else
+ {
+ try
+ {
+ filter = (Filter) instance;
+ }
+ catch (ClassCastException e)
+ {
+ throw new SearchException("@Key method does not return a
org.apache.lucene.search.Filter class: "
+ + def.getImpl().getName() + "." +
def.getFactoryMethod().getName());
+ }
+ }
+ if (def.isCache())
+ searchFactory.getFilterCachingStrategy().addCachedFilter(key, filter);
+ }
+ chainedFilter.addFilter(filter);
+ }
+ if (filter != null) chainedFilter.addFilter(filter);
+ filter = chainedFilter;
+ }
+ }
}
Added: searchable/trunk/src/main/java/org/jboss/cache/search/InvalidFqnException.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/InvalidFqnException.java
(rev 0)
+++
searchable/trunk/src/main/java/org/jboss/cache/search/InvalidFqnException.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -0,0 +1,28 @@
+package org.jboss.cache.search;
+
+import org.jboss.cache.CacheException;
+
+/**
+ * @author Navin Surtani - navin(a)surtani.org
+ */
+public class InvalidFqnException extends CacheException
+{
+ public InvalidFqnException()
+ {
+ }
+
+ public InvalidFqnException(String s)
+ {
+ super(s);
+ }
+
+ public InvalidFqnException(String s, Throwable throwable)
+ {
+ super(s, throwable);
+ }
+
+ public InvalidFqnException(Throwable throwable)
+ {
+ super(throwable);
+ }
+}
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/NodeModifiedTransactionContext.java
===================================================================
---
searchable/trunk/src/main/java/org/jboss/cache/search/NodeModifiedTransactionContext.java 2008-06-16
14:26:08 UTC (rev 5989)
+++
searchable/trunk/src/main/java/org/jboss/cache/search/NodeModifiedTransactionContext.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -5,8 +5,6 @@
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
/**
@author Navin Surtani - navin(a)surtani.org
@@ -17,6 +15,11 @@
//TODO: Javadoc all these methods
NodeModifiedEvent event;
+ public NodeModifiedTransactionContext(NodeModifiedEvent event)
+ {
+ this.event = event;
+ }
+
public boolean isTxInProgress()
{
return (event.getTransaction() != null);
@@ -34,14 +37,9 @@
{
transaction.registerSynchronization(synchronization);
}
- catch (SystemException e)
+ catch (Exception e)
{
- e.printStackTrace();
+ throw new RuntimeException(e);
}
- catch (RollbackException e)
- {
- e.printStackTrace();
- }
-
}
}
Deleted: searchable/trunk/src/main/java/org/jboss/cache/search/QueryResult.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/QueryResult.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/QueryResult.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -1,72 +0,0 @@
-package org.jboss.cache.search;
-
-import org.apache.lucene.search.Filter;
-import org.apache.lucene.search.Sort;
-import org.hibernate.search.FullTextFilter;
-import org.hibernate.search.FullTextQuery;
-
-/**
- * Created by IntelliJ IDEA.
- * User: navin
- * Date: Jun 3, 2008
- * Time: 3:13:27 PM
- * To change this template use File | Settings | File Templates.
- */
-public interface QueryResult {
-
- /**
- * Allows to let lucene sort the results. This is useful when you have
- * additional sort requirements on top of the default lucene ranking.
- * Without lucene sorting you would have to retrieve the full result set and
- * order the hibernate objects.
- *
- * @param sort The lucene sort object.
- * @return this for method chaining
- */
- FullTextQuery setSort(Sort sort);
-
- /**
- * Allows to use lucene filters.
- * Semi-deprecated? a preferred way is to use the @FullTextFilterDef approach
- *
- * @param filter The lucene filter.
- * @return this for method chaining
- */
- FullTextQuery setFilter(Filter filter);
-
- /**
- * Returns the number of hits for this search
- * <p/>
- * Caution:
- * The number of results might be slightly different from
- * <code>list().size()</code> because list() if the index is
- * not in sync with the database at the time of query.
- */
- int getResultSize();
-
- /**
- * Enable a given filter by its name. Returns a FullTextFilter object that allows
filter parameter injection
- */
- FullTextFilter enableFullTextFilter(String name);
-
- /**
- * Disable a given filter by its name
- */
- void disableFullTextFilter(String name);
-
- /**
- * {link:Query#setFirstResult}
- */
- FullTextQuery setFirstResult(int firstResult);
-
- /**
- * {link:Query#setMaxResults}
- */
- FullTextQuery setMaxResults(int maxResults);
-
- /**
- * Defines scrollable result fetch size as well as the JDBC fetch size
- */
- FullTextQuery setFetchSize(int i);
-
-}
Deleted: searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultImpl.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/QueryResultImpl.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -1,76 +0,0 @@
-package org.jboss.cache.search;
-
-import org.hibernate.search.FullTextQuery;
-import org.hibernate.search.FullTextFilter;
-import org.apache.lucene.search.Sort;
-import org.apache.lucene.search.Filter;
-import org.apache.lucene.search.Query;
-import org.jboss.cache.Cache;
-
-/**
- * Created by IntelliJ IDEA.
- * User: navin
- * Date: Jun 3, 2008
- * Time: 3:23:25 PM
- * To change this template use File | Settings | File Templates.
- */
-public class QueryResultImpl implements QueryResult
-{
- private Query query;
- private Cache cache;
- private Class[] classes;
-
- public QueryResultImpl(Query luceneQuery, Cache cache)
- {
- this.query = luceneQuery;
- this.cache = cache;
- }
-
- public QueryResultImpl(Query luceneQuery, Cache cache, Class[] classes)
- {
- this.query = luceneQuery;
- this.cache=cache;
- this.classes = classes;
-
- }
-
- public FullTextQuery setSort(Sort sort)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public FullTextQuery setFilter(Filter filter)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public int getResultSize()
- {
- return 0; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public FullTextFilter enableFullTextFilter(String name)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public void disableFullTextFilter(String name)
- {
- //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public FullTextQuery setFirstResult(int firstResult)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public FullTextQuery setMaxResults(int maxResults)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-
- public FullTextQuery setFetchSize(int i)
- {
- return null; //To change body of implemented methods use File | Settings | File
Templates.
- }
-}
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCache.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCache.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCache.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -1,6 +1,7 @@
package org.jboss.cache.search;
import org.apache.lucene.search.Query;
+import org.hibernate.search.FullTextQuery;
import org.jboss.cache.Cache;
/**
@@ -14,8 +15,8 @@
* @param luceneQuery
* @return
*/
- public CacheQuery createQuery(Query luceneQuery);
+ public FullTextQuery createQuery(Query luceneQuery);
- public CacheQuery createQuery(Query luceneQuery, Class... classes);
+ public FullTextQuery createQuery(Query luceneQuery, Class... classes);
}
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java
===================================================================
---
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java 2008-06-16
14:26:08 UTC (rev 5989)
+++
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -1,8 +1,12 @@
package org.jboss.cache.search;
+import org.hibernate.cfg.Configuration;
import org.hibernate.search.impl.SearchFactoryImpl;
import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+import java.util.Properties;
+
/**
@author Navin Surtani - navin(a)surtani.org
*/
@@ -13,13 +17,32 @@
public SearchableCache createSearchableCache (Cache c, Class... classes)
{
+ return createSearchableCache(c, null, classes);
+ }
- // TODO: Initialise HS internals and use the classes array that's being passed
in as a param
+ public SearchableCache createSearchableCache (Cache c, Properties properties, Class...
classes)
+ {
+ // assume cache is already created and running.
+ // otherwise, start the cache!!
+ if (c.getCacheStatus() != CacheStatus.STARTED) c.start();
+ // Step 1: Add cache listener to listen for events happening in the cache.
SearchableListener listener = new SearchableListener();
c.addCacheListener(listener);
- SearchableCache sc = new SearchableCacheImpl(c);
+ // step 2: create hibernate search searchImpl
+ Configuration cfg = new Configuration();
+ if (properties != null) cfg.setProperties(properties);
+ // set classes in the cfg
+ if (classes != null)
+ {
+ for (Class clazz : classes) cfg.addClass(clazz);
+ }
+
+ SearchFactoryImpl searchImpl = new SearchFactoryImpl(cfg);
+
+ // step 3: create the searchable cache delegate.
+ SearchableCache sc = new SearchableCacheImpl(c, searchImpl);
return sc;
}
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java
===================================================================
---
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java 2008-06-16
14:26:08 UTC (rev 5989)
+++
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -1,6 +1,8 @@
package org.jboss.cache.search;
import org.apache.lucene.search.Query;
+import org.hibernate.search.impl.SearchFactoryImpl;
+import org.hibernate.search.FullTextQuery;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheException;
import org.jboss.cache.CacheStatus;
@@ -23,23 +25,24 @@
{
// this is the ACTUAL cache. that does all the work.
private Cache cache;
- private Class[] classes;
+ private SearchFactoryImpl searchFactory;
//TODO: Javadoc all these methods
- public SearchableCacheImpl(Cache cache)
+ public SearchableCacheImpl(Cache cache, SearchFactoryImpl searchFactory)
{
this.cache = cache;
+ this.searchFactory = searchFactory;
}
- public CacheQuery createQuery(Query luceneQuery)
+ public FullTextQuery createQuery(Query luceneQuery)
{
- return new CacheQueryImpl(luceneQuery, cache);
+ return new CacheQueryImpl(luceneQuery, searchFactory, cache);
}
- public CacheQuery createQuery(Query luceneQuery, Class... classes)
+ public FullTextQuery createQuery(Query luceneQuery, Class... classes)
{
- return new CacheQueryImpl(luceneQuery, cache, classes);
+ return new CacheQueryImpl(luceneQuery, searchFactory, cache, classes);
}
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java
===================================================================
---
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java 2008-06-16
14:26:08 UTC (rev 5989)
+++
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -11,42 +11,46 @@
import java.util.Map;
/**
-@author Navin Surtani - navin(a)surtani.org
+ * @author Navin Surtani - navin(a)surtani.org
*/
@CacheListener
public class SearchableListener
{
-//TODO: Javadoc everything
+ //TODO: Javadoc everything
private SearchFactoryImpl searchFactory;
- private TransactionContext transactionContext;
@NodeModified
public void updateLuceneIndexes(NodeModifiedEvent event)
{
- if (event.getModificationType() ==
NodeModifiedEvent.ModificationType.valueOf("PUT_DATA"))
+ if (!event.isPre())
+ {
+ switch (event.getModificationType())
{
- handlePutData(event);
+ case PUT_MAP:
+ case PUT_DATA:
+ handlePutData(event);
+ break;
+ case REMOVE_DATA:
+ handleDeleteData(event);
+ break;
}
-
- if (event.getModificationType() ==
NodeModifiedEvent.ModificationType.valueOf("DELETE_DATA"))
- {
- handleDeleteData(event);
- }
+ }
}
void handlePutData(NodeModifiedEvent event)
{
Map dataMap = event.getData();
+ TransactionContext ctx = new NodeModifiedTransactionContext(event);
+
for (Object key : dataMap.keySet())
{
String keyString = (String) key;
String docId = Transformer.generateId(event.getFqn(), keyString);
- searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.DELETE), transactionContext);
-
- searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.ADD), transactionContext);
+ searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.DELETE), ctx);
+ searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.ADD), ctx);
}
}
@@ -55,12 +59,14 @@
{
Map dataMap = event.getData();
+ TransactionContext ctx = new NodeModifiedTransactionContext(event);
+
for (Object key : dataMap.keySet())
{
String keyString = (String) key;
String docId = Transformer.generateId(event.getFqn(), keyString);
- searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.DELETE), transactionContext);
+ searchFactory.getWorker().performWork(new Work(dataMap.get(key), docId,
WorkType.DELETE), ctx);
}
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/Transformer.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/Transformer.java 2008-06-16
14:26:08 UTC (rev 5989)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/Transformer.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -46,8 +46,10 @@
return fqn;
}
- public static String generateId(Fqn fqn, String key)
+ public static String generateId(Fqn fqn, String key) throws InvalidFqnException
{
+ if (key == null) throw new InvalidFqnException("Key passed in cannot be
null!");
+
StringBuilder sb = new StringBuilder();
sb.append("Fqn=[");
sb.append(fqn);
Added: searchable/trunk/src/test/java/org/jboss/cache/search/BlackBoxTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/BlackBoxTest.java
(rev 0)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/BlackBoxTest.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -0,0 +1,38 @@
+package org.jboss.cache.search;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.search.test.Person;
+import org.testng.annotations.Test;
+
+/**
+ * @author Navin Surtani - navin(a)surtani.org
+ */
+@Test
+public class BlackBoxTest
+{
+ public void doTest()
+ {
+ Cache cache = new DefaultCacheFactory().createCache();
+ SearchableCache sc = new SearchableCacheFactory().createSearchableCache(cache,
Person.class);
+ Person p1 = new Person();
+ p1.setName("Navin Surtani");
+ p1.setBlurb("Likes playing WoW");
+ sc.put(Fqn.fromString("/a/b/c"), "Navin", p1);
+
+ // try and search for navin
+ // TODO: Create a dummy lucene query
+ //sc.createQuery(new LQ)
+ // TODO: Test should search on name, as well as blurb. Try both cases.
+ // TODO: Also test with stuff in different Fqns.
+ // TODO; test if the indexes get updated. Try changing the values of a Person
object and put it back in the cache.
+
+ // TODO: Test more complex object graphs. Put a person Object which has an address
which has a City class with a name and description about that city. Then try finding
stuff by searching on the city.
+
+ // TODO: test removal of stuff. Remove stuff and see if you can still search for
it. You should not be able to.
+ // TODO: Create more black box tests - use a replicated cache, put stuff in one
instance and perform searches on anotehr instance.
+ // TODO: Test stuff with PojoCache. Put stuff in PojoCache (using cache.attach())
and see if you can find stuff.
+
+ }
+}
Copied: searchable/trunk/src/test/java/org/jboss/cache/search/TransformerTest.java (from
rev 5951, searchable/trunk/src/test/java/TransformerTest.java)
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/TransformerTest.java
(rev 0)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/TransformerTest.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -0,0 +1,98 @@
+package org.jboss.cache.search;
+
+import org.jboss.cache.Fqn;
+import org.testng.annotations.Test;
+
+/**
+@author Navin Surtani - navin(a)surtani.org
+ */
+
+@Test
+public class TransformerTest
+{
+ //TODO: Javadoc everything
+ public void testGenerateId()
+ {
+
+ Fqn fqn = Fqn.fromString("/a/b/c");
+ String key = "key";
+
+ String generatedId = Transformer.generateId(fqn, key);
+
+ assert generatedId.contentEquals("Fqn=[/a/b/c]Key=[key]");
+
+ assert ! generatedId.contentEquals("/ab/c/d");
+ }
+
+ public void testGetFqn()
+ {
+ Fqn fqn = Transformer.getFqn("Fqn=[/cat/dog/person]Key=[key]");
+
+ Fqn expectedFqn = Fqn.fromString("/cat/dog/person");
+
+ assert fqn.equals(expectedFqn);
+
+ expectedFqn = Fqn.fromString("/dog/cat/person");
+
+ assert !fqn.equals(expectedFqn);
+
+ }
+
+ public void testGetKey()
+ {
+ String key = Transformer.getKey("Fqn=[/a/b/c]Key=[thisIsMyKey]");
+
+ assert key.contentEquals("thisIsMyKey");
+
+ assert ! key.contentEquals("thisIsNotMyKey");
+
+ }
+
+ @Test (expectedExceptions = NullPointerException.class)
+ public void testGetKeyWithNull()
+ {
+ Transformer.getKey(null);
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithHackedString()
+ {
+ Transformer.generateId(Fqn.fromString("/Fqn=[/a/b/c"), "x");
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithHackedFqn()
+ {
+ Transformer.generateId(Fqn.fromString("/Fqn=[/a/b/c"), "x");
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithHackedFqn2()
+ {
+ Transformer.generateId(Fqn.fromString("/]Key=[/a/b/c"), "x");
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithHackedKey()
+ {
+ Transformer.generateId(Fqn.fromString("/a/b/c"), "]Key=[");
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithHackedKey2()
+ {
+ Transformer.generateId(Fqn.fromString("/a/b/c"), "Fqn=[");
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithNullKey()
+ {
+ Transformer.generateId(Fqn.fromString("/a/b/c"), null);
+ }
+
+ @Test (expectedExceptions = InvalidFqnException.class)
+ public void testGenerateIdWithNullFqn()
+ {
+ Transformer.generateId(null, "x");
+ }
+}
Added: searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java
(rev 0)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java 2008-06-16
16:58:35 UTC (rev 5990)
@@ -0,0 +1,36 @@
+package org.jboss.cache.search.test;
+
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Indexed;
+
+/**
+ * @author Navin Surtani - navin(a)surtani.org
+ */
+@Indexed
+public class Person
+{
+ @Field
+ private String name;
+ @Field
+ private String blurb;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getBlurb()
+ {
+ return blurb;
+ }
+
+ public void setBlurb(String blurb)
+ {
+ this.blurb = blurb;
+ }
+}