All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alogient.cameleon.sdk.search.solr.SolrSearchService Maven / Gradle / Ivy

The newest version!
package com.alogient.cameleon.sdk.search.solr;

import com.alogient.cameleon.sdk.content.model.AbstractCameleonModel;
import com.alogient.cameleon.sdk.content.model.ImageModel;
import com.alogient.cameleon.sdk.content.model.ResourceModel;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModel;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelAllElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelClosestUpElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelElement.DataType;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelFirstElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelImage;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelLinkedElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelLinkedElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelParentElement;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelResource;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelReverseLinkedElements;
import com.alogient.cameleon.sdk.content.ui.injection.CameleonModelSubElements;
import com.alogient.cameleon.sdk.content.util.InternalCameleonConfig;
import com.alogient.cameleon.sdk.content.vo.media.VideoVo;
import com.alogient.cameleon.sdk.search.SearchService;
import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.ResponseParser;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.util.ContentStreamBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SolrSearchService implements SearchService {
    /**
     * The log for this class
     */
    protected final Logger log = LoggerFactory.getLogger(getClass());

    private final static String SERVER_URL = "cameleon.search.solr.server_url";

    private final static String SOCKET_TIMEOUT = "cameleon.search.solr.socket_timeout";

    private final static String CONNECTION_TIMEOUT = "cameleon.search.solr.connection_timeout";

    private final static String DEFAULT_MAX_CONNECTION_PER_HOST = "cameleon.search.solr.default_max_connection_per_host";

    private final static String DEFAULT_MAX_TOTAL_CONNECTION = "cameleon.search.solr.max_total_connection";

    private final static String FOLLOW_REDIRECTS = "cameleon.search.solr.follow_redirects";

    private final static String ALLOW_COMPRESSION = "cameleon.search.solr.allow_compression";

    private final static String MAX_RETRIES = "cameleon.search.solr.max_retries";

    private final static String PARSER = "cameleon.search.solr.parser";

    private final static String READ_ONLY = "cameleon.search.solr.read_only";

    private CommonsHttpSolrServer server;

    private boolean isReadOnly;

    private boolean isInitialized;

    public SolrSearchService() {
        isInitialized = false;
    }


    @Override
    public Set getIndexedUrls() {
        SolrQuery query = new SolrQuery();
        query.setQuery("*");
        query.setRows(Integer.MAX_VALUE);

        Set indexedUrls = new HashSet();
        try {
            QueryResponse response = server.query(query);
            for (SolrDocument document : response.getResults()) {
                indexedUrls.add((String) document.getFieldValue(SEARCH_ID));
            }
        } catch (SolrServerException e) {
            log.error(e.getMessage(), e);
        }
        return indexedUrls;
    }

    @Override
    public void removeIndex(String url) {
        try {
            server.deleteById(url);
            server.commit();
        } catch (SolrServerException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void indexBinaryDocument(String path, String fileName, boolean isRemote) {
        if (!isRemote) {
            indexLocalBinaryDocument(path, fileName);
        } else {
            indexRemoteBinaryDocument(path, fileName);
        }

    }

    private void indexLocalBinaryDocument(String path, String fileName) {
        try {
            File fileToIndex = new File(path);

            ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract");

            up.addFile(fileToIndex);
            up.setParam("literal.id", fileName);
            up.setParam("uprefix", "attr_");
            up.setParam("fmap.content", "attr_content");

            up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);

            server.request(up);
        } catch (IOException e) {
            log.error("Unable to index a binary document - " + e.getMessage(), e);
        } catch (SolrServerException e) {
            log.error("Unable to index a binary document - " + e.getMessage(), e);
        }
    }

    public void indexRemoteBinaryDocument(String remoteUrl, String fileName) {
        try {

            ContentStreamUpdateRequest up = new ContentStreamUpdateRequest("/update/extract");
            up.addContentStream(new ContentStreamBase.URLStream(new URL(remoteUrl)));

            up.setParam("literal.id", remoteUrl);
            up.setParam("resource.name", fileName);
            up.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true);

            server.request(up);
        } catch (IOException e) {
            log.error("Unable to index a binary document - " + e.getMessage(), e);
        } catch (SolrServerException e) {
            log.error("Unable to index a binary document - " + e.getMessage(), e);
        }
    }

    @Override
    public void indexCameleonModel(String url, AbstractCameleonModel model) {
        SolrInputDocument doc = new SolrInputDocument();
        doc.addField(SEARCH_ID, url);
        doc.addField(SEARCH_NAV_ID, model.getNavId());
        doc.addField(SEARCH_PAGE_ID, model.getPageId());
        doc.addField(SEARCH_CULTURE_CODE, model.getCultureCode());
        doc.addField(SEARCH_PAGE_NAME, model.getPageName());
        doc.addField("text", model.getPageName());

        // Extract the templateName
        Class clazz = model.getClass();
        if (clazz.isAnnotationPresent(CameleonModel.class)) {
            CameleonModel cameleonModel = clazz.getAnnotation(CameleonModel.class);

            doc.addField(SEARCH_TEMPLATE_NAME, cameleonModel.templateName());
        }

        // Index inner elements
        indexInnerElements(doc, model);

        try {
            server.add(doc);
            server.commit();
        } catch (SolrServerException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    private void indexInnerElements(SolrInputDocument doc, Object object) {
        if (object == null) {
            return;
        }


        if (object.getClass().isAnnotationPresent(CameleonModel.class)) {
            CameleonModel cameleonModel = object.getClass().getAnnotation(CameleonModel.class);

            AbstractCameleonModel abstractCameleonModel = (AbstractCameleonModel) object;

            if (!Strings.isNullOrEmpty(cameleonModel.pageNameIndexField())) {
                doc.addField(cameleonModel.pageNameIndexField(), abstractCameleonModel.getPageName());
            }
        }

        @SuppressWarnings("rawtypes")
        Class clazz = object.getClass();
        while (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                if (field.isAnnotationPresent(CameleonModelElement.class)) {
                    CameleonModelElement cme = field.getAnnotation(CameleonModelElement.class);
                    if (cme.isIndexed()) {
                        if (cme.dataType() == DataType.Value || cme.dataType() == DataType.OptionValue) {
                            Object elementValue = getFieldValue(field, object);

                            if (elementValue != null) {
                                doc.addField(StringUtils.isBlank(cme.valueIndexField()) ? "text" : cme.valueIndexField(), elementValue);
                            }
                        } else if (cme.dataType() == DataType.Video) {
                            VideoVo elementValue = getFieldValue(field, object);

                            if (elementValue != null) {
                                doc.addField(StringUtils.isBlank(cme.videoTitleIndexField()) ? "text" : cme.videoTitleIndexField(), elementValue.getTitle());
                                doc.addField(StringUtils.isBlank(cme.videoDescriptionIndexField()) ? "text" : cme.videoDescriptionIndexField(), elementValue.getDescription());
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelImage.class)) {
                    CameleonModelImage cmi = field.getAnnotation(CameleonModelImage.class);
                    if (cmi.isIndexed()) {
                        ImageModel elementValue = getFieldValue(field, object);

                        if (elementValue != null) {
                            doc.addField(StringUtils.isBlank(cmi.altIndexField()) ? "text" : cmi.altIndexField(), elementValue.getAlt());
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelResource.class)) {
                    CameleonModelResource cmi = field.getAnnotation(CameleonModelResource.class);
                    if (cmi.isIndexed()) {
                        ResourceModel elementValue = getFieldValue(field, object);

                        // Index the resource if the resource is live.
                        if ((elementValue != null) && elementValue.getModeType().isLiveMode()) {
                            indexBinaryDocument(elementValue.getUrl(), elementValue.getFileName(), true);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelLinkedElement.class)) {
                    CameleonModelLinkedElement cmle = field.getAnnotation(CameleonModelLinkedElement.class);
                    if (cmle.isIndexed()) {
                        Object subModel = getFieldValue(field, object);
                        if (subModel != null) {
                            indexInnerElements(doc, subModel);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelLinkedElements.class)) {
                    CameleonModelLinkedElements cmle = field.getAnnotation(CameleonModelLinkedElements.class);
                    if (cmle.isIndexed()) {
                        @SuppressWarnings("rawtypes")
                        List subModels = getFieldValue(field, object);

                        if (subModels != null) {
                            for (Object subModel : subModels) {
                                indexInnerElements(doc, subModel);
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelReverseLinkedElements.class)) {
                    CameleonModelReverseLinkedElements cmrle = field.getAnnotation(CameleonModelReverseLinkedElements.class);
                    if (cmrle.isIndexed()) {
                        @SuppressWarnings("rawtypes")
                        List subModels = getFieldValue(field, object);

                        if (subModels != null) {
                            for (Object subModel : subModels) {
                                indexInnerElements(doc, subModel);
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelAllElements.class)) {
                    CameleonModelAllElements cmae = field.getAnnotation(CameleonModelAllElements.class);
                    if (cmae.isIndexed()) {
                        @SuppressWarnings("rawtypes")
                        List subModels = getFieldValue(field, object);

                        if (subModels != null) {
                            for (Object subModel : subModels) {
                                indexInnerElements(doc, subModel);
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelFirstElement.class)) {
                    CameleonModelFirstElement cmfe = field.getAnnotation(CameleonModelFirstElement.class);
                    if (cmfe.isIndexed()) {
                        Object subModel = getFieldValue(field, object);
                        if (subModel != null) {
                            indexInnerElements(doc, subModel);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelSubElements.class)) {
                    CameleonModelSubElements cmse = field.getAnnotation(CameleonModelSubElements.class);
                    if (cmse.isIndexed()) {
                        @SuppressWarnings("rawtypes")
                        List subModels = getFieldValue(field, object);

                        if (subModels != null) {
                            for (Object subModel : subModels) {
                                indexInnerElements(doc, subModel);
                            }
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelParentElement.class)) {
                    CameleonModelParentElement cmpe = field.getAnnotation(CameleonModelParentElement.class);
                    if (cmpe.isIndexed()) {
                        Object subModel = getFieldValue(field, object);
                        if (subModel != null) {
                            indexInnerElements(doc, subModel);
                        }
                    }
                } else if (field.isAnnotationPresent(CameleonModelClosestUpElement.class)) {
                    CameleonModelClosestUpElement cmcue = field.getAnnotation(CameleonModelClosestUpElement.class);
                    if (cmcue.isIndexed()) {
                        Object subModel = getFieldValue(field, object);
                        if (subModel != null) {
                            indexInnerElements(doc, subModel);
                        }
                    }
                }
            }

            clazz = clazz.getSuperclass();
        }
    }

    @SuppressWarnings("unchecked")
    private  T getFieldValue(Field field, Object object) {
        field.setAccessible(true);
        try {
            return (T) field.get(object);
        } catch (IllegalArgumentException e) {
            log.error(e.getMessage(), e);
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isReadOnly() {
        return isReadOnly;
    }

    @Override
    public boolean isInitialized() {
        if (!isInitialized) {
            init();
        }


        return server != null;
    }

    @Override
    public List doSearch(SolrQuery query) {

        if (!isInitialized()) {
            return Collections.emptyList();
        }

        List results = new ArrayList();
        try {
            QueryResponse response = server.query(query);
            for (SolrDocument document : response.getResults()) {
                results.add(document);
            }
        } catch (SolrServerException e) {
            log.error(e.getMessage(), e);
        }

        return results;
    }


    private void init() {
        String serverUrl = InternalCameleonConfig.getString(SERVER_URL, null);
        Integer socketTimeout = InternalCameleonConfig.getInteger(SOCKET_TIMEOUT, null);
        Integer connectionTimeout = InternalCameleonConfig.getInteger(CONNECTION_TIMEOUT, null);
        Integer defaultMaxConnectionPerHost = InternalCameleonConfig.getInteger(DEFAULT_MAX_CONNECTION_PER_HOST, null);
        Integer defaultMaxTotalConnection = InternalCameleonConfig.getInteger(DEFAULT_MAX_TOTAL_CONNECTION, null);
        Boolean followRedirects = InternalCameleonConfig.getBoolean(FOLLOW_REDIRECTS, null);
        Boolean allowCompression = InternalCameleonConfig.getBoolean(ALLOW_COMPRESSION, null);
        Integer maxRetries = InternalCameleonConfig.getInteger(MAX_RETRIES, null);
        String parser = InternalCameleonConfig.getString(PARSER, null);
        isReadOnly = InternalCameleonConfig.getBoolean(READ_ONLY, Boolean.FALSE);

        if (StringUtils.isBlank(serverUrl)) {
            log.error("Solr cannot be initialized without a server url : cameleon.search.solr.server_url");
            return;
        }

        try {
            server = new CommonsHttpSolrServer(serverUrl);
        } catch (MalformedURLException e) {
            log.error("Solr cannot be initialized without a malformed url : ", e);
            return;
        }

        if (socketTimeout != null) {
            server.setSoTimeout(socketTimeout);
        }
        if (connectionTimeout != null) {
            server.setConnectionTimeout(connectionTimeout);
        }
        if (defaultMaxConnectionPerHost != null) {
            server.setDefaultMaxConnectionsPerHost(defaultMaxConnectionPerHost);
        }
        if (defaultMaxTotalConnection != null) {
            server.setMaxTotalConnections(defaultMaxTotalConnection);
        }
        if (followRedirects != null) {
            server.setFollowRedirects(followRedirects);
        }
        if (allowCompression != null) {
            server.setAllowCompression(allowCompression);
        }
        if (maxRetries != null) {
            server.setMaxRetries(maxRetries);
        }
        if (StringUtils.isNotBlank(parser)) {
            try {
                server.setParser((ResponseParser) Class.forName(parser).newInstance());
            } catch (InstantiationException e) {
                log.error(e.getMessage(), e);
                throw new IllegalStateException("Invalid parser " + parser);
            } catch (IllegalAccessException e) {
                log.error(e.getMessage(), e);
                throw new IllegalStateException("Invalid parser " + parser);
            } catch (ClassNotFoundException e) {
                log.error(e.getMessage(), e);
                throw new IllegalStateException("Invalid parser " + parser);
            }
        }

        isInitialized = true;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy