package ch.x42.terye; import java.io.IOException; import java.math.BigDecimal; import java.util.Calendar; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.x42.terye.persistence.ChangeLog; import ch.x42.terye.persistence.ChangeLog.AddOperation; import ch.x42.terye.persistence.ChangeLog.ModifyOperation; import ch.x42.terye.persistence.ChangeLog.Operation; import ch.x42.terye.persistence.ChangeLog.RemoveOperation; import ch.x42.terye.value.ValueImpl; public class Index { public static final String SOLR_URL = "http://localhost:1234/solr/"; public static final String ID_FIELD = "id"; private Logger logger = LoggerFactory.getLogger(this.getClass()); private static SolrServer server; protected Index() { server = new HttpSolrServer(Index.SOLR_URL); } public void update(ChangeLog log) throws RepositoryException { Iterator<Operation> iterator = log.iterator(); try { while (iterator.hasNext()) { Operation op = iterator.next(); if (op instanceof AddOperation || op instanceof ModifyOperation) { addOrUpdate(op.getItem()); } else if (op instanceof RemoveOperation) { remove(op.getItem()); } } server.commit(); } catch (Exception e) { throw new RepositoryException("Could not update index", e); } } private void addOrUpdate(Item item) throws RepositoryException, SolrServerException, IOException { // only add nodes to index: // since creating a property modifies its parent node, we are // sure that we don't forget to index properties if (!item.isNode()) { return; } Node node = (Node) item; SolrInputDocument doc = new SolrInputDocument(); doc.addField(Index.ID_FIELD, node.getPath()); PropertyIterator iterator = node.getProperties(); while (iterator.hasNext()) { Property property = iterator.nextProperty(); String name = property.getName() + "_" + PropertyType.nameFromValue(property.getType()); Object value = ((ValueImpl) property.getValue()).getObject(); // XXX: Solr cannot handle BigDecimal if (value instanceof BigDecimal) { // store big decimals as their string representation value = value.toString(); } else if (value instanceof Calendar) { value = ((Calendar) value).getTime(); } doc.addField(name, value); } server.add(doc); } private void remove(Item item) throws SolrServerException, IOException, RepositoryException { // index docs correspond to nodes, so we skip properties here: // if a property is removed, then its parent node is modified, // which is handled in addOrUpdate if (!item.isNode()) { return; } server.deleteById(item.getPath()); } public List<String> query(String statement) throws RepositoryException { List<String> nodes = new LinkedList<String>(); SolrQuery query = new SolrQuery(statement); SolrDocumentList results; try { logger.debug("Solr query: " + statement); results = server.query(query).getResults(); } catch (SolrServerException e) { throw new RepositoryException("Query execution failed: " + statement, e); } Iterator<SolrDocument> iterator = results.iterator(); while (iterator.hasNext()) { nodes.add((String) iterator.next().get(Index.ID_FIELD)); } return nodes; } }