org.kimios.kernel.index.SolrIndexManager.java Source code

Java tutorial

Introduction

Here is the source code for org.kimios.kernel.index.SolrIndexManager.java

Source

/*
 * Kimios - Document Management System Software
 * Copyright (C) 2012-2013  DevLib'
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kimios.kernel.index;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.Vector;

import org.apache.lucene.search.Query;
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.response.QueryResponse;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.kimios.exceptions.ConfigException;
import org.kimios.kernel.controller.IPathController;
import org.kimios.kernel.dms.DMEntity;
import org.kimios.kernel.dms.Document;
import org.kimios.kernel.dms.DocumentVersion;
import org.kimios.kernel.dms.DocumentWorkflowStatus;
import org.kimios.kernel.dms.DocumentWorkflowStatusRequest;
import org.kimios.kernel.dms.FactoryInstantiator;
import org.kimios.kernel.dms.Lock;
import org.kimios.kernel.dms.MetaType;
import org.kimios.kernel.dms.MetaValue;
import org.kimios.kernel.dms.WorkflowStatus;
import org.kimios.kernel.exception.DataSourceException;
import org.kimios.kernel.exception.IndexException;
import org.kimios.kernel.index.query.factory.DocumentFactory;
import org.kimios.kernel.index.query.model.SearchResponse;
import org.kimios.kernel.security.DMEntityACL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SolrIndexManager implements ISolrIndexManager {
    private static Logger log = LoggerFactory.getLogger(SolrIndexManager.class);

    private Reindexer reindexer = null;

    private Thread reindexThread = null;

    private IPathController pathController;

    private org.kimios.kernel.index.query.factory.DocumentFactory solrDocumentFactory;

    public DocumentFactory getSolrDocumentFactory() {
        return solrDocumentFactory;
    }

    public void setSolrDocumentFactory(DocumentFactory solrDocumentFactory) {
        this.solrDocumentFactory = solrDocumentFactory;
    }

    public SolrIndexManager(SolrServer solr) {
        this.solr = solr;
    }

    private final SolrServer solr;

    public synchronized void reindex(String path) throws DataSourceException, ConfigException, IndexException {
        final String finalPath = path;
        if (this.reindexThread == null || !this.reindexThread.isAlive()) {

            this.reindexer = new Reindexer(this, pathController, finalPath);
            this.reindexThread = new Thread(this.reindexer);
            this.reindexThread.setName("ReindexThread");
            this.reindexThread.start();
        } else {
            throw new IndexException(null, "A reindex process is already running.");
        }
    }

    public int getReindexProgression() {
        if (this.reindexThread != null && this.reindexer != null) {
            return this.reindexer.getReindexProgression();
        } else {
            return -1;
        }
    }

    public boolean deleteDirectory(File path) {
        if (path.exists()) {
            File[] files = path.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    deleteDirectory(files[i]);
                } else {
                    files[i].delete();
                }
            }
        }
        return (path.delete());
    }

    public void deleteDocument(Document document) throws IndexException {
        try {
            this.solr.deleteById(String.valueOf(document.getUid()));
            log.debug("Commited deletion of document " + document.getUid());
            this.solr.commit();
        } catch (IOException e) {
            throw new IndexException(e,
                    "An exception occured while deleting document " + document.getUid() + " : " + e.getMessage());
        } catch (SolrServerException e) {
            throw new IndexException(e,
                    "An exception occured while deleting document " + document.getUid() + " : " + e.getMessage());
        }
    }

    private SolrInputDocument toSolrInputDocument(Document document) throws DataSourceException, ConfigException {
        SolrInputDocument doc = new SolrInputDocument();
        doc.addField("DocumentUid", document.getUid());
        doc.addField("DocumentName", document.getName().toLowerCase());
        doc.addField("DocumentNameDisplayed", document.getName());
        doc.addField("DocumentNameAnalysed", document.getName());
        if (document.getExtension() != null) {
            doc.addField("DocumentExtension", document.getExtension().toLowerCase());
        }
        doc.addField("DocumentOwner", document.getOwner() + "@" + document.getOwnerSource());
        doc.addField("DocumentOwnerId", document.getOwner());
        doc.addField("DocumentOwnerSource", document.getOwnerSource());
        doc.addField("DocumentPath", document.getPath());
        doc.addField("DocumentParent", document.getFolder().getPath() + "/");
        doc.addField("DocumentParentId", document.getFolder().getUid());
        DocumentVersion version = FactoryInstantiator.getInstance().getDocumentVersionFactory()
                .getLastDocumentVersion(document);

        if (version == null) {
            log.error("Document {} has no version", document.getUid());
            return null;
        }
        //standard datas
        doc.addField("DocumentCreationDate", document.getCreationDate());
        doc.addField("DocumentUpdateDate", document.getUpdateDate());
        doc.addField("DocumentVersionCreationDate", version.getCreationDate());
        doc.addField("DocumentVersionUpdateDate", version.getModificationDate());
        doc.addField("DocumentVersionOwner", version.getAuthor() + "@" + version.getAuthorSource());
        doc.addField("DocumentVersionOwnerId", version.getAuthor());
        doc.addField("DocumentVersionOwnerSource", version.getAuthorSource());
        doc.addField("DocumentVersionLength", version.getLength());
        doc.addField("DocumentVersionHash", version.getHashMD5() + ":" + version.getHashSHA1());

        Lock lock = document.getCheckoutLock();

        doc.addField("DocumentCheckout", lock != null);

        if (lock != null) {
            doc.addField("DocumentCheckoutOwnerId", lock.getUser());
            doc.addField("DocumentCheckoutOwnerSource", lock.getUserSource());
            doc.addField("DocumentCheckoutDate", lock.getDate());
        }
        // DocumentOutWorkflow

        DocumentWorkflowStatusRequest req = FactoryInstantiator.getInstance()
                .getDocumentWorkflowStatusRequestFactory().getLastPendingRequest(document);
        DocumentWorkflowStatus st = FactoryInstantiator.getInstance().getDocumentWorkflowStatusFactory()
                .getLastDocumentWorkflowStatus(document.getUid());
        boolean outOfWorkflow = true;
        if (req != null) {
            outOfWorkflow = false;
        }
        if (st != null) {

            WorkflowStatus stOrg = FactoryInstantiator.getInstance().getWorkflowStatusFactory()
                    .getWorkflowStatus(st.getWorkflowStatusUid());
            doc.addField("DocumentWorkflowStatusName", stOrg.getName());
            doc.addField("DocumentWorkflowStatusUid", st.getWorkflowStatusUid());
            if (stOrg.getSuccessorUid() == null) {
                outOfWorkflow = true;
            }
        }
        doc.addField("DocumentOutWorkflow", outOfWorkflow);
        if (version.getDocumentType() != null) {
            log.info("Document Type Found for version");
            doc.addField("DocumentTypeUid", version.getDocumentType().getUid());
            doc.addField("DocumentTypeName", version.getDocumentType().getName());
            List<MetaValue> values = FactoryInstantiator.getInstance().getMetaValueFactory().getMetaValues(version);
            log.info("Meta Values Found for version " + values.size() + " / " + values);
            for (MetaValue value : values) {
                switch (value.getMeta().getMetaType()) {
                case MetaType.STRING:
                    doc.addField("MetaDataString_" + value.getMetaUid(), ((String) value.getValue()).toLowerCase());
                    break;
                case MetaType.BOOLEAN:
                    doc.addField("MetaDataBoolean_" + value.getMetaUid(), value.getValue());
                    break;
                case MetaType.NUMBER:
                    doc.addField("MetaDataNumber_" + value.getMetaUid(), value.getValue());
                    break;
                case MetaType.DATE:

                    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
                    cal.setTime((Date) value.getValue());
                    doc.addField("MetaDataDate_" + value.getMetaUid(), cal.getTime());

                    log.info("Inserting date in solr: " + value.getValue() + " / " + cal.getTime() + " / " + cal);
                    break;
                default:
                    doc.addField("MetaData_" + value.getMetaUid(), value.getValue());
                    break;
                }
            }
        }
        for (String attribute : document.getAttributes().keySet()) {
            doc.addField("Attribute_" + attribute.toUpperCase(),
                    document.getAttributes().get(attribute).getValue());
        }
        Object body = null;
        try {
            IndexFilter filter = FiltersMapper.getInstance().getFiltersFor(document.getExtension());
            log.debug(document.getExtension() + " --> "
                    + (filter != null ? filter.getClass().getName() : "No filter"));
            if (filter != null) {
                body = filter.getBody(version.getInputStream());
                log.debug((String) body);
            }
        } catch (Throwable ex) {
            log.debug("Error while getting body", ex);
        }
        if (body == null) {
            body = IndexHelper.EMPTY_STRING;
        }
        if (body instanceof String) {
            doc.addField("DocumentBody", (String) body);
        }

        List<DMEntityACL> acls = org.kimios.kernel.security.FactoryInstantiator.getInstance()
                .getDMEntitySecurityFactory().getDMEntityACL(document);

        for (int i = 0; i < acls.size(); i++) {
            doc.addField("DocumentACL", acls.get(i).getRuleHash());
        }

        return doc;
    }

    public void indexDocument(DMEntity documentEntity) throws IndexException, DataSourceException, ConfigException {
        try {

            Document document = (Document) documentEntity;
            this.deleteDocument(document);
            SolrInputDocument solrInputDocument = toSolrInputDocument(document);
            this.solr.add(solrInputDocument);
            this.solr.commit();
        } catch (IOException io) {
            throw new IndexException(io, "An exception occured while indexing document " + documentEntity.getUid()
                    + " : " + io.getMessage());
        } catch (SolrServerException ex) {
            throw new IndexException(ex, "An exception occured while indexing document " + documentEntity.getUid()
                    + " : " + ex.getMessage());
        }
    }

    public void indexDocumentList(List<DMEntity> documentEntities)
            throws IndexException, DataSourceException, ConfigException {
        try {
            List<SolrInputDocument> updatedDocument = new ArrayList<SolrInputDocument>();
            List<String> updatedDocumentIds = new ArrayList<String>();
            for (DMEntity doc : documentEntities) {
                SolrInputDocument solrInputDocument = toSolrInputDocument((Document) doc);
                if (solrInputDocument != null) {
                    updatedDocumentIds.add(String.valueOf(doc.getUid()));
                    updatedDocument.add(solrInputDocument);
                    log.info("Doc added to solr Query " + doc + " / " + solrInputDocument);
                }
            }

            this.solr.deleteById(updatedDocumentIds);
            this.solr.add(updatedDocument);
            this.solr.commit();
        } catch (IOException io) {
            throw new IndexException(io, "An exception occured while indexing document list " + io.getMessage());
        } catch (SolrServerException ex) {
            throw new IndexException(ex, "An exception occured while indexing document " + ex.getMessage());
        }
    }

    public List<? extends Number> executeQuery(Query query) throws IndexException {
        QueryResponse rsp;
        try {
            rsp = solr.query(new SolrQuery(query.toString()));
            final List<Long> list = new Vector<Long>();
            SolrDocumentList documentList = rsp.getResults();
            for (SolrDocument dc : documentList) {
                list.add((Long) dc.getFieldValue("DocumentUid"));
            }
            return list;
        } catch (SolrServerException ex) {
            throw new IndexException(ex, ex.getMessage());
        }
    }

    public SearchResponse executeSolrQuery(SolrQuery query) throws IndexException {
        QueryResponse rsp;
        try {
            rsp = solr.query(query);
            final List<Long> list = new Vector<Long>();
            SolrDocumentList documentList = rsp.getResults();
            for (SolrDocument dc : documentList) {

                log.debug("Solr result doc: " + dc);

                list.add((Long) dc.getFieldValue("DocumentUid"));
            }
            SearchResponse searchResponse = new SearchResponse(list);
            searchResponse.setResults(new Long(documentList.getNumFound()).intValue());
            searchResponse.setRows(solrDocumentFactory.getPojosFromSolrInputDocument(rsp.getResults()));
            return searchResponse;
        } catch (SolrServerException ex) {
            throw new IndexException(ex, ex.getMessage());
        }
    }

    public void updateAcls(long docUid, List<DMEntityACL> acls) throws IndexException {
        try {
            log.trace("Updating ACL for document #" + docUid);
            QueryResponse rsp = this.solr.query(new SolrQuery("DocumentUid:" + docUid));
            if (rsp.getResults().getNumFound() > 0) {
                SolrDocument doc = rsp.getResults().get(0);
                this.solr.deleteById(String.valueOf(docUid));
                doc.removeFields("DocumentACL");
                SolrInputDocument docUpdate = ClientUtils.toSolrInputDocument(doc);
                for (int j = 0; j < acls.size(); j++) {
                    docUpdate.addField("DocumentACL", acls.get(j).getRuleHash());
                }
                this.solr.add(docUpdate);
            }
        } catch (Exception e) {
            throw new IndexException(e, e.getMessage());
        } finally {
            try {
                this.solr.commit();
            } catch (Exception e) {
                throw new IndexException(e, e.getMessage());
            }
        }
    }

    public void deletePath(String path) throws IndexException {
        try {

            log.debug("Path delete: " + path);
            if (path.endsWith("/")) {
                path = path.substring(0, path.lastIndexOf("/"));
            }
            Query q = new DocumentParentClause(path).getLuceneQuery();
            this.solr.deleteByQuery("DocumentParent:" + path + "/*");
            this.solr.commit();
        } catch (Exception ex) {
            throw new IndexException(ex, ex.getMessage());
        }
    }

    public void deleteByQuery(String query) throws IndexException {
        try {
            this.solr.deleteByQuery(query);
            this.solr.commit();
        } catch (Exception ex) {
            throw new IndexException(ex, ex.getMessage());
        }
    }

    public void updatePath(String oldPath, String newPath) throws IndexException {
        try {
            if (oldPath.endsWith("/")) {
                oldPath = oldPath.substring(0, oldPath.lastIndexOf("/"));
            }
            if (!newPath.endsWith("/")) {
                newPath += "/";
            }
            Query q = new DocumentParentClause(oldPath).getLuceneQuery();
            SolrDocumentList items = this.solr.query(new SolrQuery(q.toString())).getResults();

            if (items.getNumFound() > 0) {
                List<SolrInputDocument> documentList = new ArrayList<SolrInputDocument>();
                this.solr.deleteByQuery(q.toString());
                for (SolrDocument doc : items) {
                    String path = doc.getFieldValue("DocumentParent").toString();
                    path = newPath + path.substring(oldPath.length() + 1);
                    doc.removeFields("DocumentParent");
                    SolrInputDocument updatedDocument = ClientUtils.toSolrInputDocument(doc);
                    updatedDocument.addField("DocumentParent", path);
                    documentList.add(updatedDocument);
                }
                this.solr.add(documentList);
                this.solr.commit();
            }
        } catch (Exception ex) {
            throw new IndexException(ex, ex.getMessage());
        }
    }

    public IPathController getPathController() {
        return pathController;
    }

    public void setPathController(IPathController pathController) {
        this.pathController = pathController;
    }
}