Skip to content
Permalink
Browse files
[CXF-5430] Support for cases when the bean and search properties name…
…s differ

git-svn-id: https://svn.apache.org/repos/asf/cxf/trunk@1567194 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Sergey Beryozkin committed Feb 11, 2014
1 parent 4b48fab commit 39d89d0ed0ac3fbdcf5ec845a48028b8b8790557
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 47 deletions.
@@ -34,21 +34,52 @@
import org.apache.cxf.jaxrs.ext.search.collections.CollectionCheck;
import org.apache.cxf.jaxrs.ext.search.collections.CollectionCheckInfo;
import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.message.MessageUtils;

public abstract class AbstractSearchConditionParser<T> implements SearchConditionParser<T> {


protected final Map<String, String> contextProperties;
protected final Class<T> conditionClass;
protected Beanspector<T> beanspector;
protected Map<String, String> beanPropertiesMap;


protected AbstractSearchConditionParser(Class<T> tclass) {
this(tclass, Collections.<String, String>emptyMap());
this(tclass, Collections.<String, String>emptyMap(), null);
}

protected AbstractSearchConditionParser(Class<T> tclass, Map<String, String> contextProperties) {
protected AbstractSearchConditionParser(Class<T> tclass,
Map<String, String> contextProperties,
Map<String, String> beanProperties) {
this.conditionClass = tclass;
this.contextProperties = contextProperties == null
? Collections.<String, String>emptyMap() : contextProperties;
beanspector = SearchBean.class.isAssignableFrom(tclass) ? null : new Beanspector<T>(tclass);
this.beanPropertiesMap = beanProperties;
}

protected String getActualSetterName(String setter) {
String beanPropertyName = beanPropertiesMap == null ? null : beanPropertiesMap.get(setter);
return beanPropertyName != null ? beanPropertyName : setter;
}

protected TypeInfo getTypeInfo(String setter, String value)
throws SearchParseException, PropertyNotFoundException {

String name = getSetter(setter);

TypeInfo typeInfo = null;
try {
typeInfo = beanspector != null ? beanspector.getAccessorTypeInfo(name)
: new TypeInfo(String.class, String.class);
} catch (Exception e) {
// continue
}
if (typeInfo == null && !MessageUtils.isTrue(contextProperties.get(SearchUtils.LAX_PROPERTY_MATCH))) {
throw new PropertyNotFoundException(name, value);
}
return typeInfo;
}

protected String getSetter(String setter) {
@@ -27,15 +27,12 @@

import org.apache.cxf.jaxrs.ext.search.AbstractSearchConditionParser;
import org.apache.cxf.jaxrs.ext.search.AndSearchCondition;
import org.apache.cxf.jaxrs.ext.search.Beanspector;
import org.apache.cxf.jaxrs.ext.search.Beanspector.TypeInfo;
import org.apache.cxf.jaxrs.ext.search.ConditionType;
import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
import org.apache.cxf.jaxrs.ext.search.PropertyNotFoundException;
import org.apache.cxf.jaxrs.ext.search.SearchBean;
import org.apache.cxf.jaxrs.ext.search.SearchCondition;
import org.apache.cxf.jaxrs.ext.search.SearchParseException;
import org.apache.cxf.jaxrs.ext.search.SearchUtils;
import org.apache.cxf.jaxrs.ext.search.SimpleSearchCondition;
import org.apache.cxf.message.MessageUtils;

@@ -99,9 +96,6 @@
COMPARATORS_PATTERN_SINGLE_EQUALS = Pattern.compile(s2);
}

private Beanspector<T> beanspector;
private Map<String, String> beanPropertiesMap;

private Map<String, ConditionType> operatorsMap = OPERATORS_MAP;
private Pattern comparatorsPattern = COMPARATORS_PATTERN;
/**
@@ -135,12 +129,8 @@ public FiqlParser(Class<T> tclass, Map<String, String> contextProperties) {
public FiqlParser(Class<T> tclass,
Map<String, String> contextProperties,
Map<String, String> beanProperties) {
super(tclass, contextProperties);

beanspector = SearchBean.class.isAssignableFrom(tclass)
? null : new Beanspector<T>(tclass);
super(tclass, contextProperties, beanProperties);

this.beanPropertiesMap = beanProperties;
if (MessageUtils.isTrue(this.contextProperties.get(SUPPORT_SINGLE_EQUALS))) {
operatorsMap = new HashMap<String, ConditionType>(operatorsMap);
operatorsMap.put("=", ConditionType.EQUALS);
@@ -172,7 +162,6 @@ public FiqlParser(Class<T> tclass,
*/
public SearchCondition<T> parse(String fiqlExpression) throws SearchParseException {
ASTNode<T> ast = parseAndsOrsBrackets(fiqlExpression);
// System.out.println(ast);
return ast.build();
}

@@ -267,18 +256,13 @@ private Comparison parseComparison(String expr) throws SearchParseException {
}

String name = unwrapSetter(propertyName);
String beanPropertyName = beanPropertiesMap == null ? null : beanPropertiesMap.get(name);
if (beanPropertyName != null) {
name = beanPropertyName;
}


name = getActualSetterName(name);
TypeInfoObject castedValue = parseType(propertyName, name, value);
if (castedValue != null) {
return new Comparison(name, operator, castedValue);
} else if (MessageUtils.isTrue(contextProperties.get(SearchUtils.LAX_PROPERTY_MATCH))) {
return null;
} else {
throw new PropertyNotFoundException(name, value);
return null;
}
} else {
throw new SearchParseException("Not a comparison expression: " + expr);
@@ -287,18 +271,9 @@ private Comparison parseComparison(String expr) throws SearchParseException {


private TypeInfoObject parseType(String originalName, String setter, String value) throws SearchParseException {
String name = getSetter(setter);

try {
TypeInfo typeInfo =
beanspector != null ? beanspector.getAccessorTypeInfo(name)
: new TypeInfo(String.class, String.class);
Object object = parseType(originalName, null, null, setter, typeInfo, value);
return new TypeInfoObject(object, typeInfo);
} catch (Exception e) {
return null;
}

TypeInfo typeInfo = getTypeInfo(setter, value);
Object object = parseType(originalName, null, null, setter, typeInfo, value);
return new TypeInfoObject(object, typeInfo);
}

protected boolean isCount(String propName) {
@@ -19,11 +19,12 @@
package org.apache.cxf.jaxrs.ext.search.odata;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.cxf.jaxrs.ext.search.AbstractSearchConditionParser;
import org.apache.cxf.jaxrs.ext.search.AndSearchCondition;
import org.apache.cxf.jaxrs.ext.search.Beanspector;
import org.apache.cxf.jaxrs.ext.search.Beanspector.TypeInfo;
import org.apache.cxf.jaxrs.ext.search.ConditionType;
import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
@@ -81,11 +82,9 @@ private static class TypedValue {

private class FilterExpressionVisitor implements ExpressionVisitor {
private final T condition;
private final Beanspector< T > beanspector;

FilterExpressionVisitor(final T condition) {
this.condition = condition;
this.beanspector = new Beanspector<T>(condition);
}

@Override
@@ -188,12 +187,9 @@ public Object visitLiteral(LiteralExpression literal, EdmLiteral edmLiteral) {

@Override
public Object visitProperty(PropertyExpression propertyExpression, String uriLiteral, EdmTyped edmProperty) {
try {
final TypeInfo typeInfo = beanspector.getAccessorTypeInfo(uriLiteral);
return new TypedProperty(typeInfo, uriLiteral);
} catch (Exception ex) {
throw new SearchParseException("Failed to get type information from property path: " + uriLiteral, ex);
}
String setter = getActualSetterName(uriLiteral);
final TypeInfo typeInfo = ODataParser.this.getTypeInfo(setter, null);
return new TypedProperty(typeInfo, setter);
}

@Override
@@ -229,14 +225,41 @@ public Object visitOrder(OrderExpression orderExpression, Object filterResult, S
}

/**
* Creates OData 2.0 parser.
* Creates OData parser.
*
* @param conditionClass - class of T used to create condition objects. Class T must have
* accessible no-arguments constructor and complementary setters to these used in
* OData 2.0 $filter expressions.
* OData $filter expressions.
*/
public ODataParser(final Class< T > conditionClass) {
super(conditionClass);
this(conditionClass, Collections.<String, String>emptyMap());
}

/**
* Creates OData parser.
*
* @param 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
* OData $filter expressions.
* @param contextProperties
*/
public ODataParser(Class<T> tclass, Map<String, String> contextProperties) {
this(tclass, contextProperties, null);
}

/**
* Creates OData parser.
*
* @param 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
* OData $filter expressions.
* @param contextProperties
*/
public ODataParser(Class<T> tclass,
Map<String, String> contextProperties,
Map<String, String> beanProperties) {
super(tclass, contextProperties, beanProperties);

this.parser = new FilterParserImpl(null);
}

@@ -18,6 +18,8 @@
*/
package org.apache.cxf.jaxrs.ext.search.odata;

import java.util.Collections;

import org.apache.cxf.jaxrs.ext.search.SearchCondition;
import org.apache.cxf.jaxrs.ext.search.SearchParseException;

@@ -73,7 +75,8 @@ Person withAge(int newAge) {

@Before
public void setUp() {
parser = new ODataParser<Person>(Person.class);
parser = new ODataParser<Person>(Person.class, Collections.<String, String>emptyMap(),
Collections.singletonMap("thename", "FirstName"));
}

@Test
@@ -83,6 +86,13 @@ public void testFilterByFirstNameEqualsValue() throws SearchParseException {
assertFalse(filter.isMet(new Person("Peter", "Bombadil")));
}

@Test
public void testFilterByFirstNameEqualsValueNonMatchingProperty() throws SearchParseException {
SearchCondition< Person > filter = parser.parse("thename eq 'Tom'");
assertTrue(filter.isMet(new Person("Tom", "Bombadil")));
assertFalse(filter.isMet(new Person("Peter", "Bombadil")));
}

@Test
public void testFilterByFirstAndLastNameEqualValue() throws SearchParseException {
SearchCondition< Person > filter = parser.parse("FirstName eq 'Tom' and LastName eq 'Bombadil'");

0 comments on commit 39d89d0

Please sign in to comment.