org.fracturedatlas.athena.search.AthenaSearch.java Source code

Java tutorial

Introduction

Here is the source code for org.fracturedatlas.athena.search.AthenaSearch.java

Source

/*
    
ATHENA Project: Management Tools for the Cultural Sector
Copyright (C) 2010, Fractured Atlas
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/
    
 */
package org.fracturedatlas.athena.search;

import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.fracturedatlas.athena.exception.AthenaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AthenaSearch {

    public static final String LIMIT = "_limit";
    public static final String START = "_start";
    public static final String INCLUDE = "_include";
    public static final String QUERY = "_q";
    public static final String ANY_VALUE = ".*";
    Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    ArrayList<AthenaSearchConstraint> asc = new ArrayList<AthenaSearchConstraint>();
    List<String> includes = new ArrayList<String>();
    Map<String, String> searchModifiers = new HashMap<String, String>();

    String type;

    public AthenaSearch() {
        asc = new ArrayList<AthenaSearchConstraint>();
    }

    public void addConstraint(String fieldName, Operator operator, String searchValue) {
        asc.add(new AthenaSearchConstraint(fieldName, operator, searchValue));
    }

    public void addConstraint(String fieldName, Operator operator, Set<String> searchValues) {
        asc.add(new AthenaSearchConstraint(fieldName, operator, searchValues));
    }

    public void addConstraint(AthenaSearchConstraint searchConstraint) {
        asc.add(searchConstraint);
    }

    public List<AthenaSearchConstraint> getConstraints() {
        return asc;
    }

    public void setSearchModifier(String modifierName, String modifierValue) {
        searchModifiers.put(modifierName, modifierValue);
    }

    public String getSearchModifier(String modifierName) {
        return searchModifiers.get(modifierName);
    }

    public Map<String, String> getSearchModifiers() {
        return searchModifiers;
    }

    public Boolean isQuerySearch() {
        return getSearchModifiers().get(QUERY) != null;
    }

    public String getQuery() {
        return getSearchModifier(QUERY);
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    /**
     * Get the limit of this search
     * @return the limit, null if limit has not been set
     */
    public Integer getLimit() {
        return getIntegerModifier(LIMIT);
    }

    public List<String> getIncludes() {
        return includes;
    }

    public void setIncludes(List<String> includes) {
        this.includes = includes;
    }

    /**
     * Get the start of this search
     * @return the start, null if start has not been set
     */
    public Integer getStart() {
        return getIntegerModifier(START);
    }

    private Integer getIntegerModifier(String modifierName) {
        Integer modifierValue = null;
        String stringVal = getSearchModifier(modifierName);
        if (stringVal != null) {
            try {
                modifierValue = Integer.parseInt(stringVal);
            } catch (NumberFormatException ex) {
                logger.info("{} parameter for AthenaSearch was malformed [{}]", modifierName, stringVal);
                logger.info("Continuing with search");
            }
        }

        return modifierValue;
    }

    public static class Builder {
        AthenaSearch search;

        public Builder(AthenaSearchConstraint sc) {
            this.search = new AthenaSearch();
            this.search.addConstraint(sc);
        }

        public Builder() {
            this.search = new AthenaSearch();
        }

        public AthenaSearch build() {
            return search;
        }

        public AthenaSearch.Builder and(AthenaSearchConstraint sc) {
            search.addConstraint(sc);
            return this;
        }

        public AthenaSearch.Builder include(String subType) {
            search.getIncludes().add(subType);
            return this;
        }

        public AthenaSearch.Builder and(String param, Operator operator, String value) {
            search.addConstraint(new AthenaSearchConstraint(param, operator, value));
            return this;
        }

        public AthenaSearch.Builder limit(Integer limit) {
            search.setSearchModifier(AthenaSearch.LIMIT, limit.toString());
            return this;
        }

        public AthenaSearch.Builder query(String searchTerm) {
            search.setSearchModifier(AthenaSearch.QUERY, searchTerm);
            return this;
        }

        public AthenaSearch.Builder start(Integer start) {
            search.setSearchModifier(AthenaSearch.START, start.toString());
            return this;
        }

        public AthenaSearch.Builder type(String type) {
            search.setType(type);
            return this;
        }

    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final AthenaSearch other = (AthenaSearch) obj;
        if (this.asc != other.asc && (this.asc == null || !this.asc.equals(other.asc))) {
            return false;
        }
        if (this.searchModifiers != other.searchModifiers
                && (this.searchModifiers == null || !this.searchModifiers.equals(other.searchModifiers))) {
            return false;
        }
        if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 23 * hash + (this.asc != null ? this.asc.hashCode() : 0);
        hash = 23 * hash + (this.searchModifiers != null ? this.searchModifiers.hashCode() : 0);
        hash = 23 * hash + (this.type != null ? this.type.hashCode() : 0);
        return hash;
    }

    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("type [").append(getType()).append("]\n");

        for (Entry<String, String> entry : searchModifiers.entrySet()) {
            buf.append(entry.getKey()).append(" [").append(getType()).append("]\n");
        }

        for (AthenaSearchConstraint con : getConstraints()) {
            buf.append(con.toString()).append("\n");
        }

        return buf.toString();
    }

    public AthenaSearch(Map<String, List<String>> queryParams) {

        List<String> values = null;
        Operator operator;
        String value;
        Set<String> valueSet = null;
        for (String fieldName : queryParams.keySet()) {
            values = queryParams.get(fieldName);

            if (values == null || values.size() == 0) {
                throw new AthenaException("Found no values for search parameter [" + fieldName + "]");
            }

            for (String operatorPrefixedValue : values) {
                if (StringUtils.isBlank(operatorPrefixedValue)) {
                    throw new AthenaException("Found no values for search parameter [" + fieldName + "]");
                }
                if (fieldName.startsWith("_")) {
                    if (INCLUDE.equals(fieldName)) {
                        getIncludes().add(operatorPrefixedValue);
                    } else {
                        this.setSearchModifier(fieldName, operatorPrefixedValue);
                    }
                } else {
                    int start = 0;

                    if (operatorPrefixedValue.length() < 2) {
                        operator = Operator.EQUALS;
                        value = operatorPrefixedValue;
                    } else {
                        //If the operator isn't found, this defaults to equals
                        operator = Operator.fromType(operatorPrefixedValue.substring(0, 2));
                        start = 2;

                        if (operator == null) {
                            operator = Operator.EQUALS;
                            start = 0;
                        }
                        value = operatorPrefixedValue.substring(start, operatorPrefixedValue.length());
                    }
                    if (StringUtils.isBlank(value)) {
                        throw new AthenaException("Found no values for search parameter [" + fieldName + "]");
                    }

                    valueSet = parseValues(value);
                    this.addConstraint(fieldName, operator, valueSet);
                }
            }
        }
    }

    public static Set<String> parseValues(String valueString) {
        HashSet<String> values = new HashSet<String>();
        valueString = StringUtils.trimToEmpty(valueString);
        valueString = StringUtils.strip(valueString, "()");
        valueString = StringUtils.trimToEmpty(valueString);
        CharacterIterator it = new StringCharacterIterator(valueString);
        boolean inString = false;
        int begin = 0;
        int end = 0;
        int numValues = 0;
        StringBuilder sb = new StringBuilder();
        // Iterate over the characters in the forward direction
        for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
            if (ch == '\"') {
                inString = true;
                ch = it.next();
                sb = new StringBuilder();
                for (; ch != CharacterIterator.DONE; ch = it.next()) {
                    if (ch == '\\') {
                        // skip any " in a string
                        sb.append(ch);
                        ch = it.next();
                    } else if (ch == '\"') {
                        break;
                    }
                    sb.append(ch);
                }
                inString = false;
                values.add(StringUtils.trimToEmpty(sb.toString()));
            } else if (ch == ',') {
                // new value
            } else if (" \t\n\r".indexOf(ch) > -1) {
                //skip whitespace
            } else {
                // not a comma, whitespace or a string start
                sb = new StringBuilder();
                for (; ch != CharacterIterator.DONE; ch = it.next()) {
                    if (ch == ',') {
                        break;
                    }
                    sb.append(ch);
                }
                inString = false;
                values.add(StringUtils.trimToEmpty(sb.toString()));

            }
        }

        return values;
    }

}