Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2007 Daniel Spiewak
   * 
   * Licensed under the Apache License, Version 2.0 (the "License"); 
   * you may not use this file except in compliance with the License. 
   * You may obtain a copy of the License at
   * 
   *	    http://www.apache.org/licenses/LICENSE-2.0 
   * 
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package net.java.ao;
 
 import java.util.List;
 
 
 import  org.apache.lucene.analysis.Analyzer;
 import  org.apache.lucene.analysis.StopAnalyzer;
 import  org.apache.lucene.document.Document;
 import  org.apache.lucene.document.Field;
 import  org.apache.lucene.index.CorruptIndexException;
 import  org.apache.lucene.index.IndexReader;
 import  org.apache.lucene.index.IndexWriter;
 import  org.apache.lucene.index.Term;
 import  org.apache.lucene.queryParser.MultiFieldQueryParser;
 import  org.apache.lucene.queryParser.ParseException;
 import  org.apache.lucene.queryParser.QueryParser;
 import  org.apache.lucene.search.Hits;
 import  org.apache.lucene.search.IndexSearcher;
 import  org.apache.lucene.store.Directory;
 
 import static com.google.common.base.Preconditions.checkNotNull;

Required to manage entities with enabled full-text searching. This is where all the "meat" of the Lucene indexing support is actually implemented. It is required to use this EntityManager implementation to use full-text searching. Example:

public interface Post extends Entity {
     // ...

     @Searchable
     @SQLType(Types.BLOB)
     public String getBody();

     @Searchable
     @SQLType(Types.BLOB)
     public void setBody(String body);
 }

 // ...
 SearchableEntityManager manager = new SearchableEntityManager(
         uri, username, password, FSDirectory.getDirectory("~/lucene_index"));
 manager.search(Post.class, "my search string");       // returns results as Post[]

This class does not support any Java full-text search libraries other than Lucene. Also, the support for Lucene itself is comparatively limited. If your requirements dictate more advanced functionality, you should consider writing a custom implementation of this class to provide the enhancements you need. More features are planned for this class in future...

Author(s):
Daniel Spiewak
See also:
net.java.ao.Searchable
 
 public class SearchableEntityManager extends EntityManager {
 
     private final Directory indexDir;
 
 	private final Analyzer analyzer;
 
     public SearchableEntityManager(DatabaseProvider databaseProviderEntityManagerConfiguration configurationLuceneConfiguration luceneConfigurationthrows IOException
     {
         super(databaseProviderconfiguration);
         this. = checkNotNull(checkNotNull(luceneConfiguration).getIndexDirectory());
         this. = new StopAnalyzer();
         init();
     }
 
     @Override
 	protected <T extends RawEntity<K>, K> T getAndInstantiate(EntityInfo<T, K> entityInfo, K key) {
 		T back = super.getAndInstantiate(entityInfokey);
 		back.addPropertyChangeListener(new IndexAppender<T, K>(back));
 
 		return back;
 	}

Runs a Lucene full-text search on the specified entity type with the given query. The search will be run on every Searchable field within the entity. No caching is performed in this method. Rather, AO relies upon the underlying Lucene code to be performant.

Parameters:
type The type of the entities to search for.
strQuery The query to pass to Lucene for the search.
Returns:
The entity instances which correspond with the search results.
Throws:
IOException If Lucene was unable to open the index.
ParseException If Lucene was unable to parse the search string into a valid query.
	@SuppressWarnings("unchecked")
	public <T extends RawEntity<K>, K> T[] search(Class<T> typeString strQuerythrows IOException, ParseException, SQLException
    {
        EntityInfo<T, K> entityInfo = resolveEntityInfo(type);
		List<StringindexFields = Common.getSearchableFields(thistype);
		String[] searchFields = new String[indexFields.size()];
		String primaryKeyField = Common.getPrimaryKeyField(typegetFieldNameConverter());
		TypeInfo dbType = entityInfo.getPrimaryKey().getTypeInfo();
		for (int i = 0; i < searchFields.lengthi++) {
			searchFields[i] = table + '.' + indexFields.get(i);
		}
		IndexSearcher searcher = new IndexSearcher();
		QueryParser parser = new MultiFieldQueryParser(searchFields);
		org.apache.lucene.search.Query query = parser.parse(strQuery);
		Hits hits = searcher.search(query);
		K[] keys = (K[]) new Object[hits.length()];
		for (int i = 0; i < hits.length(); i++) {
			keys[i] = (K) dbType.getLogicalType().parseDefault(hits.doc(i).get(table + "." + primaryKeyField));
		}
		searcher.close();
		return peer(entityInfokeys);
	}
	public void delete(RawEntity<?>... entitiesthrows SQLException {
		super.delete(entities);
		IndexReader reader = null;
		try {
			reader = IndexReader.open();
			for (RawEntity<?> entity : entities) {
				removeFromIndexImpl(entityreader);
			}
catch (IOException e) {
			throw (SQLExceptionnew SQLException().initCause(e);
finally {
			if (reader != null) {
				try {
					reader.close();
catch (IOException e) {
				}
			}
		}
	}

Adds the entity instance to the index. No checking is performed to ensure that the entity is not already part of the index. All of the Searchable fields within the entity will be added to the index as part of the document corresponding to the instance.

Parameters:
entity The entity to add to the index.
Throws:
IOException If Lucene was unable to open the index.
	@SuppressWarnings("unchecked")
    public void addToIndex(RawEntity<?> entitythrows IOException {
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(false);
			Document doc = new Document();
			doc.add(new Field(getTableNameConverter().getName(entity.getEntityType()) + "."
					Field.Store.YES, Field.Index.UN_TOKENIZED));
			boolean shouldAdd = false;
			for (Method m : entity.getEntityType().getMethods()) {
				if (indexAnno != null) {
					shouldAdd = true;
					if (Common.isAccessor(m)) {
						Object value = m.invoke(entity);
						if (value != null) {
							doc.add(new Field(table + '.' + attributevalue.toString(), Field.Store.YES, Field.Index.TOKENIZED));
						}
					}
				}
			}
			if (shouldAdd) {
				writer.addDocument(doc);
			}
catch (IllegalArgumentException e) {
			throw (IOExceptionnew IOException().initCause(e);
catch (IllegalAccessException e) {
			throw (IOExceptionnew IOException().initCause(e);
catch (InvocationTargetException e) {
			throw (IOExceptionnew IOException().initCause(e);
finally {
			if (writer != null) {
				writer.close();
			}
		}
	}

Removes the specified entity from the Lucene index. This performs a lookup in the index based on the value of the entity primary key and removes the appropriate Document.

Parameters:
entity The entity to remove from the index.
Throws:
IOException If Lucene was unable to open the index.
	public void removeFromIndex(RawEntity<?> entitythrows IOException {
		IndexReader reader = null;
		try {
			reader = IndexReader.open();
			removeFromIndexImpl(entityreader);
finally {
			if (reader != null) {
				reader.close();
			}
		}
	}
	private void removeFromIndexImpl(RawEntity<?> entity, IndexReader readerthrows IOException {
		reader.deleteDocuments(new Term(getTableNameConverter().getName(entity.getEntityType()) + "."
	}

Optimizes the Lucene index for searching. This call peers down to IndexWriter#optimize(). For sizable indexes, this call will take some time, so it is best not to perform the operation in scenarios where it may block interface responsiveness (such as in the middle of a page request, or within the EDT).

This method is the only optimization call made against the Lucene index. Meaning, SearchableEntityManager never optimizes the index automatically, as this could potentially cause major performance issues. Developers should be aware of this and the negative impact lack-of optimization can have upon search performance.

Throws:
IOException If Lucene was unable to open the index.
	public void optimize() throws IOException {
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(false);
			writer.optimize();
finally {
			if (writer != null) {
				writer.close();
			}
		}
	}
	public Directory getIndexDir() {
		return ;
	}
	public Analyzer getAnalyzer() {
		return ;
	}
    private void init() throws IOException
    {
        if (!IndexReader.indexExists())
        {
            new IndexWriter(true).close();
        }
    }
	private class IndexAppender<T extends RawEntity<K>, K> implements PropertyChangeListener {
		private Document doc;
		private IndexAppender(T entity) {
			 = new Document();
            .add(new Field(getTableNameConverter().getName(entity.getEntityType()) + "."
					Field.Store.YES, Field.Index.UN_TOKENIZED));
		}
		public void propertyChange(final PropertyChangeEvent evt) {
entity = (T) evt.getSource();
				.add(new Field(getTableNameConverter().getName(entity.getEntityType()) + '.'
evt.getPropertyName(), evt.getNewValue().toString(), Field.Store.YES, Field.Index.TOKENIZED));
				IndexWriter writer = null;
				try {
					writer = new IndexWriter(getIndexDir(), getAnalyzer(), false);
					writer.updateDocument(new Term(getTableNameConverter().getName(entity.getEntityType()) + "."
catch (IOException e) {
finally {
					if (writer != null) {
						try {
							writer.close();
catch (CorruptIndexException e) {
							e.printStackTrace();
catch (IOException e) {
						}
					}
				}
			}
		}
	}
	@SuppressWarnings("unchecked")
    private final String primaryKeyToString(RawEntity<?> entity)
	{
	    TypeInfo pkType = Common.getPrimaryKeyType(getProvider().getTypeManager(), entity.getEntityType());
	    return pkType.getLogicalType().valueToString(Common.getPrimaryKeyValue(entity));
	}
New to GrepCode? Check out our FAQ X