Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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 org.apache.cxf.jaxrs.ext.search.fiql;
 import java.util.List;
 import java.util.Map;
 
Parses FIQL expression to construct org.apache.cxf.jaxrs.ext.search.SearchCondition structure. Since this class operates on Java type T, not on XML structures "selectors" part of specification is not applicable; instead selectors describes getters of type T used as search condition type (see org.apache.cxf.jaxrs.ext.search.SimpleSearchCondition.isMet(java.lang.Object) for details.

Parameters:
<T> type of search condition.
 
 public class FiqlParser<T> extends AbstractSearchConditionParser<T> {
 
     public static final String OR = ",";
     public static final String AND = ";";
 
     public static final String GT = "=gt=";
     public static final String GE = "=ge=";
     public static final String LT = "=lt=";
     public static final String LE = "=le=";
     public static final String EQ = "==";
     public static final String NEQ = "!=";
     
     public static final Map<ConditionTypeStringCONDITION_MAP;
         
     
     public static final String SUPPORT_SINGLE_EQUALS = "fiql.support.single.equals.operator";       
     public static final String EXTENSION_COUNT = "count";
     protected static final String EXTENSION_COUNT_OPEN =  + "(";
     
     private static final Map<StringConditionTypeOPERATORS_MAP;
     private static final Pattern COMPARATORS_PATTERN;
     private static final Pattern COMPARATORS_PATTERN_SINGLE_EQUALS;
     
     static {
         // operatorsMap
          = new HashMap<StringConditionType>();
         .put(.);
         
          = new HashMap<ConditionTypeString>();
         .put(.);
         
         
         // pattern
         String comparators =  + "|" +  + "|" +  + "|" +  + "|" +  + "|" + ;
         String s1 = "[\\p{ASCII}]+(" + comparators + ")";
          = Pattern.compile(s1);
         
         String s2 = "[\\p{ASCII}]+(" + comparators + "|" + "=" + ")";
          = Pattern.compile(s2);
     }
 
    private Pattern comparatorsPattern = ;
    
Creates FIQL parser.

Parameters:
tclass - class of T used to create condition objects in built syntax tree. Class T must have accessible no-arg constructor and complementary setters to these used in FIQL expressions.
    public FiqlParser(Class<T> tclass) {
        this(tclass, Collections.<StringString>emptyMap());
    }
    
    
Creates FIQL parser.

Parameters:
tclass - class of T used to create condition objects in built syntax tree. Class T must have accessible no-arg constructor and complementary setters to these used in FIQL expressions.
contextProperties
    public FiqlParser(Class<T> tclassMap<StringStringcontextProperties) {
        this(tclasscontextPropertiesnull);
    }
    
    
Creates FIQL parser.

Parameters:
tclass - class of T used to create condition objects in built syntax tree. Class T must have accessible no-arg constructor and complementary setters to these used in FIQL expressions.
contextProperties
    public FiqlParser(Class<T> tclass
                      Map<StringStringcontextProperties,
                      Map<StringStringbeanProperties) {
        super(tclasscontextPropertiesbeanProperties);
        
        if (MessageUtils.isTrue(this..get())) {
             = new HashMap<StringConditionType>();
            .put("=".);
        }
    }
    
    
Parses expression and builds search filter. Names used in FIQL expression are names of getters/setters in type T.

Example:

 class Condition {
   public String getFoo() {...}
   public void setFoo(String foo) {...}
   public int getBar() {...}
   public void setBar(int bar) {...}
 }
 
 FiqlParser<Condition> parser = new FiqlParser<Condition>(Condition.class);
 parser.parse("foo==mystery*;bar=ge=10");
 

Parameters:
fiqlExpression expression of filter.
Returns:
tree of org.apache.cxf.jaxrs.ext.search.SearchCondition objects representing runtime search structure.
Throws:
org.apache.cxf.jaxrs.ext.search.SearchParseException when expression does not follow FIQL grammar
    public SearchCondition<T> parse(String fiqlExpressionthrows SearchParseException {
        ASTNode<T> ast = parseAndsOrsBrackets(fiqlExpression);
        return ast.build();
    }
    private ASTNode<T> parseAndsOrsBrackets(String exprthrows SearchParseException {
        List<Stringsubexpressions = new ArrayList<String>();
        List<Stringoperators = new ArrayList<String>();
        int level = 0;
        int lastIdx = 0;
        int idx = 0;
        for (idx = 0; idx < expr.length(); idx++) {
            char c = expr.charAt(idx);
            if (c == '(') {
                level++;
            } else if (c == ')') {
                level--;
                if (level < 0) {
                    throw new SearchParseException(String.format("Unexpected closing bracket at position %d",
                                                               idx));
                }
            }
            String cs = Character.toString(c);
            boolean isOperator = .equals(cs) || .equals(cs);
            if (level == 0 && isOperator) {
                String s1 = expr.substring(lastIdxidx);
                String s2 = expr.substring(idxidx + 1);
                subexpressions.add(s1);
                operators.add(s2);
                lastIdx = idx + 1;
            }
            boolean isEnd = idx == expr.length() - 1;
            if (isEnd) {
                String s1 = expr.substring(lastIdxidx + 1);
                subexpressions.add(s1);
                operators.add(null);
                lastIdx = idx + 1;
            }
        }
        if (level != 0) {
            throw new SearchParseException(String
                .format("Unmatched opening and closing brackets in expression: %s"expr));
        }
        if (operators.get(operators.size() - 1) != null) {
            String op = operators.get(operators.size() - 1);
            String ex = subexpressions.get(subexpressions.size() - 1);
            throw new SearchParseException("Dangling operator at the end of expression: ..." + ex + op);
        }
        // looking for adjacent ANDs then group them into ORs
        // Note: in case not ANDs is found (e.g only ORs) every single subexpression is
        // treated as "single item group of ANDs"
        int from = 0;
        int to = 0;
        SubExpression ors = new SubExpression();
        while (to < operators.size()) {
            while (to < operators.size() && .equals(operators.get(to))) {
                to++;
            }
            SubExpression ands = new SubExpression();
            for (; from <= tofrom++) {
                String subex = subexpressions.get(from);
                ASTNode<T> node = null;
                if (subex.startsWith("(")) {
                    node = parseAndsOrsBrackets(subex.substring(1, subex.length() - 1));
                } else {
                    node = parseComparison(subex);
                }
                if (node != null) {
                    ands.add(node);
                }
            }
            to = from;
            if (ands.getSubnodes().size() == 1) {
                ors.add(ands.getSubnodes().get(0));
            } else {
                ors.add(ands);
            }
        }
        if (ors.getSubnodes().size() == 1) {
            return ors.getSubnodes().get(0);
        } else {
            return ors;
        }
    }
    private Comparison parseComparison(String exprthrows SearchParseException {
        Matcher m = .matcher(expr);
        if (m.find()) {
            String propertyName = expr.substring(0, m.start(1));
            String operator = m.group(1);
            String value = expr.substring(m.end(1));
            if ("".equals(value)) {
                throw new SearchParseException("Not a comparison expression: " + expr);
            }
            
            String name = unwrapSetter(propertyName);
        
            name = getActualSetterName(name);
            TypeInfoObject castedValue = parseType(propertyNamenamevalue);
            if (castedValue != null) {
                return new Comparison(nameoperatorcastedValue);
            } else {
                return null;
            }
        } else {
            throw new SearchParseException("Not a comparison expression: " + expr);
        }
    }
    
    private TypeInfoObject parseType(String originalNameString setterString valuethrows SearchParseException {
        TypeInfo typeInfo = getTypeInfo(settervalue);
        if (isDecodeQueryValues()) {
            value = UrlUtils.urlDecode(value);
        }
        Object object = parseType(originalNamenullnullsettertypeInfovalue);
        return new TypeInfoObject(objecttypeInfo);
    }
    
    protected boolean isCount(String propName) {
        return propName.startsWith();
    }
    
    
    private String unwrapSetter(String setter) {
        if (setter.startsWith() && setter.endsWith(")")) {
            return setter.substring(.length(), setter.length() - 1);        
        } else {
            return setter;
        }
    }
    
    // node of abstract syntax tree
    private interface ASTNode<T> {
        SearchCondition<T> build() throws SearchParseException;
    }
    private class SubExpression implements ASTNode<T> {
        private String operator;
        private List<ASTNode<T>> subnodes = new ArrayList<ASTNode<T>>();
        public SubExpression(String operator) {
            this. = operator;
        }
        public void add(ASTNode<T> node) {
            .add(node);
        }
        public List<ASTNode<T>> getSubnodes() {
            return Collections.unmodifiableList();
        }
        @Override
        public String toString() {
            String s = .equals() ? "AND" : "OR";
            StringBuilder builder = new StringBuilder(s);
            builder.append(":[");
            for (int i = 0; i < .size(); i++) {
                builder.append(.get(i));
                if (i < .size() - 1) {
                    builder.append(", ");
                }
            }
            builder.append("]");
            return builder.toString();
        }
        public SearchCondition<T> build() throws SearchParseException {
            List<SearchCondition<T>> scNodes = new ArrayList<SearchCondition<T>>();
            for (ASTNode<T> node : ) {
                scNodes.add(node.build());
            }
            if (.equals()) {
                return new OrSearchCondition<T>(scNodes);
            } else {
                return new AndSearchCondition<T>(scNodes);
            }
            
        }
    }
    private class Comparison implements ASTNode<T> {
        private String name;
        private String operator;
        private TypeInfoObject tvalue;
        public Comparison(String nameString operatorTypeInfoObject value) {
            this. = name;
            this. = operator;
            this. = value;
        }
        @Override
        public String toString() {
            return  + " " +  + " " + .getObject() 
                + " (" + .getObject().getClass().getSimpleName() + ")";
        }
        public SearchCondition<T> build() throws SearchParseException {
            String templateName = getSetter();
            T cond = createTemplate(templateName);
            ConditionType ct = .get();
            
            if (isPrimitive(cond)) {
                return new SimpleSearchCondition<T>(ctcond); 
            } else {
                String templateNameLCase = templateName.toLowerCase();
                return new SimpleSearchCondition<T>(Collections.singletonMap(templateNameLCasect),
                                                    Collections.singletonMap(templateNameLCase),
                                                    Collections.singletonMap(templateNameLCase.getTypeInfo()),
                                                    cond);
            }
        }
        private boolean isPrimitive(T pojo) {
            return pojo.getClass().getName().startsWith("java.lang");
        }
        
        @SuppressWarnings("unchecked")
        private T createTemplate(String setterthrows SearchParseException {
            try {
                if ( != null) {
                    .instantiate().setValue(setter.getObject());
                    return .getBean();
                } else {
                    SearchBean bean = (SearchBean).newInstance();
                    bean.set(setter.getObject().toString());
                    return (T)bean;
                }
            } catch (Throwable e) {
                throw new SearchParseException(e);
            }
        }
    }
    
    static class TypeInfoObject {
        private Object object;
        private TypeInfo typeInfo;
        
        public TypeInfoObject(Object objectTypeInfo typeInfo) {
            this. = object;
            this. = typeInfo;
        }
        public TypeInfo getTypeInfo() {
            return ;
        }
        public Object getObject() {
            return ;
        }
                
    }
New to GrepCode? Check out our FAQ X