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

redis.clients.jedis.search.SearchBuilderFactory Maven / Gradle / Ivy

The newest version!
package redis.clients.jedis.search;

import static redis.clients.jedis.BuilderFactory.STRING;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import redis.clients.jedis.Builder;
import redis.clients.jedis.BuilderFactory;
import redis.clients.jedis.util.DoublePrecision;
import redis.clients.jedis.util.KeyValue;
import redis.clients.jedis.util.SafeEncoder;

public final class SearchBuilderFactory {

  public static final Builder> SEARCH_PROFILE_PROFILE = new Builder>() {

    private final String ITERATORS_PROFILE_STR = "Iterators profile";
    private final String CHILD_ITERATORS_STR = "Child iterators";
    private final String RESULT_PROCESSORS_PROFILE_STR = "Result processors profile";

    @Override
    public Map build(Object data) {
      List list = (List) SafeEncoder.encodeObject(data);
      Map profileMap = new HashMap<>(list.size(), 1f);

      for (Object listObject : list) {
        List attributeList = (List) listObject;
        String attributeName = (String) attributeList.get(0);
        Object attributeValue;

        if (attributeList.size() == 2) {

          Object value = attributeList.get(1);
          if (attributeName.equals(ITERATORS_PROFILE_STR)) {
            attributeValue = parseIterators(value);
          } else if (attributeName.endsWith(" time")) {
            attributeValue = DoublePrecision.parseEncodedFloatingPointNumber(value);
          } else {
            attributeValue = value;
          }

        } else if (attributeList.size() > 2) {

          if (attributeName.equals(RESULT_PROCESSORS_PROFILE_STR)) {
            List> resultProcessorsProfileList = new ArrayList<>(attributeList.size() - 1);
            for (int i = 1; i < attributeList.size(); i++) {
              resultProcessorsProfileList.add(parseResultProcessors(attributeList.get(i)));
            }
            attributeValue = resultProcessorsProfileList;
          } else {
            attributeValue = attributeList.subList(1, attributeList.size());
          }

        } else {
          attributeValue = null;
        }

        profileMap.put(attributeName, attributeValue);
      }
      return profileMap;
    }

    private Map parseResultProcessors(Object data) {
      List list = (List) data;
      Map map = new HashMap<>(list.size() / 2, 1f);
      for (int i = 0; i < list.size(); i += 2) {
        String key = (String) list.get(i);
        Object value = list.get(i + 1);
        if (key.equals("Time")) {
          value = DoublePrecision.parseEncodedFloatingPointNumber(value);
        }
        map.put(key, value);
      }
      return map;
    }

    private Object parseIterators(Object data) {
      if (!(data instanceof List)) return data;
      List iteratorsAttributeList = (List) data;
      int childIteratorsIndex = iteratorsAttributeList.indexOf(CHILD_ITERATORS_STR);
      // https://github.com/RediSearch/RediSearch/issues/3205 patch. TODO: Undo if resolved in RediSearch.
      if (childIteratorsIndex < 0) childIteratorsIndex = iteratorsAttributeList.indexOf("Child iterator");

      Map iteratorsProfile;
      if (childIteratorsIndex < 0) {
        childIteratorsIndex = iteratorsAttributeList.size();
        iteratorsProfile = new HashMap<>(childIteratorsIndex / 2, 1f);
      } else {
        iteratorsProfile = new HashMap<>(1 + childIteratorsIndex / 2, 1f);
      }

      for (int i = 0; i < childIteratorsIndex; i += 2) {
        String key = (String) iteratorsAttributeList.get(i);
        Object value = iteratorsAttributeList.get(i + 1);
        if (key.equals("Time")) {
          value = DoublePrecision.parseEncodedFloatingPointNumber(value);
        }
        iteratorsProfile.put(key, value);
      }

      if (childIteratorsIndex + 1 < iteratorsAttributeList.size()) {
        List childIteratorsList = new ArrayList(iteratorsAttributeList.size() - childIteratorsIndex - 1);
        for (int i = childIteratorsIndex + 1; i < iteratorsAttributeList.size(); i++) {
          childIteratorsList.add(parseIterators(iteratorsAttributeList.get(i)));
        }
        iteratorsProfile.put(CHILD_ITERATORS_STR, childIteratorsList);
      }
      return iteratorsProfile;
    }
  };

  public static final Builder>> SEARCH_SYNONYM_GROUPS = new Builder>>() {
    @Override
    public Map> build(Object data) {
      List list = (List) data;
      if (list.isEmpty()) return Collections.emptyMap();

      if (list.get(0) instanceof KeyValue) {
        return ((List) data).stream().collect(Collectors.toMap(
            kv -> STRING.build(kv.getKey()), kv -> BuilderFactory.STRING_LIST.build(kv.getValue())));
      }

      Map> dump = new HashMap<>(list.size() / 2, 1f);
      for (int i = 0; i < list.size(); i += 2) {
        dump.put(STRING.build(list.get(i)), BuilderFactory.STRING_LIST.build(list.get(i + 1)));
      }
      return dump;
    }
  };

  public static final Builder>> SEARCH_SPELLCHECK_RESPONSE
      = new Builder>>() {

    private static final String TERM = "TERM";
    private static final String RESULTS = "results";

    @Override
    public Map> build(Object data) {
      List rawDataList = (List) data;
      if (rawDataList.isEmpty()) return Collections.emptyMap();

      if (rawDataList.get(0) instanceof KeyValue) {
        KeyValue rawData = (KeyValue) rawDataList.get(0);
        String header = STRING.build(rawData.getKey());
        if (!RESULTS.equals(header)) {
          throw new IllegalStateException("Unrecognized header: " + header);
        }

        return ((List) rawData.getValue()).stream().collect(Collectors.toMap(
            rawTerm -> STRING.build(rawTerm.getKey()),
            rawTerm -> ((List>) rawTerm.getValue()).stream()
                .collect(Collectors.toMap(entry -> STRING.build(entry.get(0).getKey()),
                      entry -> BuilderFactory.DOUBLE.build(entry.get(0).getValue()))),
            (x, y) -> x, LinkedHashMap::new));
      }

      Map> returnTerms = new LinkedHashMap<>(rawDataList.size());

      for (Object rawData : rawDataList) {
        List rawElements = (List) rawData;

        String header = STRING.build(rawElements.get(0));
        if (!TERM.equals(header)) {
          throw new IllegalStateException("Unrecognized header: " + header);
        }
        String term = STRING.build(rawElements.get(1));

        List> list = (List>) rawElements.get(2);
        Map entries = new LinkedHashMap<>(list.size());
        list.forEach(entry -> entries.put(STRING.build(entry.get(1)), BuilderFactory.DOUBLE.build(entry.get(0))));

        returnTerms.put(term, entries);
      }
      return returnTerms;
    }
  };

  private SearchBuilderFactory() {
    throw new InstantiationError("Must not instantiate this class");
  }
}