package er.neo4jadaptor.storage.lucene; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.index.Index; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eocontrol.EOQualifier; import er.neo4jadaptor.ersatz.Ersatz; import er.neo4jadaptor.ersatz.lucene.LuceneErsatz; import er.neo4jadaptor.ersatz.neo4j.Neo4JErsatz; import er.neo4jadaptor.query.Filter; import er.neo4jadaptor.query.LayeringFilter; import er.neo4jadaptor.query.Results; import er.neo4jadaptor.storage.IndexProvider; import er.neo4jadaptor.storage.Store; import er.neo4jadaptor.utils.cursor.Cursor; /** * Store that maintains record representation in Lucene documents. Each EO attribute is stored as a separate * document field, plus there an extra property {@value #TYPE_PROPERTY_NAME} added for storing entity name. * * @author Jedrzej Sobanski * * @param <Type> */ public class LuceneStore <Type extends PropertyContainer> implements Store<Neo4JErsatz, Neo4JErsatz> { private static final Logger log = LoggerFactory.getLogger(LuceneStore.class); public static final String TYPE_PROPERTY_NAME = "#_type"; private final Index<Type> index; private final GraphDatabaseService db; private final EOEntity entity; private final Filter<Type> facetCreator; @SuppressWarnings("unchecked") public LuceneStore(GraphDatabaseService db, EOEntity entity) { this.index = (Index<Type>) IndexProvider.instance.getIndexForEntity(db, entity); this.db = db; this.entity = entity; this.facetCreator = new LayeringFilter<>(); } // this method is not defined in Store interface as lucene objects can't exist // independent in Lucene for Neo4J (there must exist corresponding Node/Relationship). // Implementing Store would make this method accept Ersatz, which would cause a need // for a class cast, but this way we have our own method with very specific signature @SuppressWarnings("unchecked") public Neo4JErsatz insert(Neo4JErsatz row) { Type container = (Type) row.getPropertyContainer(); LuceneErsatz<Type> lucene = LuceneErsatz.createForInsert(entity, container, index); Ersatz.copy(row, lucene); return row; } @SuppressWarnings("unchecked") public void update(Ersatz newValues, Neo4JErsatz neoErsatz) { Type container = (Type) neoErsatz.getPropertyContainer(); LuceneErsatz<Type> lucene = LuceneErsatz.createForUpdate(entity, container, index); Ersatz.copy(newValues, lucene); } @SuppressWarnings("unchecked") public void delete(Neo4JErsatz neoErsatz) { Type container = (Type) neoErsatz.getPropertyContainer(); LuceneErsatz<Type> lucene = LuceneErsatz.createForUpdate(entity, container, index); lucene.delete(); } public Cursor<Neo4JErsatz> query(EOQualifier q) { Results<Type> result = facetCreator.doFilter(db, entity, q); log.debug("Fetching {} where {}.", entity.name(), q); return new LinkingCursor(result, entity); } public Ersatz newPrimaryKey() { throw new UnsupportedOperationException(); } }