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

com.couchbase.client.java.search.result.hits.DefaultHitLocations Maven / Gradle / Ivy

/*
 * Copyright (c) 2016 Couchbase, 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.couchbase.client.java.search.result.hits;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.couchbase.client.core.annotations.InterfaceAudience;
import com.couchbase.client.core.annotations.InterfaceStability;
import com.couchbase.client.java.document.json.JsonArray;
import com.couchbase.client.java.document.json.JsonObject;

/**
 * A default implementation of a {@link HitLocations}.
 *
 * @author Simon Baslé
 * @author Michael Nitschinger
 * @since 2.3.0
 */
@InterfaceStability.Experimental
@InterfaceAudience.Public
public class DefaultHitLocations implements HitLocations {

    private final Map>> locations = new HashMap>>();
    private int size;

    @Override
    public HitLocations add(HitLocation l) {
        //note: it is not expected that multiple threads concurrently add a HitLocation, as even a
        //streaming parser would parse a single hit in its entirety, not individual locations.
        Map> byTerm = locations.get(l.field());
        if (byTerm == null) {
            byTerm = new HashMap>();
            locations.put(l.field(), byTerm);
        }

        List list = byTerm.get(l.term());
        if (list == null) {
            list = new ArrayList();
            byTerm.put(l.term(), list);
        }

        list.add(l);
        size++;
        return this;
    }

    @Override
    public List get(String field) {
        Map> byTerm = locations.get(field);
        if (byTerm == null) {
            return Collections.emptyList();
        }

        List result = new LinkedList();
        for (List termList : byTerm.values()) {
            result.addAll(termList);
        }
        return result;
    }

    @Override
    public List get(String field, String term) {
        Map> byTerm = locations.get(field);
        if (byTerm == null) {
            return Collections.emptyList();
        }

        List result = byTerm.get(term);
        if (result == null) {
            return Collections.emptyList();
        }
        return new ArrayList(result);
    }

    @Override
    public List getAll() {
        List all = new LinkedList();
        for (Map.Entry>> terms : locations.entrySet()) {
            for (List hitLocations : terms.getValue().values()) {
                all.addAll(hitLocations);
            }
        }
        return all;
    }

    @Override
    public long count() {
        return size;
    }

    @Override
    public List fields() {
        return new ArrayList(locations.keySet());
    }

    @Override
    public List termsFor(String field) {
        final Map> termMap = locations.get(field);
        if (termMap == null) {
            return Collections.emptyList();
        }
        return new ArrayList(termMap.keySet());
    }

    @Override
    public Set terms() {
        Set termSet = new HashSet();
        for (Map> termMap : locations.values()) {
            termSet.addAll(termMap.keySet());
        }
        return termSet;
    }

    /**
     * Parses a FTS JSON representation of a {@link HitLocations}.
     */
    public static HitLocations from(JsonObject locationsJson) {
        DefaultHitLocations hitLocations = new DefaultHitLocations();
        if (locationsJson == null) {
            return hitLocations;
        }

        for (String field : locationsJson.getNames()) {
            JsonObject termsJson = locationsJson.getObject(field);

            for (String term : termsJson.getNames()) {
                JsonArray locsJson = termsJson.getArray(term);

                for (int i = 0; i < locsJson.size(); i++) {
                    JsonObject loc = locsJson.getObject(i);
                    long pos = loc.getLong("pos");
                    long start = loc.getLong("start");
                    long end = loc.getLong("end");
                    JsonArray arrayPositionsJson = loc.getArray("array_positions");
                    long[] arrayPositions = null;
                    if (arrayPositionsJson != null) {
                        arrayPositions = new long[arrayPositionsJson.size()];
                        for (int j = 0; j < arrayPositionsJson.size(); j++) {
                            arrayPositions[j] = arrayPositionsJson.getLong(j);
                        }
                    }
                    hitLocations.add(new HitLocation(field, term, pos, start, end, arrayPositions));
                }
            }
        }
        return hitLocations;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("DefaultHitLocations{")
                .append("size=").append(size)
                .append(", locations=[");

        for (Map> map : locations.values()) {
            for (List hitLocations : map.values()) {
                for (HitLocation hitLocation : hitLocations) {
                    sb.append(hitLocation).append(",");
                }
            }
        }

        if (!locations.isEmpty()) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("]}");
        return sb.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy