com.opensearchserver.affinities.process.AffinityProcess.java Source code

Java tutorial

Introduction

Here is the source code for com.opensearchserver.affinities.process.AffinityProcess.java

Source

/**
 * Copyright 2015 OpenSearchServer Inc.
 *
 * 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.opensearchserver.affinities.process;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.ws.rs.core.Response.Status;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.http.client.ClientProtocolException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.opensearchserver.affinities.AffinityList;
import com.opensearchserver.affinities.model.Affinity;
import com.opensearchserver.affinities.model.AffinityBatchRequest;
import com.opensearchserver.affinities.model.AffinityRequest;
import com.opensearchserver.affinities.model.AffinityResults;
import com.opensearchserver.affinities.model.ServerResource;
import com.opensearchserver.client.JsonClient1;
import com.opensearchserver.client.common.index.TemplateEnum;
import com.opensearchserver.client.common.update.DocumentUpdate;
import com.opensearchserver.client.v1.FieldApi1;
import com.opensearchserver.client.v1.IndexApi1;
import com.opensearchserver.client.v1.UpdateApi1;
import com.opensearchserver.client.v1.field.FieldUpdate;
import com.opensearchserver.client.v1.field.SchemaField;
import com.opensearchserver.client.v1.field.SchemaField.Indexed;
import com.opensearchserver.client.v1.field.SchemaField.Stored;
import com.opensearchserver.utils.json.JsonApplicationException;
import com.opensearchserver.utils.json.JsonMapper;

public class AffinityProcess {

    public static AffinityResults execute(String name, Affinity affinity, AffinityRequest request)
            throws ClientProtocolException, URISyntaxException, IOException {
        AffinityResults results = null;
        boolean cache = request.getCacheOrDefault();
        String requestString = null;
        if (cache) {
            requestString = DigestUtils.md5Hex(JsonMapper.MAPPER.writeValueAsString(request));
            results = readCacheEntry(affinity, requestString);
            if (results != null)
                return results;
        }
        switch (affinity.getTypeOfDefault()) {
        case EXACT_MATCH:
            results = doExactMatch(name, affinity, request);
            break;
        case SCORING:
            results = doScoring(name, affinity, request);
            break;
        }
        if (results == null)
            return null;
        if (cache)
            writeCacheEntry(affinity, requestString, results);
        return results;
    }

    public static List<AffinityResults> execute(List<AffinityBatchRequest> requests)
            throws ClientProtocolException, URISyntaxException, IOException {
        List<AffinityResults> results = new ArrayList<AffinityResults>();
        for (AffinityBatchRequest request : requests) {
            Affinity affinity = AffinityList.INSTANCE.get(request.name);
            if (affinity == null)
                throw new JsonApplicationException(Status.NOT_FOUND, "Unknown: " + request.name);
            AffinityResults result = execute(request.name, affinity, request);
            results.add(result);
            switch (request.getActionOrDefault()) {
            case STOP_IF_FOUND:
                if (!result.isEmpty())
                    return results;
                break;
            case CONTINUE:
                break;
            }
        }
        return results;
    }

    /**
     * @param server
     * @return the right AffinityProcess implementation
     * @throws IOException
     */
    private static AffinityProcessInterface checkServerResource(ServerResource server) throws IOException {
        if (server == null)
            throw new ClientProtocolException("The server to used has not been configured.");
        switch (server.getVersionOfDefault()) {
        case 1:
            return new AffinityProcess1Impl();
        case 2:
            return new AffinityProcess2Impl();
        }
        throw new JsonApplicationException(Status.BAD_REQUEST, "Version not supported: " + server.version);
    }

    static AffinityResults doExactMatch(String name, Affinity affinity, AffinityRequest request)
            throws URISyntaxException, ClientProtocolException, IOException {
        return checkServerResource(affinity.data).doExactMatch(name, affinity, request);
    }

    static AffinityResults doScoring(String name, Affinity affinity, AffinityRequest request)
            throws JsonParseException, JsonMappingException, ClientProtocolException, IOException,
            URISyntaxException {

        Map<String, String> crawlResult = null;

        if (request.url != null) {
            // We do the crawl
            if (affinity.crawl_mapping == null || affinity.crawl_mapping.isEmpty())
                throw new JsonApplicationException(Status.NOT_ACCEPTABLE,
                        "The mapping between crawl and criteria is missing.");
            crawlResult = checkServerResource(affinity.crawl).doUrl(affinity.crawl, request.url);

            if (crawlResult != null) {
                // If we don't have critera, let's create the map
                if (request.criteria == null)
                    request.criteria = new LinkedHashMap<String, String>();

                // Copy crawl result to criteria
                for (Map.Entry<String, String> entry : affinity.crawl_mapping.entrySet()) {
                    String keyCriteria = entry.getKey().intern();
                    String keyCrawl = entry.getValue().intern();
                    String value = crawlResult.get(keyCrawl);
                    if (value != null && !value.isEmpty() && affinity.criteria.containsKey(keyCriteria))
                        request.criteria.put(keyCriteria, value);
                }
            }
        }

        if (request.criteria == null || request.criteria.isEmpty())
            throw new JsonApplicationException(Status.BAD_REQUEST, "The criteria are missing");
        return checkServerResource(affinity.data).doScoring(name, affinity, request);
    }

    static List<String> mergeReturnedFields(Affinity affinity, AffinityRequest request) {
        if (affinity.returned_fields == null)
            return request.returned_fields;
        if (request.returned_fields == null)
            return affinity.returned_fields;
        Set<String> set = new TreeSet<String>();
        set.addAll(affinity.returned_fields);
        set.addAll(request.returned_fields);
        return new ArrayList<String>(set);
    }

    static String anyGroupBy(Affinity affinity, AffinityRequest request) {
        String group_by = request.group_by;
        if (!StringUtils.isEmpty(group_by))
            return group_by;
        return StringUtils.isEmpty(affinity.group_by) ? null : affinity.group_by;
    }

    final static String CACHE_FIELD_KEY = "key";
    final static String CACHE_FIELD_DATE = "date";
    final static String CACHE_FIELD_VALUE = "value";

    final static FastDateFormat CACHE_DATEFORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss");

    public static void createCacheIndex(Affinity affinity) throws IOException, URISyntaxException {
        JsonClient1 client = checkServerResource(affinity.cache).getJsonClient(affinity.cache);
        IndexApi1 indexApi = new IndexApi1(client);
        if (indexApi.indexExists(affinity.cache.name))
            return;
        indexApi.createIndex(affinity.cache.name, TemplateEnum.EMPTY_INDEX);
        FieldApi1 fieldApi = new FieldApi1(client);
        List<SchemaField> fields = new ArrayList<SchemaField>();
        fields.add(new SchemaField().setName(CACHE_FIELD_KEY).setIndexed(Indexed.YES));
        fields.add(new SchemaField().setName(CACHE_FIELD_DATE).setIndexed(Indexed.YES));
        fields.add(new SchemaField().setName(CACHE_FIELD_VALUE).setIndexed(Indexed.NO).setStored(Stored.YES));
        fieldApi.setFields(affinity.cache.name, fields);
        fieldApi.setDefaultUniqueField(affinity.cache.name, CACHE_FIELD_KEY, CACHE_FIELD_KEY);
    }

    public static void writeCacheEntry(Affinity affinity, String requestString, AffinityResults results)
            throws URISyntaxException, IOException {
        JsonClient1 client = checkServerResource(affinity.cache).getJsonClient(affinity.cache);
        UpdateApi1 updateApi = new UpdateApi1(client);
        List<DocumentUpdate> documents = new ArrayList<DocumentUpdate>(1);
        documents.add(new DocumentUpdate().addField(new FieldUpdate(CACHE_FIELD_KEY, requestString, null))
                .addField(new FieldUpdate(CACHE_FIELD_DATE, CACHE_DATEFORMAT.format(System.currentTimeMillis()),
                        null))
                .addField(new FieldUpdate(CACHE_FIELD_VALUE, JsonMapper.MAPPER.writeValueAsString(results), null)));
        updateApi.updateDocuments(affinity.cache.name, documents);
    }

    public static AffinityResults readCacheEntry(Affinity affinity, String requestString)
            throws URISyntaxException, IOException {
        return checkServerResource(affinity.cache).readCacheEntry(affinity.cache, requestString);
    }
}