com.fujitsu.dc.common.es.impl.EsIndexImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.fujitsu.dc.common.es.impl.EsIndexImpl.java

Source

/**
 * personium.io
 * Copyright 2014 FUJITSU LIMITED
 *
 * 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.fujitsu.dc.common.es.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.CharEncoding;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.indices.IndexAlreadyExistsException;
import org.elasticsearch.indices.IndexMissingException;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fujitsu.dc.common.es.EsBulkRequest;
import com.fujitsu.dc.common.es.EsIndex;
import com.fujitsu.dc.common.es.query.DcQueryBuilder;
import com.fujitsu.dc.common.es.response.DcBulkResponse;
import com.fujitsu.dc.common.es.response.DcMultiSearchResponse;
import com.fujitsu.dc.common.es.response.DcSearchResponse;
import com.fujitsu.dc.common.es.response.EsClientException;
import com.fujitsu.dc.common.es.response.impl.DcBulkResponseImpl;
import com.fujitsu.dc.common.es.response.impl.DcMultiSearchResponseImpl;
import com.fujitsu.dc.common.es.response.impl.DcSearchResponseImpl;

/**
 * Index ? Class.
 */
public class EsIndexImpl extends EsTranslogHandler implements EsIndex {
    private InternalEsClient esClient;

    /**
     * .
     */
    static Logger log = LoggerFactory.getLogger(EsIndexImpl.class);

    // ?
    private int retryCount;
    // ?
    private int retryInterval;

    String name;
    String category;

    private EsTranslogHandler requestOwner;

    /**
     * ???????.
     * @param name ??
     * @param category 
     * @param times ES??????
     * @param interval ES??????()
     * @param client EsClient
     */
    public EsIndexImpl(final String name, final String category, int times, int interval, InternalEsClient client) {
        super(times, interval, client, name);
        // ?????????public???????????
        // EsClient??????
        this.name = name;
        this.category = category;
        this.retryCount = times;
        this.retryInterval = interval;
        this.esClient = client;

        this.requestOwner = this;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public String getCategory() {
        return this.category;
    }

    @Override
    public void create() {
        if (mappingConfigs == null) {
            loadMappingConfigs();
        }
        Map<String, JSONObject> mappings = mappingConfigs.get(this.category);
        if (mappings == null) {
            throw new EsClientException("NO MAPPINGS DEFINED for " + this.category + this.name);
        }

        CreateRetryableRequest request = new CreateRetryableRequest(retryCount, retryInterval, name, mappings);
        // ???????.
        request.doRequest();
    }

    @Override
    public void delete() {
        DeleteRetryableRequest request = new DeleteRetryableRequest(retryCount, retryInterval, this.name);
        // ???????.
        request.doRequest();
    }

    @Override
    public DcSearchResponse search(String routingId, final Map<String, Object> query) {
        SearchWithMapRetryableRequest request = new SearchWithMapRetryableRequest(retryCount, retryInterval,
                routingId, query);
        // ???????.
        return DcSearchResponseImpl.getInstance(request.doRequest());
    }

    @Override
    public DcSearchResponse search(String routingId, final DcQueryBuilder query) {
        SearchRetryableRequest request = new SearchRetryableRequest(retryCount, retryInterval, routingId,
                getQueryBuilder(query));
        // ???????.
        return DcSearchResponseImpl.getInstance(request.doRequest());
    }

    @Override
    public DcMultiSearchResponse multiSearch(String routingId, final List<Map<String, Object>> queryList) {
        MultiSearchRetryableRequest request = new MultiSearchRetryableRequest(retryCount, retryInterval, routingId,
                queryList);
        // ???????.
        return DcMultiSearchResponseImpl.getInstance(request.doRequest());
    }

    @Override
    public void deleteByQuery(String routingId, DcQueryBuilder queryBuilder) {
        QueryBuilder deleteQuery = getQueryBuilder(queryBuilder);
        DeleteByQueryRetryableRequest request = new DeleteByQueryRetryableRequest(retryCount, retryInterval,
                this.name, deleteQuery);
        request.doRequest();

        // ?????????????
        DcSearchResponse response = this.search(routingId, queryBuilder);
        long failedCount = response.getHits().getAllPages();
        if (failedCount != 0) {
            throw new EsClientException.EsDeleteByQueryException(failedCount);
        }
    }

    private QueryBuilder getQueryBuilder(DcQueryBuilder dcQueryBuilder) {
        QueryBuilder queryBuilder = null;
        if (dcQueryBuilder != null) {
            queryBuilder = dcQueryBuilder.getQueryBuilder();
        }
        if (queryBuilder == null) {
            log.info("Query is not specified.");
        }
        return queryBuilder;
    }

    @Override
    public DcBulkResponse bulkCreate(final String routingId, final List<EsBulkRequest> datas) {
        BulkCreateRetryableRequest request = new BulkCreateRetryableRequest(retryCount, retryInterval, this.name,
                routingId, datas);
        // ???????.
        return DcBulkResponseImpl.getInstance(request.doRequest());
    }

    /**
     * ??.
     * @param index ??
     * @param settings ?
     * @return Void
     */
    public Void updateSettings(String index, Map<String, String> settings) {
        UpdateSettingsRetryableRequest request = new UpdateSettingsRetryableRequest(retryCount, retryInterval,
                index, settings);
        // ???????.
        return request.doRequest();
    }

    /**
     * Elasticsearch?? index create?.
     */
    class CreateRetryableRequest extends AbstractRetryableEsRequest<CreateIndexResponse> {
        String name;
        Map<String, JSONObject> mappings;

        public CreateRetryableRequest(int retryCount, long retryInterval, String argName,
                Map<String, JSONObject> argMappings) {
            super(retryCount, retryInterval, "EsIndex create");
            name = argName;
            mappings = argMappings;
        }

        @Override
        CreateIndexResponse doProcess() {
            return esClient.createIndex(name, mappings).actionGet();
        }

        /**
         * ????????true???????.
         * ???#onParticularError???.
         * ??, ? false?.
         * @param e ?
         * @return true: ?????, false: ??
         */
        @Override
        boolean isParticularError(ElasticsearchException e) {
            return e instanceof IndexAlreadyExistsException || e.getCause() instanceof IndexAlreadyExistsException;
        }

        @Override
        CreateIndexResponse onParticularError(ElasticsearchException e) {
            if (e instanceof IndexAlreadyExistsException || e.getCause() instanceof IndexAlreadyExistsException) {
                throw new EsClientException.EsIndexAlreadyExistsException(e);
            }
            throw e;
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * Elasticsearch?? index delete?.
     */
    class DeleteRetryableRequest extends AbstractRetryableEsRequest<DeleteIndexResponse> {
        String name;

        public DeleteRetryableRequest(int retryCount, long retryInterval, String argName) {
            super(retryCount, retryInterval, "EsIndex delete");
            name = argName;
        }

        @Override
        DeleteIndexResponse doProcess() {
            return esClient.deleteIndex(this.name).actionGet();
        }

        @Override
        boolean isParticularError(ElasticsearchException e) {
            return e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException;
        }

        @Override
        DeleteIndexResponse onParticularError(ElasticsearchException e) {
            if (e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException) {
                throw new EsClientException.EsIndexMissingException(e);
            }
            throw e;
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    static Map<String, Map<String, JSONObject>> mappingConfigs = null;

    static synchronized void loadMappingConfigs() {
        if (mappingConfigs != null) {
            return;
        }
        mappingConfigs = new HashMap<String, Map<String, JSONObject>>();
        loadMappingConfig(EsIndex.CATEGORY_AD, "Domain", "es/mapping/domain.json");
        loadMappingConfig(EsIndex.CATEGORY_AD, "Cell", "es/mapping/cell.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "link", "es/mapping/link.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "Account", "es/mapping/account.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "Box", "es/mapping/box.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "Role", "es/mapping/role.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "Relation", "es/mapping/relation.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "SentMessage", "es/mapping/sentMessage.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "ReceivedMessage", "es/mapping/receivedMessage.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "EntityType", "es/mapping/entityType.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "AssociationEnd", "es/mapping/associationEnd.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "Property", "es/mapping/property.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "ComplexType", "es/mapping/complexType.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "ComplexTypeProperty", "es/mapping/complexTypeProperty.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "ExtCell", "es/mapping/extCell.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "ExtRole", "es/mapping/extRole.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "dav", "es/mapping/dav.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "UserData", "es/mapping/userdata.json");
        loadMappingConfig(EsIndex.CATEGORY_USR, "_default_", "es/mapping/default.json");
    }

    static void loadMappingConfig(String indexCat, String typeCat, String resPath) {
        JSONObject json = readJsonResource(resPath);
        Map<String, JSONObject> idxMappings = mappingConfigs.get(indexCat);
        if (idxMappings == null) {
            idxMappings = new HashMap<String, JSONObject>();
            mappingConfigs.put(indexCat, idxMappings);
        }
        idxMappings.put(typeCat, json);
    }

    /**
     * ?JSON???????.
     * @param resPath 
     * @return ???JSON
     */
    private static JSONObject readJsonResource(final String resPath) {
        JSONParser jp = new JSONParser();
        JSONObject json = null;
        InputStream is = null;
        try {
            is = EsIndexImpl.class.getClassLoader().getResourceAsStream(resPath);
            json = (JSONObject) jp.parse(new InputStreamReader(is, CharEncoding.UTF_8));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return json;
    }

    /**
     * ????????.
     */
    public static class TooLongIndexNameException extends RuntimeException {
        /**
         * ?ID.
         */
        private static final long serialVersionUID = 1L;

        /**
         * .
         * @param msg 
         */
        public TooLongIndexNameException(final String msg) {
            super(msg);
        }
    }

    /**
     * Elasticsearch?? search?. <br />
     * Query?Map????QueryBuilder????????.
     */
    @Deprecated
    class SearchWithMapRetryableRequest extends AbstractRetryableEsRequest<SearchResponse> {
        String routingId;
        Map<String, Object> query;

        public SearchWithMapRetryableRequest(int retryCount, long retryInterval, String argRoutingId,
                Map<String, Object> argQuery) {
            super(retryCount, retryInterval, "EsIndex search");
            query = argQuery;
            routingId = argRoutingId;
        }

        @Override
        SearchResponse doProcess() {
            return asyncIndexSearch(routingId, query).actionGet();
        }

        @Override
        boolean isParticularError(ElasticsearchException e) {
            return e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException
                    || e instanceof SearchPhaseExecutionException;
        }

        @Override
        SearchResponse onParticularError(ElasticsearchException e) {
            if (e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException) {
                return null;
            }
            if (e instanceof SearchPhaseExecutionException) {
                throw new EsClientException("unknown property was appointed.", e);
            }
            throw e;
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * Elasticsearch?? search?.
     */
    class SearchRetryableRequest extends AbstractRetryableEsRequest<SearchResponse> {
        String routingId;
        QueryBuilder query;

        public SearchRetryableRequest(int retryCount, long retryInterval, String argRoutingId,
                QueryBuilder argQuery) {
            super(retryCount, retryInterval, "EsIndex search");
            routingId = argRoutingId;
            query = argQuery;
        }

        @Override
        boolean isParticularError(ElasticsearchException e) {
            return e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException
                    || e instanceof SearchPhaseExecutionException;
        }

        @Override
        SearchResponse doProcess() {
            return asyncIndexSearch(routingId, query).actionGet();
        }

        @Override
        SearchResponse onParticularError(ElasticsearchException e) {
            if (e instanceof IndexMissingException || e.getCause() instanceof IndexMissingException) {
                return null;
            }
            if (e instanceof SearchPhaseExecutionException) {
                throw new EsClientException("unknown property was appointed.", e);
            }
            throw e;
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * Elasticsearch?? multisearch?.
     */
    class MultiSearchRetryableRequest extends AbstractRetryableEsRequest<MultiSearchResponse> {
        String routingId;
        List<Map<String, Object>> queryList;

        public MultiSearchRetryableRequest(int retryCount, long retryInterval, String argRoutingId,
                List<Map<String, Object>> argQueryList) {
            super(retryCount, retryInterval, "EsIndex search");
            routingId = argRoutingId;
            queryList = argQueryList;
        }

        @Override
        MultiSearchResponse doProcess() {
            return asyncMultiIndexSearch(routingId, queryList).actionGet();
        }

        @Override
        boolean isParticularError(ElasticsearchException e) {
            return e instanceof SearchPhaseExecutionException;
        }

        @Override
        MultiSearchResponse onParticularError(ElasticsearchException e) {
            if (e instanceof SearchPhaseExecutionException) {
                throw new EsClientException("unknown property was appointed.", e);
            }
            throw e;
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * Elasticsearch?? delete by query?.
     */
    class DeleteByQueryRetryableRequest extends AbstractRetryableEsRequest<DeleteByQueryResponse> {
        String name;
        QueryBuilder deleteQuery;

        public DeleteByQueryRetryableRequest(int retryCount, long retryInterval, String argName,
                QueryBuilder argDeleteQuery) {
            super(retryCount, retryInterval, "EsIndex deleteByQuery");
            name = argName;
            deleteQuery = argDeleteQuery;
        }

        @Override
        DeleteByQueryResponse doProcess() {
            return esClient.deleteByQuery(name, deleteQuery);
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * Elasticsearch?? update index settings?.
     */
    class UpdateSettingsRetryableRequest extends AbstractRetryableEsRequest<Void> {
        String index;
        Map<String, String> settings;

        public UpdateSettingsRetryableRequest(int retryCount, long retryInterval, String index,
                Map<String, String> settings) {
            super(retryCount, retryInterval, "EsIndex updateSettings");
            this.index = index;
            this.settings = settings;
        }

        @Override
        Void doProcess() {
            return esClient.updateIndexSettings(index, settings);
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }

    /**
     * ???. <br />
     * Query?Map????QueryBuilder????????.
     * @param routingId routingId
     * @param query 
     * @return ES
     */
    public ActionFuture<SearchResponse> asyncIndexSearch(String routingId, final Map<String, Object> query) {
        return esClient.asyncSearch(this.name, routingId, query);
    }

    /**
     * ???.
     * @param routingId routingId
     * @param query 
     * @return ES
     */
    public ActionFuture<SearchResponse> asyncIndexSearch(String routingId, final QueryBuilder query) {
        return esClient.asyncSearch(this.name, routingId, query);
    }

    /**
     * ????.
     * @param routingId routingId
     * @param queryList 
     * @return ES
     */
    public ActionFuture<MultiSearchResponse> asyncMultiIndexSearch(String routingId,
            final List<Map<String, Object>> queryList) {
        return esClient.asyncMultiSearch(this.name, routingId, queryList);
    }

    /**
     * Elasticsearch?? bulk create?.
     */
    class BulkCreateRetryableRequest extends AbstractRetryableEsRequest<BulkResponse> {
        String name;
        String routingId;
        List<EsBulkRequest> datas;

        public BulkCreateRetryableRequest(int retryCount, long retryInterval, String argName, String argRoutingId,
                List<EsBulkRequest> argDatas) {
            super(retryCount, retryInterval, "EsIndex bulkCreate");
            name = argName;
            routingId = argRoutingId;
            datas = argDatas;
        }

        @Override
        BulkResponse doProcess() {
            return esClient.bulkCreate(name, routingId, datas);
        }

        @Override
        EsTranslogHandler getEsTranslogHandler() {
            return requestOwner;
        }
    }
}