Java tutorial
/* * Copyright 2010 Impetus Infotech. * * 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 com.impetus.kundera.index; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import lucandra.IndexReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.LockObtainFailedException; import org.apache.lucene.util.Version; import com.impetus.kundera.CassandraClient; import com.impetus.kundera.Client; import com.impetus.kundera.Constants; import com.impetus.kundera.db.accessor.ColumnFamilyDataAccessor; import com.impetus.kundera.loader.DBType; import com.impetus.kundera.metadata.EntityMetadata; import com.impetus.kundera.metadata.EntityMetadata.PropertyIndex; import com.impetus.kundera.property.PropertyAccessException; import com.impetus.kundera.property.PropertyAccessorHelper; /** * The Class LucandraIndexer. * * @author animesh.kumar */ public class LucandraIndexer implements Indexer { /** log for this class. */ private static Log log = LogFactory.getLog(ColumnFamilyDataAccessor.class); /** The INDEX_NAME. */ private static String INDEX_NAME = "kundera-alpha";// is // persistent-unit-name /** The Constant UUID. */ private static final long UUID = 6077004083174677888L; /** The Constant DELIMETER. */ private static final String DELIMETER = "~"; /** The Constant ENTITY_ID_FIELD. */ public static final String ENTITY_ID_FIELD = UUID + ".entity.id"; /** The Constant KUNDERA_ID_FIELD. */ public static final String KUNDERA_ID_FIELD = UUID + ".kundera.id"; /** The Constant ENTITY_INDEXNAME_FIELD. */ public static final String ENTITY_INDEXNAME_FIELD = UUID + ".entity.indexname"; /** The Constant ENTITY_CLASS_FIELD. */ public static final String ENTITY_CLASS_FIELD = /*UUID +*/ "entity.class"; /** The Constant DEFAULT_SEARCHABLE_FIELD. */ private static final String DEFAULT_SEARCHABLE_FIELD = UUID + ".default_property"; /** The client. */ private Client client; /** The analyzer. */ private Analyzer analyzer; /** * Instantiates a new lucandra indexer. * * @param client * the client * @param analyzer * the analyzer */ public LucandraIndexer(Client client, Analyzer analyzer) { this.client = client; this.analyzer = analyzer; } /* * @see * com.impetus.kundera.index.Indexer#unindex(com.impetus.kundera.metadata * .EntityMetadata, java.lang.String) */ @Override public final void unindex(EntityMetadata metadata, String id) { log.debug("Unindexing @Entity[" + metadata.getEntityClazz().getName() + "] for key:" + id); try { getIndexWriter().deleteDocuments(new Term(KUNDERA_ID_FIELD, getKunderaId(metadata, id))); } catch (CorruptIndexException e) { throw new IndexingException(e.getMessage()); } catch (IOException e) { throw new IndexingException(e.getMessage()); } } /* * @see * com.impetus.kundera.index.Indexer#index(com.impetus.kundera.metadata. * EntityMetadata, java.lang.Object) */ @Override public final void index(EntityMetadata metadata, Object object) { if (!metadata.isIndexable()) { return; } log.debug("Indexing @Entity[" + metadata.getEntityClazz().getName() + "] " + object); String indexName = metadata.getIndexName(); Document document = new Document(); Field luceneField; // index row try { String id = PropertyAccessorHelper.getId(object, metadata); luceneField = new Field(ENTITY_ID_FIELD, id, // adding class // namespace Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); document.add(luceneField); // index namespace for unique deletion luceneField = new Field(KUNDERA_ID_FIELD, getKunderaId(metadata, id), // adding // class // namespace Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); document.add(luceneField); // index entity class luceneField = new Field(ENTITY_CLASS_FIELD, metadata.getEntityClazz().getCanonicalName().toLowerCase(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); document.add(luceneField); // index index name luceneField = new Field(ENTITY_INDEXNAME_FIELD, metadata.getIndexName(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); document.add(luceneField); } catch (PropertyAccessException e) { throw new IllegalArgumentException("Id could not be read."); } // now index all indexable properties for (PropertyIndex index : metadata.getIndexProperties()) { java.lang.reflect.Field property = index.getProperty(); String propertyName = index.getName(); try { String value = PropertyAccessorHelper.getString(object, property).toString(); luceneField = new Field(getCannonicalPropertyName(indexName, propertyName), value, Field.Store.NO, Field.Index.ANALYZED); document.add(luceneField); } catch (PropertyAccessException e) { // TODO: do something with the exceptions // e.printStackTrace(); } } // flush the indexes try { log.debug("Flushing to Lucandra: " + document); if (!metadata.getDBType().equals(DBType.CASSANDRA)) { IndexWriter w = getDefaultIndexWriter(); w.addDocument(document, analyzer); w.optimize(); w.commit(); w.close(); } else { getIndexWriter().addDocument(document, analyzer); } } catch (CorruptIndexException e) { throw new IndexingException(e.getMessage()); } catch (IOException e) { throw new IndexingException(e.getMessage()); } } // TODO: this is not the best implementation. need to improve! /* @see com.impetus.kundera.index.Indexer#search(java.lang.String, int, int) */ @SuppressWarnings("deprecation") @Override public final List<String> search(String luceneQuery, int start, int count) { if (Constants.INVALID == count) { count = 100; } log.debug("Searhcing index with query[" + luceneQuery + "], start:" + start + ", count:" + count); Set<String> entityIds = new HashSet<String>(); org.apache.lucene.index.IndexReader indexReader = null; try { if (client.getType().equals(DBType.CASSANDRA)) { indexReader = new IndexReader(INDEX_NAME, ((CassandraClient) client).getCassandraClient()); } else { indexReader = getDefaultReader(); } } catch (Exception e) { throw new IndexingException(e.getMessage()); } IndexSearcher searcher = new IndexSearcher(indexReader); QueryParser qp = new QueryParser(Version.LUCENE_CURRENT, DEFAULT_SEARCHABLE_FIELD, analyzer); try { Query q = qp.parse(luceneQuery); TopDocs docs = searcher.search(q, count); for (ScoreDoc sc : docs.scoreDocs) { Document doc = searcher.doc(sc.doc); entityIds.add(doc.get(ENTITY_ID_FIELD)); } } catch (ParseException e) { new IndexingException(e.getMessage()); } catch (IOException e) { new IndexingException(e.getMessage()); } log.debug("Result[" + entityIds + "]"); return new ArrayList<String>(entityIds); } /** * Gets the kundera id. * * @param metadata * the metadata * @param id * the id * * @return the kundera id */ private String getKunderaId(EntityMetadata metadata, String id) { return metadata.getEntityClazz().getCanonicalName() + DELIMETER + id; } /** * Gets the cannonical property name. * * @param indexName * the index name * @param propertyName * the property name * * @return the cannonical property name */ private String getCannonicalPropertyName(String indexName, String propertyName) { return indexName + "." + propertyName; } // helper method to get Lucandra IndexWriter object /** * Gets the index writer. * * @return the index writer */ private lucandra.IndexWriter getIndexWriter() { try { return new lucandra.IndexWriter(INDEX_NAME, ((CassandraClient) client).getCassandraClient()); } catch (Exception e) { throw new IndexingException(e.getMessage()); } } /** * Added for HBase support. * @return default index writer */ private IndexWriter getDefaultIndexWriter() { StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT); Directory index = null; IndexWriter w = null; try { index = FSDirectory.open(getIndexDirectory()); if (index.listAll().length == 0) { log.info("Creating fresh Index because it was empty"); w = new IndexWriter(index, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); } else { w = new IndexWriter(index, analyzer, false, IndexWriter.MaxFieldLength.LIMITED); } } catch (CorruptIndexException e) { throw new IndexingException(e.getMessage()); } catch (LockObtainFailedException e) { throw new IndexingException(e.getMessage()); } catch (IOException e) { throw new IndexingException(e.getMessage()); } return w; } /** * Returns default index reader. * @return index reader. */ private org.apache.lucene.index.IndexReader getDefaultReader() { org.apache.lucene.index.IndexReader reader = null; try { reader = IndexReader.open(FSDirectory.open(getIndexDirectory())); } catch (CorruptIndexException e) { throw new IndexingException(e.getMessage()); } catch (IOException e) { throw new IndexingException(e.getMessage()); } return reader; } /** * Creates a directory if it does not exist. * @return */ private File getIndexDirectory() { String filePath = System.getProperty("user.home") + "/lucene"; File file = new File(filePath); if (!file.isDirectory()) { file.mkdir(); } return file; } }