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

com.bericotech.clavin.gazetteer.query.QueryBuilder Maven / Gradle / Ivy

Go to download

CLAVIN (Cartographic Location And Vicinity INdexer) is an open source software package for geographic entity resolution from text.

The newest version!
/*#####################################################################
 *
 * CLAVIN (Cartographic Location And Vicinity INdexer)
 * ---------------------------------------------------
 *
 * Copyright (C) 2012-2013 Berico Technologies
 * http://clavin.bericotechnologies.com
 *
 * ====================================================================
 *
 * 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.
 *
 * ====================================================================
 *
 * QueryBuilder.java
 *
 *###################################################################*/

package com.bericotech.clavin.gazetteer.query;

import com.bericotech.clavin.extractor.LocationOccurrence;
import com.bericotech.clavin.gazetteer.FeatureCode;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

/**
 * A Builder class to assist in creating GazetteerQuery configurations.
 * QueryBuilders can be re-used to create varied queries but are not
 * thread-safe.
 */
public class QueryBuilder {
    private static final int DEFAULT_MAX_RESULTS = 10;
    private static final FuzzyMode DEFAULT_FUZZY_MODE = FuzzyMode.OFF;
    private static final AncestryMode DEFAULT_HIERARCHY_MODE = AncestryMode.LAZY;
    private static final boolean DEFAULT_INCLUDE_HISTORICAL = true;
    private static final boolean DEFAULT_FILTER_DUPES = false;

    private static final Set COUNTRY_CODES = Collections.unmodifiableSet(EnumSet.of(
            FeatureCode.PCL,
            FeatureCode.PCLD,
            FeatureCode.PCLF,
            FeatureCode.PCLH,
            FeatureCode.PCLI,
            FeatureCode.PCLIX,
            FeatureCode.PCLS,
            FeatureCode.TERRI
    ));

    private static final Set ANCESTRY_ADMIN_CODES = Collections.unmodifiableSet(EnumSet.of(
            FeatureCode.ADM1,
            FeatureCode.ADM1H,
            FeatureCode.ADM2,
            FeatureCode.ADM2H,
            FeatureCode.ADM3,
            FeatureCode.ADM3H,
            FeatureCode.ADM4,
            FeatureCode.ADM4H
    ));

    private static final Set ADMIN_CODES = Collections.unmodifiableSet(EnumSet.of(
            FeatureCode.ADM1,
            FeatureCode.ADM1H,
            FeatureCode.ADM2,
            FeatureCode.ADM2H,
            FeatureCode.ADM3,
            FeatureCode.ADM3H,
            FeatureCode.ADM4,
            FeatureCode.ADM4H,
            FeatureCode.ADM5,
            FeatureCode.ADMD,
            FeatureCode.ADMDH,
            FeatureCode.TERR,
            FeatureCode.PRSH
    ));

    private static final Set CITY_CODES = Collections.unmodifiableSet(EnumSet.of(
            FeatureCode.PPL,
            FeatureCode.PPLA,
            FeatureCode.PPLA2,
            FeatureCode.PPLA3,
            FeatureCode.PPLA4,
            FeatureCode.PPLC,
            FeatureCode.PPLCH,
            FeatureCode.PPLF,
            FeatureCode.PPLG,
            FeatureCode.PPLH,
            FeatureCode.PPLL,
            FeatureCode.PPLQ,
            FeatureCode.PPLR,
            FeatureCode.PPLS,
            FeatureCode.PPLW,
            FeatureCode.PPLX,
            FeatureCode.STLMT
    ));

    private LocationOccurrence location;
    private int maxResults = DEFAULT_MAX_RESULTS;
    private FuzzyMode fuzzyMode = DEFAULT_FUZZY_MODE;
    private AncestryMode ancestryMode = DEFAULT_HIERARCHY_MODE;
    private boolean includeHistorical = DEFAULT_INCLUDE_HISTORICAL;
    private boolean filterDupes = DEFAULT_FILTER_DUPES;
    private Set parentIds = new HashSet();
    private Set featureCodes = EnumSet.noneOf(FeatureCode.class);

    /**
     * Constructs a query from the current configuration of this Builder.
     * @return a {@link GazetteerQuery} configuration object
     */
    public GazetteerQuery build() {
        return new GazetteerQuery(location, maxResults, fuzzyMode, ancestryMode, includeHistorical, filterDupes, parentIds, featureCodes);
    }

    /**
     * Get the currently configured location to query for.
     * @return the location to query for
     */
    public LocationOccurrence location() {
        return location;
    }

    /**
     * Set the location to query for.
     * @param loc the location to query for.
     * @return this
     */
    public QueryBuilder location(final LocationOccurrence loc) {
        location = loc;
        return this;
    }

    /**
     * Convenience method to create a LocationOccurrence at position 0 for
     * the given location name.
     * @param locName the name of the location to query for
     * @return this
     */
    public QueryBuilder location(final String locName) {
        location = new LocationOccurrence(locName, 0);
        return this;
    }

    /**
     * Get the current maximum number of results.
     * @return the maximum number of results
     */
    public int maxResults() {
        return maxResults;
    }

    /**
     * Set the maximum number of search results.
     * @param max the maximum number of results
     * @return this
     */
    public QueryBuilder maxResults(final int max) {
        maxResults = max;
        return this;
    }

    /**
     * Get the current fuzzy matching mode.
     * @return the fuzzy matching mode
     */
    public FuzzyMode fuzzyMode() {
        return fuzzyMode;
    }

    /**
     * Configure the fuzzy matching mode.
     * @param mode the fuzzy matching mode
     * @return this
     */
    public QueryBuilder fuzzyMode(final FuzzyMode mode) {
        fuzzyMode = mode;
        return this;
    }

    /**
     * Get the current ancestry loading mode.
     * @return the ancestry loading mode
     */
    public AncestryMode ancestryMode() {
        return ancestryMode;
    }

    /**
     * Configure the ancestry loading mode.
     * @param mode the ancestry loading mode
     * @return this
     */
    public QueryBuilder ancestryMode(final AncestryMode mode) {
        ancestryMode = mode;
        return this;
    }

    /**
     * Does this builder include historical locations?
     * @return true if this builder is configured to return historical locations
     */
    public boolean includeHistorical() {
        return includeHistorical;
    }

    /**
     * Indicate whether or not this builder includes historical locations in the search results.
     * @param incHist true to include historical locations in the results
     * @return this
     */
    public QueryBuilder includeHistorical(final boolean incHist) {
        includeHistorical = incHist;
        return this;
    }

    /**
     * Does this builder filter duplicate results?
     * @return true if this builder is configured to filter duplicates
     */
    public boolean filterDupes() {
        return filterDupes;
    }

    /**
     * Indicate whether or not this builder should filter duplicate results.
     * @param filter true to filter duplicate results
     * @return this
     */
    public QueryBuilder filterDupes(final boolean filter) {
        filterDupes = filter;
        return this;
    }

    /**
     * Get the set of parent IDs that will be used to constrain the query results.  This set
     * may not be modifiable and modifications, if allowed, will not affect the generated
     * queries.
     * @return the current set of parent IDs used to constrain the query results
     */
    public Set parentIds() {
        return Collections.unmodifiableSet(parentIds);
    }

    /**
     * Set the parent IDs that will be used to constraint the query results; replacing any
     * previously configured IDs. Use the addParentIds() and removeParentIds() methods to
     * modify the existing configuration.
     * @param ids the new set of parent IDs used to constrain the query results
     * @return this
     */
    public QueryBuilder parentIds(final Set ids) {
        parentIds = new HashSet();
        if (ids != null) {
            parentIds.addAll(ids);
        }
        return this;
    }

    /**
     * Add the provided parent ID to the set of query constraints.
     * @param id the parent ID to add
     * @return this
     */
    public QueryBuilder addParentIds(final Integer id) {
        parentIds.add(id);
        return this;
    }

    /**
     * Add the provided parent IDs to the set of query constraints.
     * @param id1 the first parent ID to add
     * @param ids the subsequent parent IDs to add
     * @return this
     */
    public QueryBuilder addParentIds(final Integer id1, final Integer... ids) {
        parentIds.add(id1);
        parentIds.addAll(Arrays.asList(ids));
        return this;
    }

    /**
     * Add the provided parent IDs to the set of query constraints.
     * @param ids the parent IDs to add
     * @return this
     */
    public QueryBuilder addParentIds(final Collection ids) {
        if (ids != null) {
            parentIds.addAll(ids);
        }
        return this;
    }

    /**
     * Remove the provided parent ID from the set of query constraints.
     * @param id the parent ID to remove
     * @return this
     */
    public QueryBuilder removeParentIds(final Integer id) {
        parentIds.remove(id);
        return this;
    }

    /**
     * Remove the provided parent IDs from the set of query constraints.
     * @param id1 the first parent ID to remove
     * @param ids the subsequent parent IDs to remove
     * @return this
     */
    public QueryBuilder removeParentIds(final Integer id1, final Integer... ids) {
        parentIds.remove(id1);
        parentIds.removeAll(Arrays.asList(ids));
        return this;
    }

    /**
     * Remove the provided parent IDs from the set of query constraints.
     * @param ids the parent IDs to remove
     * @return this
     */
    public QueryBuilder removeParentIds(final Collection ids) {
        if (ids != null) {
            parentIds.removeAll(ids);
        }
        return this;
    }

    /**
     * Convenience method to remove all current parent ID restrictions.
     * @return this
     */
    public QueryBuilder clearParentIds() {
        parentIds = new HashSet();
        return this;
    }

    /**
     * Get the set of {@link FeatureCode}s that will be used to constrain the query results.  This set
     * may not be modifiable and modifications, if allowed, will not affect the generated
     * queries.
     * @return the current set of {@link FeatureCode}s used to constrain the query results
     */
    public Set featureCodes() {
        return Collections.unmodifiableSet(featureCodes);
    }

    /**
     * Set the {@link FeatureCode}s that will be used to constraint the query results; replacing any
     * previously configured IDs. Use the addFeatureCodes() and removeFeatureCodes() methods to
     * modify the existing configuration.
     * @param codes the new set of {@link FeatureCode}s used to constrain the query results
     * @return this
     */
    public QueryBuilder featureCodes(final Set codes) {
        featureCodes = EnumSet.noneOf(FeatureCode.class);
        if (codes != null) {
            featureCodes.addAll(codes);
        }
        return this;
    }

    /**
     * Add the provided {@link FeatureCode} to the set of query constraints.
     * @param code the {@link FeatureCode} to add
     * @return this
     */
    public QueryBuilder addFeatureCodes(final FeatureCode code) {
        featureCodes.add(code);
        return this;
    }

    /**
     * Add the provided {@link FeatureCode}s to the set of query constraints.
     * @param code1 the first {@link FeatureCode} to add
     * @param codes the subsequent {@link FeatureCode}s to add
     * @return this
     */
    public QueryBuilder addFeatureCodes(final FeatureCode code1, final FeatureCode... codes) {
        featureCodes.add(code1);
        featureCodes.addAll(Arrays.asList(codes));
        return this;
    }

    /**
     * Add the provided {@link FeatureCode}s to the set of query constraints.
     * @param codes the {@link FeatureCode}s to add
     * @return this
     */
    public QueryBuilder addFeatureCodes(final Collection codes) {
        if (codes != null) {
            featureCodes.addAll(codes);
        }
        return this;
    }

    /**
     * Remove the provided {@link FeatureCode} from the set of query constraints.
     * @param code the {@link FeatureCode} to remove
     * @return this
     */
    public QueryBuilder removeFeatureCodes(final FeatureCode code) {
        featureCodes.remove(code);
        return this;
    }

    /**
     * Remove the provided {@link FeatureCode} from the set of query constraints.
     * @param code1 the first {@link FeatureCode} to remove
     * @param codes the subsequent {@link FeatureCode}s to remove
     * @return this
     */
    public QueryBuilder removeFeatureCodes(final FeatureCode code1, final FeatureCode... codes) {
        featureCodes.remove(code1);
        featureCodes.removeAll(Arrays.asList(codes));
        return this;
    }

    /**
     * Remove the provided {@link FeatureCode}s from the set of query constraints.
     * @param codes the {@link FeatureCode}s to remove
     * @return this
     */
    public QueryBuilder removeFeatureCodes(final Collection codes) {
        if (codes != null) {
            featureCodes.removeAll(codes);
        }
        return this;
    }

    /**
     * Convenience method to clear any existing {@link FeatureCode} restrictions.
     * @return this
     */
    public QueryBuilder clearFeatureCodes() {
        featureCodes = EnumSet.noneOf(FeatureCode.class);
        return this;
    }

    /**
     * Convenience method to add the {@link FeatureCode}s representing countries
     * and similar top-level political entities to the restriction list.  This
     * method modifies the existing set of codes.
     * @return this
     */
    public QueryBuilder addCountryCodes() {
        return addFeatureCodes(COUNTRY_CODES);
    }

    /**
     * Convenience method to remove the {@link FeatureCode}s representing countries
     * and similar top-level political entities from the restriction list.  This
     * method modifies the existing set of codes.
     * @return this
     */
    public QueryBuilder removeCountryCodes() {
        return removeFeatureCodes(COUNTRY_CODES);
    }

    /**
     * Convenience method to add the {@link FeatureCode}s representing administrative
     * divisions to the restriction list. This includes all ADM* codes, territories (TERR)
     * and parishes (PRSH). This method modifies the existing set of codes.
     * @return this
     */
    public QueryBuilder addAdminCodes() {
        return addFeatureCodes(ADMIN_CODES);
    }

    /**
     * Convenience method to remove the {@link FeatureCode}s representing administrative
     * divisions from the restriction list. This includes all ADM* codes, territories (TERR)
     * and parishes (PRSH). This method modifies the existing set of codes.
     * @return this
     */
    public QueryBuilder removeAdminCodes() {
        return removeFeatureCodes(ADMIN_CODES);
    }

    /**
     * Convenience method to add the {@link FeatureCode}s representing administrative
     * divisions that can be part of the ancestry tree to the restriction list.  This
     * only includes administrative divisions 1-4 (ADM[1-4]). This method modifies the
     * existing set of codes.
     * @return this
     */
    public QueryBuilder addAncestryAdminCodes() {
        return addFeatureCodes(ANCESTRY_ADMIN_CODES);
    }

    /**
     * Convenience method to remove the {@link FeatureCode}s representing administrative
     * divisions that can be part of the ancestry tree from the restriction list.  This
     * only includes administrative divisions 1-4 (ADM[1-4]). This method modifies the
     * existing set of codes.
     * @return this
     */
    public QueryBuilder removeAncestryAdminCodes() {
        return removeFeatureCodes(ANCESTRY_ADMIN_CODES);
    }

    /**
     * Convenience method to add the {@link FeatureCode}s representing cities and other
     * populated places to the restriction list. This method modifies the existing set
     * of codes.
     * @return this
     */
    public QueryBuilder addCityCodes() {
        return addFeatureCodes(CITY_CODES);
    }

    /**
     * Convenience method to remove the {@link FeatureCode}s representing cities and other
     * populated places from the restriction list. This method modifies the existing set
     * of codes.
     * @return this
     */
    public QueryBuilder removeCityCodes() {
        return removeFeatureCodes(CITY_CODES);
    }

    @Override
    public String toString() {
        return String.format("loc: %s, maxResults: %s, fuzzyMode: %s, historical? %s, filterDupes? %s, parents: %s, codes: %s",
                location, maxResults, fuzzyMode, includeHistorical, filterDupes, parentIds, featureCodes);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy