+++ /dev/null
-/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.northbound.commons.query;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.opendaylight.controller.northbound.commons.query.CompareExpression.OP;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- */
-/*package*/ class QueryImpl<T> implements Query<T> {
- public static final Logger LOGGER = LoggerFactory.getLogger(QueryImpl.class);
- private static final boolean ALLOW_OBJECT_STRING_COMPARE = true;
-
- private final Expression expression;
- private final TypeInfo rootType ;
- /**
- * Set the expression and cache
- * @param type
- * @param expression
- */
- public QueryImpl(Class<T> type, Expression expression) {
- this.expression = expression;
- this.rootType = TypeInfo.createRoot(null, type);
- }
-
- @Override
- public List<T> find(Collection<T> collection) throws QueryException {
- // new arraylist for result
- List<T> result = new ArrayList<T>();
- for (T item : collection) {
- if (match(item, rootType)) {
- result.add(item);
- }
- }
- return result;
- }
-
- @Override
- public int filter(Collection<T> collection) throws QueryException {
- // find items
- List<T> matched = new ArrayList<T>();
- for (T item : collection) {
- if (match(item, rootType)) {
- matched.add(item);
- }
- }
- collection.clear();
- collection.addAll(matched);
- return matched.size();
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public int filter(T rootObject, Class<?> childClass) throws QueryException {
- // retrieve underlying collection
- TypeInfo childType = rootType.getCollectionChild(childClass);
- if (childType == null || !(childType instanceof IteratableTypeInfo)) {
- return 0;
- }
- Collection collection = (Collection)
- childType.getAccessor().getValue(rootObject);
- // get the child type of the collection type
- TypeInfo ti = childType.getCollectionChild(childClass);
- List matched = new ArrayList();
- for (Object item : collection) {
- if (match(item, ti)) {
- matched.add(item);
- }
- }
- collection.clear();
- collection.addAll(matched);
- return matched.size();
- }
-
- private boolean match(final Object object, final TypeInfo rootType)
- throws QueryException {
- return expression.accept(new Visitor () {
- @Override
- public boolean visit(LogicalExpression le) throws QueryException {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Logical exp {}|{}|{}", le.getOperator(), le.getFirst(),
- le.getSecond());
- }
- return (le.getOperator() == LogicalExpression.OP.AND) ?
- le.getFirst().accept(this) && le.getSecond().accept(this) :
- le.getFirst().accept(this) || le.getSecond().accept(this);
- }
-
- @Override
- public boolean visit(CompareExpression ce) throws QueryException {
- boolean result = visitInternal(ce);
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("=== Compare exp {}|{}|{} == {}", ce.getOperator(),
- ce.getSelector(), ce.getArgument(), result);
- }
- return result;
- }
-
- public boolean visitInternal(CompareExpression ce) throws QueryException {
- String[] selector = ce.getSelector().split("\\.");
- if (!rootType.getName().equals(selector[0])) {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Root name mismatch: {} != {}",
- rootType.getName(), selector[0]);
- }
- return false;
- }
- Object value = rootType.retrieve(object, selector, 1);
- if(value == null){ // nothing to compare against
- return false;
- }
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Comparing [{}] {} [{}]", ce.getArgument(),
- ce.getOperator(), value.toString());
- }
- if (value instanceof Collection) {
- Collection<?> collection = (Collection<?>) value;
- if(collection.size() == 0 && ce.getOperator() == OP.NE) {
- // collection doesn't contain query string
- return true;
- }
- // If there are elements iterate
- Iterator<?> it = collection.iterator();
- OP operator = ce.getOperator();
- if (operator == OP.NE) {
- // negate the operator
- operator = OP.EQ;
- }
- while (it.hasNext()) {
- Object item = it.next();
- if (compare(parse(ce.getArgument(), item), item, operator)) {
- // if match found check the operator and return false for NE
- return (ce.getOperator() != OP.NE);
- }
- }
- // return true for NE and false for rest
- return (ce.getOperator() == OP.NE);
- } else {
- return compare(parse(ce.getArgument(), value), value,
- ce.getOperator());
- }
- }
-
- });
- }
-
- private boolean compare(Object valueToMatch, Object actualValue, OP operator) {
- if (valueToMatch == null || actualValue == null) return false;
- if (ALLOW_OBJECT_STRING_COMPARE && (valueToMatch instanceof String)
- && !(actualValue instanceof String)) {
- actualValue = actualValue.toString();
- }
-
- int compareResult = -1;
- if (valueToMatch instanceof Comparable) {
- compareResult = ((Comparable)actualValue).compareTo(valueToMatch);
- } else {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Not a comparable type: {} {}",
- valueToMatch.getClass().getName(),
- actualValue.getClass().getName());
- }
- return false;
- }
- switch(operator) {
- case EQ :
- return compareResult == 0;
- case RE :
- // Regex match,
- if (valueToMatch instanceof String) {
- return Pattern.matches((String)valueToMatch, actualValue.toString());
- } else {
- return compareResult == 0;
- }
- case NE:
- return compareResult != 0;
- case GT :
- return compareResult > 0;
- case GE :
- return compareResult >= 0;
- case LT :
- return compareResult < 0;
- case LE :
- return compareResult <= 0;
- default:
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Unrecognized comparator - {}", operator);
- }
- return false;
- }
- }
- private Object parse(String arg, Object value) {
- if (value == null) return null;
-
- try {
- if (value instanceof String) {
- return arg;
- } else if (value instanceof Byte) {
- return Byte.decode(arg);
- } else if (value instanceof Double) {
- return Double.parseDouble(arg);
- } else if (value instanceof Float) {
- return Float.parseFloat(arg);
- } else if (value instanceof Integer) {
- return Integer.parseInt(arg);
- } else if (value instanceof Long) {
- return Long.parseLong(arg);
- } else if (value instanceof Short) {
- return Short.parseShort(arg);
- }
- } catch (NumberFormatException ignore) {
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Exception parsing {}", arg, value);
- }
- }
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Using string comparision for type - {}",
- value.getClass().getName());
- }
- // Not a number or string. Convert to a string and compare as last resort
- return ALLOW_OBJECT_STRING_COMPARE ? arg.toString() : null;
- }
-
-}