/** * Copyright (C) 2016 Pink Summit, LLC (info@pinksummit.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. */ package net.di2e.ecdr.commons.query; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import javax.ws.rs.core.MultivaluedMap; import net.di2e.ecdr.api.query.QueryCriteria; import net.di2e.ecdr.commons.constants.SearchConstants; import net.di2e.ecdr.commons.util.SearchUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.opengis.filter.FilterVisitor; import org.opengis.filter.sort.SortBy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.catalog.operation.Query; import ddf.catalog.source.UnsupportedQueryException; public class CDRQueryImpl implements Query { private static final Logger LOGGER = LoggerFactory.getLogger( CDRQueryImpl.class ); private QueryCriteria queryCriteria = null; private StringBuilder humanReadableQueryBuilder = null; private Collection<String> sources = null; private int count; private String responseFormat; private long timeoutMilliseconds; private boolean isStrictMode = false; private int startIndex; public CDRQueryImpl( QueryCriteria crit, String localSourceId ) throws UnsupportedQueryException { queryCriteria = crit; MultivaluedMap<String, String> queryParameters = queryCriteria.getParameterValues(); humanReadableQueryBuilder = new StringBuilder( StringUtils.defaultString( queryCriteria.getHumanReadableQuery() ) ); populateStrictMode( queryParameters ); appendParameter( SearchConstants.STRICTMODE_PARAMETER, isStrictMode ); populateResponseFormat( queryParameters ); appendParameter( SearchConstants.FORMAT_PARAMETER, responseFormat ); populateStartIndex( queryParameters ); appendParameter( SearchConstants.STARTINDEX_PARAMETER, startIndex ); populateCount( queryParameters ); appendParameter( SearchConstants.COUNT_PARAMETER, count ); populateTimeoutMilliseconds( queryParameters ); appendParameter( SearchConstants.TIMEOUT_PARAMETER, timeoutMilliseconds ); boolean includeStatus = isIncludeStatus( queryParameters ); appendParameter( SearchConstants.STATUS_PARAMETER, includeStatus ); populateSourceList( queryCriteria.getParameterValues() ); if ( CollectionUtils.isNotEmpty( sources ) ) { appendParameter( SearchConstants.SOURCE_PARAMETER, StringUtils.join( sources, ", " ) ); } } protected void appendParameter( String parameter, Object value ) { humanReadableQueryBuilder.append( " " + parameter + "=[" + value + "] " ); } @Override public boolean evaluate( Object object ) { return queryCriteria.getFilter().evaluate( object ); } @Override public Object accept( FilterVisitor visitor, Object extraData ) { return queryCriteria.getFilter().accept( visitor, extraData ); } @Override public int getPageSize() { return count; } @Override public SortBy getSortBy() { return queryCriteria.getSortBy(); } @Override public int getStartIndex() { return startIndex; } @Override public long getTimeoutMillis() { return timeoutMilliseconds; } @Override public boolean requestsTotalResultsCount() { return true; } public boolean getStrictMode() { return isStrictMode; } public String getResponseFormat() { return responseFormat; } public String getHumanReadableQuery() { return humanReadableQueryBuilder.toString(); } public Collection<String> getSiteNames() { return sources; } protected void populateSourceList( MultivaluedMap<String, String> queryParameters ) { sources = new ArrayList<String>(); String sourceString = queryParameters.getFirst( SearchConstants.SOURCE_PARAMETER ); if ( sourceString != null && !sourceString.isEmpty() ) { String[] sourceArray = sourceString.split( "," ); sources = Arrays.asList( sourceArray ); } } protected void populateTimeoutMilliseconds( MultivaluedMap<String, String> queryParameters ) throws UnsupportedQueryException { String timeout = queryParameters.getFirst( SearchConstants.TIMEOUT_PARAMETER ); timeoutMilliseconds = queryCriteria.getQueryConfiguration().getDefaultTimeoutMillis(); LOGGER.debug( "Attempting to set 'timeout' value from request [" + timeout + "] to long" ); if ( StringUtils.isNotBlank( timeout ) ) { try { timeoutMilliseconds = Long.parseLong( timeout ); if ( timeoutMilliseconds <= 0 ) { throw new UnsupportedQueryException( "The [" + SearchConstants.TIMEOUT_PARAMETER + "] parameter cannot nbe less than 0 and was [" + timeout + "]" ); } } catch ( NumberFormatException e ) { String message = "Invalid Number found for 'timeout' [" + timeout + "]. Resulted in exception: " + e.getMessage(); LOGGER.warn( message ); if ( isStrictMode ) { throw new UnsupportedQueryException( message ); } } } else { LOGGER.debug( "'timeout' parameter was not specified, defaulting value to [{}]", timeout ); } } protected void populateResponseFormat( MultivaluedMap<String, String> queryParameters ) { String format = queryParameters.getFirst( SearchConstants.FORMAT_PARAMETER ); responseFormat = StringUtils.defaultIfBlank( format, queryCriteria.getQueryConfiguration().getDefaultResponseFormat() ); } protected void populateStartIndex( MultivaluedMap<String, String> queryParameters ) throws UnsupportedQueryException { String indexString = queryParameters.getFirst( SearchConstants.STARTINDEX_PARAMETER ); int index = 1; LOGGER.debug( "Attempting to set 'startIndex' value from request [{}] to int", indexString ); if ( StringUtils.isNotBlank( indexString ) ) { try { index = Integer.parseInt( indexString ); } catch ( NumberFormatException e ) { String message = "Invalid Number found for 'startIndex' [" + indexString + "]. Resulted in exception: " + e.getMessage(); LOGGER.warn( message ); throw new UnsupportedQueryException( message ); } } else { LOGGER.debug( "'startIndex' parameter was not specified, defaulting value to [{}]", index ); } startIndex = index < 1 ? 1 : index; } protected void populateCount( MultivaluedMap<String, String> queryParameters ) throws UnsupportedQueryException { String stringCount = queryParameters.getFirst( SearchConstants.COUNT_PARAMETER ); count = queryCriteria.getQueryConfiguration().getDefaultCount(); LOGGER.debug( "Attempting to set 'count' value from request [{}] to int", stringCount ); if ( StringUtils.isNotBlank( stringCount ) ) { try { count = Integer.parseInt( stringCount ); if ( count <= 0 ) { throw new UnsupportedQueryException( "The [" + SearchConstants.COUNT_PARAMETER + "] parameter cannot be less than 0 and was [" + stringCount + "]" ); } } catch ( NumberFormatException e ) { String message = "Invalid Number found for 'count' [" + stringCount + "]. Resulted in exception: " + e.getMessage(); LOGGER.warn( message ); throw new UnsupportedQueryException( message ); } } else { LOGGER.debug( "'count' parameter was not specified, defaulting value to [{}]", count ); } } protected void populateStrictMode( MultivaluedMap<String, String> queryParameters ) { isStrictMode = BooleanUtils.toBooleanDefaultIfNull( SearchUtils.getBoolean( queryParameters.getFirst( SearchConstants.STRICTMODE_PARAMETER ) ), false ); } protected boolean isIncludeStatus( MultivaluedMap<String, String> queryParameters ) { // Include status is true unless explicitly set to false return BooleanUtils.toBooleanDefaultIfNull( SearchUtils.getBoolean( queryParameters.getFirst( SearchConstants.STATUS_PARAMETER ) ), true ); } }