Author: sergeyb
Date: Thu Mar 25 22:49:26 2010
New Revision: 927626
URL: http://svn.apache.org/viewvc?rev=927626&view=rev
Log:
JAXRS : ensuring search conditions can 'recreate' original queries and
introducing toSQL utility method
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
(with props)
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
(with props)
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
(with props)
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
(with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AndSearchCondition.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/OrSearchCondition.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/FiqlParserTest.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchConditionTest.java
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java?rev=927626&view=auto
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
(added)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
Thu Mar 25 22:49:26 2010
@@ -0,0 +1,90 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class AbstractComplexCondition<T> implements
SearchCondition<T> {
+
+ protected List<SearchCondition<T>> conditions;
+ private ConditionType cType;
+
+ protected AbstractComplexCondition(ConditionType cType) {
+ this.cType = cType;
+ }
+
+ protected AbstractComplexCondition(List<SearchCondition<T>> conditions,
ConditionType cType) {
+ this.conditions = conditions;
+ this.cType = cType;
+ }
+
+ public void setConditions(List<SearchCondition<T>> conditions) {
+ this.conditions = conditions;
+ }
+
+ public List<T> findAll(Collection<T> pojos) {
+ List<T> result = new ArrayList<T>();
+ for (T pojo : pojos) {
+ if (isMet(pojo)) {
+ result.add(pojo);
+ }
+ }
+ return result;
+ }
+
+ public T getCondition() {
+ return null;
+ }
+
+ public ConditionType getConditionType() {
+ return cType;
+ }
+
+ public List<SearchCondition<T>> getSearchConditions() {
+ return Collections.unmodifiableList(conditions);
+ }
+
+ public PrimitiveStatement getStatement() {
+ return null;
+ }
+
+ public String toSQL(String table, String... columns) {
+ StringBuilder sb = new StringBuilder();
+
+ if (table != null) {
+ SearchUtils.startSqlQuery(sb, table, columns);
+ }
+
+ boolean first = true;
+ for (SearchCondition<T> sc : conditions) {
+ if (!first) {
+ sb.append(" " + cType.toString() + " ");
+ } else {
+ first = false;
+ }
+
+ sb.append("(").append(sc.toSQL(null)).append(")");
+ }
+ return sb.toString();
+ }
+
+}
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractComplexCondition.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AndSearchCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AndSearchCondition.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AndSearchCondition.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/AndSearchCondition.java
Thu Mar 25 22:49:26 2010
@@ -18,29 +18,21 @@
*/
package org.apache.cxf.jaxrs.ext.search;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
/**
* Composite 'and' search condition
*/
-public class AndSearchCondition<T> implements SearchCondition<T> {
+public class AndSearchCondition<T> extends AbstractComplexCondition<T> {
- private List<SearchCondition<T>> conditions;
-
public AndSearchCondition() {
-
+ super(ConditionType.AND);
}
public AndSearchCondition(List<SearchCondition<T>> conditions) {
- this.conditions = conditions;
+ super(conditions, ConditionType.AND);
}
- public void setConditions(List<SearchCondition<T>> conditions) {
- this.conditions = conditions;
- }
public boolean isMet(T pojo) {
for (SearchCondition<T> sc : conditions) {
@@ -50,26 +42,5 @@ public class AndSearchCondition<T> imple
}
return true;
}
-
- public T getCondition() {
- return null;
- }
-
- public ConditionType getConditionType() {
- return ConditionType.AND;
- }
-
- public List<SearchCondition<T>> getConditions() {
- return Collections.unmodifiableList(conditions);
- }
-
- public List<T> findAll(Collection<T> pojos) {
- List<T> result = new ArrayList<T>();
- for (T pojo : pojos) {
- if (isMet(pojo)) {
- result.add(pojo);
- }
- }
- return result;
- }
+
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/OrSearchCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/OrSearchCondition.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/OrSearchCondition.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/OrSearchCondition.java
Thu Mar 25 22:49:26 2010
@@ -18,29 +18,21 @@
*/
package org.apache.cxf.jaxrs.ext.search;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
/**
* Composite 'or' search condition
*/
-public class OrSearchCondition<T> implements SearchCondition<T> {
+public class OrSearchCondition<T> extends AbstractComplexCondition<T> {
- private List<SearchCondition<T>> conditions;
-
public OrSearchCondition() {
-
+ super(ConditionType.OR);
}
public OrSearchCondition(List<SearchCondition<T>> conditions) {
- this.conditions = conditions;
+ super(conditions, ConditionType.OR);
}
- public void setConditions(List<SearchCondition<T>> conditions) {
- this.conditions = conditions;
- }
public boolean isMet(T pojo) {
for (SearchCondition<T> sc : conditions) {
@@ -51,26 +43,4 @@ public class OrSearchCondition<T> implem
return false;
}
- public T getCondition() {
- return null;
- }
-
- public ConditionType getConditionType() {
- return ConditionType.OR;
- }
-
- public List<SearchCondition<T>> getConditions() {
- return Collections.unmodifiableList(conditions);
- }
-
- public List<T> findAll(Collection<T> pojos) {
- List<T> result = new ArrayList<T>();
- for (T pojo : pojos) {
- if (isMet(pojo)) {
- result.add(pojo);
- }
- }
- return result;
- }
-
}
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java?rev=927626&view=auto
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
(added)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
Thu Mar 25 22:49:26 2010
@@ -0,0 +1,180 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class PrimitiveSearchCondition<T> implements SearchCondition<T> {
+
+ private String propertyName;
+ private Object propertyValue;
+ private T condition;
+ private ConditionType cType;
+ private Beanspector<T> beanspector;
+
+ public PrimitiveSearchCondition(String propertyName,
+ Object propertyValue,
+ ConditionType ct,
+ T condition) {
+ this.propertyName = propertyName;
+ this.propertyValue = propertyValue;
+ this.condition = condition;
+ this.cType = ct;
+ if (propertyName != null) {
+ this.beanspector = new Beanspector<T>(condition);
+ }
+ }
+
+ public List<T> findAll(Collection<T> pojos) {
+ List<T> result = new ArrayList<T>();
+ for (T pojo : pojos) {
+ if (isMet(pojo)) {
+ result.add(pojo);
+ }
+ }
+ return result;
+ }
+
+ public T getCondition() {
+ return condition;
+ }
+
+ public ConditionType getConditionType() {
+ return cType;
+ }
+
+ public List<SearchCondition<T>> getSearchConditions() {
+ return null;
+ }
+
+ public PrimitiveStatement getStatement() {
+ return new PrimitiveStatement(propertyName, propertyValue, cType);
+ }
+
+ public boolean isMet(T pojo) {
+ if (isPrimitive(pojo)) {
+ return compare(pojo, cType, propertyValue);
+ } else {
+ Object lValue = getValue(propertyName, pojo);
+ return lValue == null ? false : compare(lValue, cType,
propertyValue);
+ }
+ }
+
+ private Object getValue(String getter, T pojo) {
+ try {
+ return beanspector.swap(pojo).getValue(getter);
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ public String toSQL(String table, String... columns) {
+ StringBuilder sb = new StringBuilder();
+
+ if (table != null) {
+ SearchUtils.startSqlQuery(sb, table, columns);
+ }
+
+ String rvalStr = propertyValue.toString();
+ rvalStr = rvalStr.replaceAll("\\*", "%");
+
+
+ sb.append(propertyName).append(" ").append(
+ SearchUtils.conditionTypeToSqlOperator(cType, rvalStr)).append(" ")
+ .append("'").append(rvalStr).append("'");
+ return sb.toString();
+ }
+
+ private boolean isPrimitive(T pojo) {
+ return pojo.getClass().getName().startsWith("java.lang");
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean compare(Object lval, ConditionType cond, Object rval) {
+ boolean compares = true;
+ if (cond == ConditionType.EQUALS || cond == ConditionType.NOT_EQUALS) {
+ if (rval == null) {
+ compares = true;
+ } else if (lval == null) {
+ compares = false;
+ } else {
+ if (lval instanceof String) {
+ compares = textCompare((String)lval, (String)rval);
+ } else {
+ compares = lval.equals(rval);
+ }
+ if (cond == ConditionType.NOT_EQUALS) {
+ compares = !compares;
+ }
+ }
+ } else {
+ if (lval instanceof Comparable && rval instanceof Comparable) {
+ Comparable lcomp = (Comparable)lval;
+ Comparable rcomp = (Comparable)rval;
+ int comp = lcomp.compareTo(rcomp);
+ switch (cond) {
+ case GREATER_THAN:
+ compares = comp > 0;
+ break;
+ case GREATER_OR_EQUALS:
+ compares = comp >= 0;
+ break;
+ case LESS_THAN:
+ compares = comp < 0;
+ break;
+ case LESS_OR_EQUALS:
+ compares = comp <= 0;
+ break;
+ default:
+ String msg = String.format("Condition type %s is not
supported", cond.name());
+ throw new RuntimeException(msg);
+ }
+ }
+ }
+ return compares;
+ }
+
+ private boolean textCompare(String lval, String rval) {
+ // check wild cards
+ boolean starts = false;
+ boolean ends = false;
+ if (rval.charAt(0) == '*') {
+ starts = true;
+ rval = rval.substring(1);
+ }
+ if (rval.charAt(rval.length() - 1) == '*') {
+ ends = true;
+ rval = rval.substring(0, rval.length() - 1);
+ }
+ if (starts || ends) {
+ // wild card tests
+ if (starts && !ends) {
+ return lval.endsWith(rval);
+ } else if (ends && !starts) {
+ return lval.startsWith(rval);
+ } else {
+ return lval.contains(rval);
+ }
+ } else {
+ return lval.equals(rval);
+ }
+ }
+}
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java?rev=927626&view=auto
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
(added)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
Thu Mar 25 22:49:26 2010
@@ -0,0 +1,49 @@
+/**
+ * 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;
+
+/**
+ * Encapsulates a basic search statement such as a = b, i < 5, etc
+ */
+
+public class PrimitiveStatement {
+
+ private String propery;
+ private Object value;
+ private ConditionType condition;
+
+ public PrimitiveStatement(String property, Object value, ConditionType
condition) {
+ this.propery = property;
+ this.value = value;
+ this.condition = condition;
+ }
+
+ public String getPropery() {
+ return propery;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+ public ConditionType getCondition() {
+ return condition;
+ }
+
+
+}
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveStatement.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java
Thu Mar 25 22:49:26 2010
@@ -55,17 +55,27 @@ public interface SearchCondition<T> {
* thus making it simpler to implement isMet(T). In some cases, the code
which is given
* SearchCondition may find it more efficient to directly deal with the
captured state
* for a more efficient lookup of matching data/records as opposed to
calling
- * SearchCondition.isMet for every instance of T it knows about.
+ * SearchCondition.isMet for every instance of T it knows about.
+ *
*
* @return T the captured search criteria, can be null
*/
T getCondition();
+
+
+ /**
+ * Primitive statement such a > b, i < 5, etc
+ * this condition may represent
+ *
+ * @return primitive search statement, can be null
+ */
+ PrimitiveStatement getStatement();
/**
* List of conditions this SearchCondition may represent
* @return list of conditions, can be null
*/
- List<SearchCondition<T>> getConditions();
+ List<SearchCondition<T>> getSearchConditions();
/**
* Type of condition this SearchCondition represents
@@ -73,4 +83,12 @@ public interface SearchCondition<T> {
*/
ConditionType getConditionType();
+ /**
+ * Utility method for converting this condition into an SQL expression
+ * @param table table name
+ * @param columns column names, a wildcard as in 'SELECT * from table'
will be used
+ * if names are not provided
+ * @return SQL expression
+ */
+ String toSQL(String table, String... columns);
}
Added:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java?rev=927626&view=auto
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
(added)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
Thu Mar 25 22:49:26 2010
@@ -0,0 +1,71 @@
+/**
+ * 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;
+
+public final class SearchUtils {
+
+ private SearchUtils() {
+
+ }
+
+ public static void startSqlQuery(StringBuilder sb, String table, String...
columns) {
+ sb.append("SELECT ");
+ if (columns.length > 0) {
+ for (int i = 0; i < columns.length; i++) {
+ sb.append(columns[i]);
+ if (i + 1 < columns.length) {
+ sb.append(",");
+ }
+ }
+ } else {
+ sb.append("*");
+ }
+ sb.append(" FROM ").append(table).append(" WHERE ");
+ }
+
+ public static String conditionTypeToSqlOperator(ConditionType ct, String
value) {
+ // TODO : if we have the same column involved, ex a >= 123 and a <=244
then
+ // we may try to use IN or BETWEEN, depending on the values
+ String op;
+ switch (ct) {
+ case EQUALS:
+ op = value.contains("%") ? "LIKE" : "=";
+ break;
+ case NOT_EQUALS:
+ op = value.contains("%") ? "NOT LIKE" : "<>";
+ break;
+ case GREATER_THAN:
+ op = ">";
+ break;
+ case GREATER_OR_EQUALS:
+ op = ">=";
+ break;
+ case LESS_THAN:
+ op = "<";
+ break;
+ case LESS_OR_EQUALS:
+ op = "<=";
+ break;
+ default:
+ String msg = String.format("Condition type %s is not supported",
ct.name());
+ throw new RuntimeException(msg);
+ }
+ return op;
+ }
+}
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
Thu Mar 25 22:49:26 2010
@@ -20,6 +20,7 @@ package org.apache.cxf.jaxrs.ext.search;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -31,6 +32,7 @@ import java.util.Set;
* {...@link #isMet(Object)} description.
*
* @param <T> type of search condition.
+ *
*/
public class SimpleSearchCondition<T> implements SearchCondition<T> {
@@ -43,12 +45,11 @@ public class SimpleSearchCondition<T> im
supportedTypes.add(ConditionType.LESS_THAN);
supportedTypes.add(ConditionType.LESS_OR_EQUALS);
}
- private ConditionType cType;
+ private ConditionType joiningType = ConditionType.AND;
private T condition;
- private Map<String, ConditionType> getters2operators;
- private Map<String, Object> getters2values;
- private Beanspector<T> beanspector;
-
+
+ private List<SearchCondition<T>> scts;
+
/**
* Creates search condition with same operator (equality, inequality)
applied in all comparison; see
* {...@link #isMet(Object)} for details of comparison.
@@ -66,9 +67,9 @@ public class SimpleSearchCondition<T> im
if (!supportedTypes.contains(cType)) {
throw new IllegalArgumentException("unsupported condition type: "
+ cType.name());
}
- this.cType = cType;
- this.getters2operators = null;
this.condition = condition;
+ scts = createConditions(null, cType);
+
}
/**
@@ -91,14 +92,13 @@ public class SimpleSearchCondition<T> im
+ "not supported for primitive
type "
+
condition.getClass().getName());
}
+ this.condition = condition;
for (ConditionType ct : getters2operators.values()) {
if (!supportedTypes.contains(ct)) {
throw new IllegalArgumentException("unsupported condition
type: " + ct.name());
}
}
- this.cType = null;
- this.getters2operators = getters2operators;
- this.condition = condition;
+ scts = createConditions(getters2operators, null);
}
public T getCondition() {
@@ -111,13 +111,49 @@ public class SimpleSearchCondition<T> im
* When constructor with map is used it returns null.
*/
public ConditionType getConditionType() {
- return cType;
+ if (scts.size() > 1) {
+ return joiningType;
+ } else {
+ return scts.get(0).getStatement().getCondition();
+ }
}
- public List<SearchCondition<T>> getConditions() {
- return null;
+ public List<SearchCondition<T>> getSearchConditions() {
+ if (scts.size() > 1) {
+ return Collections.unmodifiableList(scts);
+ } else {
+ return null;
+ }
}
+ private List<SearchCondition<T>> createConditions(Map<String,
ConditionType> getters2operators,
+ ConditionType
sharedType) {
+ if (isPrimitive(condition)) {
+ return Collections.singletonList(
+ (SearchCondition<T>)new PrimitiveSearchCondition<T>(null,
condition, sharedType, condition));
+ } else {
+ List<SearchCondition<T>> list = new
ArrayList<SearchCondition<T>>();
+ Map<String, Object> get2val = getGettersAndValues();
+
+ for (String getter : get2val.keySet()) {
+ ConditionType ct = getters2operators == null ? sharedType :
getters2operators.get(getter);
+ if (ct == null) {
+ continue;
+ }
+ Object rval = get2val.get(getter);
+ if (rval == null) {
+ continue;
+ }
+ list.add(new PrimitiveSearchCondition<T>(getter, rval, ct,
condition));
+
+ }
+ if (list.isEmpty()) {
+ throw new IllegalStateException("This search condition is
empty and can not be used");
+ }
+ return list;
+ }
+ }
+
/**
* Compares given object against template condition object.
* <p>
@@ -182,28 +218,12 @@ public class SimpleSearchCondition<T> im
* @throws IllegalAccessException when security manager disallows
reflective call of getters.
*/
public boolean isMet(T pojo) {
- if (isPrimitive(pojo)) {
- return compare(pojo, cType, condition);
- } else {
- boolean matches = false;
- Map<String, Object> get2val = getGettersAndValues();
- for (String getter : get2val.keySet()) {
- ConditionType ct = cType;
- if (ct == null) {
- ct = getters2operators.get(getter);
- if (ct == null) {
- continue;
- }
- }
- Object lval = getValue(getter, pojo);
- Object rval = get2val.get(getter);
- matches = compare(lval, ct, rval);
- if (!matches) {
- break;
- }
+ for (SearchCondition<T> sc : scts) {
+ if (!sc.isMet(pojo)) {
+ return false;
}
- return matches;
}
+ return true;
}
/**
@@ -214,20 +234,19 @@ public class SimpleSearchCondition<T> im
* @return template (condition) object getters mapped to their non-null
values
*/
private Map<String, Object> getGettersAndValues() {
- if (getters2values == null) {
- getters2values = new HashMap<String, Object>();
- beanspector = new Beanspector<T>(condition);
- for (String getter : beanspector.getGettersNames()) {
- Object value = getValue(getter, condition);
- getters2values.put(getter, value);
- }
- //we do not need compare class objects
- getters2values.keySet().remove("class");
+
+ Map<String, Object> getters2values = new HashMap<String, Object>();
+ Beanspector<T> beanspector = new Beanspector<T>(condition);
+ for (String getter : beanspector.getGettersNames()) {
+ Object value = getValue(beanspector, getter, condition);
+ getters2values.put(getter, value);
}
+ //we do not need compare class objects
+ getters2values.keySet().remove("class");
return getters2values;
}
- private Object getValue(String getter, T pojo) {
+ private Object getValue(Beanspector<T> beanspector, String getter, T pojo)
{
try {
return beanspector.swap(pojo).getValue(getter);
} catch (Throwable e) {
@@ -239,76 +258,6 @@ public class SimpleSearchCondition<T> im
return pojo.getClass().getName().startsWith("java.lang");
}
- @SuppressWarnings("unchecked")
- private boolean compare(Object lval, ConditionType cond, Object rval) {
- boolean compares = true;
- if (cond == ConditionType.EQUALS || cond == ConditionType.NOT_EQUALS) {
- if (rval == null) {
- compares = true;
- } else if (lval == null) {
- compares = false;
- } else {
- if (lval instanceof String) {
- compares = textCompare((String)lval, (String)rval);
- } else {
- compares = lval.equals(rval);
- }
- if (cond == ConditionType.NOT_EQUALS) {
- compares = !compares;
- }
- }
- } else {
- if (lval instanceof Comparable && rval instanceof Comparable) {
- Comparable lcomp = (Comparable)lval;
- Comparable rcomp = (Comparable)rval;
- int comp = lcomp.compareTo(rcomp);
- switch (cond) {
- case GREATER_THAN:
- compares = comp > 0;
- break;
- case GREATER_OR_EQUALS:
- compares = comp >= 0;
- break;
- case LESS_THAN:
- compares = comp < 0;
- break;
- case LESS_OR_EQUALS:
- compares = comp <= 0;
- break;
- default:
- String msg = String.format("Condition type %s is not
supported", cond.name());
- throw new RuntimeException(msg);
- }
- }
- }
- return compares;
- }
-
- private boolean textCompare(String lval, String rval) {
- // check wild cards
- boolean starts = false;
- boolean ends = false;
- if (rval.charAt(0) == '*') {
- starts = true;
- rval = rval.substring(1);
- }
- if (rval.charAt(rval.length() - 1) == '*') {
- ends = true;
- rval = rval.substring(0, rval.length() - 1);
- }
- if (starts || ends) {
- // wild card tests
- if (starts && !ends) {
- return lval.endsWith(rval);
- } else if (ends && !starts) {
- return lval.startsWith(rval);
- } else {
- return lval.contains(rval);
- }
- } else {
- return lval.equals(rval);
- }
- }
public List<T> findAll(Collection<T> pojos) {
List<T> result = new ArrayList<T>();
@@ -320,4 +269,40 @@ public class SimpleSearchCondition<T> im
return result;
}
+ public String toSQL(String table, String... columns) {
+ if (isPrimitive(condition)) {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+
+ if (table != null) {
+ SearchUtils.startSqlQuery(sb, table, columns);
+ }
+
+ boolean first = true;
+ for (SearchCondition<T> sc : scts) {
+ PrimitiveStatement ps = sc.getStatement();
+ if (ps.getPropery() == null) {
+ continue;
+ }
+ if (!first) {
+ sb.append(" " + joiningType.toString() + " ");
+ } else {
+ first = false;
+ }
+
+ sb.append(sc.toSQL(null));
+ }
+ return sb.toString();
+ }
+
+ public PrimitiveStatement getStatement() {
+ if (scts.size() == 1) {
+ return scts.get(0).getStatement();
+ } else {
+ return null;
+ }
+ }
+
+
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/FiqlParserTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/FiqlParserTest.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/FiqlParserTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/FiqlParserTest.java
Thu Mar 25 22:49:26 2010
@@ -25,13 +25,12 @@ import java.util.Date;
import javax.xml.datatype.DatatypeFactory;
+import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-public class FiqlParserTest {
+public class FiqlParserTest extends Assert {
private FiqlParser<Condition> parser = new
FiqlParser<Condition>(Condition.class);
@Test(expected = FiqlParseException.class)
@@ -155,6 +154,14 @@ public class FiqlParserTest {
assertFalse(filter.isMet(new Condition("ami", 8, null)));
assertFalse(filter.isMet(new Condition("am", 20, null)));
}
+
+ @Test
+ public void testSQL1() throws FiqlParseException {
+ SearchCondition<Condition> filter =
parser.parse("name==ami*;level=gt=10");
+ String sql = filter.toSQL("table");
+ assertTrue("SELECT * FROM table WHERE name LIKE 'ami%' AND level >
'10'".equals(sql)
+ || "SELECT * FROM table WHERE level > '10' AND name LIKE
'ami%'".equals(sql));
+ }
@Test
public void testParseComplex2() throws FiqlParseException {
@@ -165,6 +172,14 @@ public class FiqlParserTest {
}
@Test
+ public void testSQL2() throws FiqlParseException {
+ SearchCondition<Condition> filter =
parser.parse("name==ami*,level=gt=10");
+ String sql = filter.toSQL("table");
+ assertTrue("SELECT * FROM table WHERE (name LIKE 'ami%') OR (level >
'10')".equals(sql)
+ || "SELECT * FROM table WHERE (level > '10') OR (name LIKE
'ami%')".equals(sql));
+ }
+
+ @Test
public void testParseComplex3() throws FiqlParseException {
SearchCondition<Condition> filter =
parser.parse("name==foo*;(name!=*bar,level=gt=10)");
assertTrue(filter.isMet(new Condition("fooooo", 0, null)));
@@ -174,6 +189,16 @@ public class FiqlParserTest {
}
@Test
+ public void testSQL3() throws FiqlParseException {
+ SearchCondition<Condition> filter =
parser.parse("name==foo*;(name!=*bar,level=gt=10)");
+ String sql = filter.toSQL("table");
+ assertTrue(("SELECT * FROM table WHERE (name LIKE 'foo%') AND ((name
NOT LIKE '%bar') "
+ + "OR (level > '10'))").equals(sql)
+ || ("SELECT * FROM table WHERE (name LIKE 'foo%') AND "
+ + "((level > '10') OR (name NOT LIKE
'%bar'))").equals(sql));
+ }
+
+ @Test
public void testParseComplex4() throws FiqlParseException {
SearchCondition<Condition> filter =
parser.parse("name==foo*;name!=*bar,level=gt=10");
assertTrue(filter.isMet(new Condition("zonk", 20, null)));
@@ -181,7 +206,7 @@ public class FiqlParserTest {
assertTrue(filter.isMet(new Condition("foobar", 20, null)));
assertFalse(filter.isMet(new Condition("fooxxxbar", 0, null)));
}
-
+
@Ignore
static class Condition {
private String name;
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchConditionTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchConditionTest.java?rev=927626&r1=927625&r2=927626&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchConditionTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchConditionTest.java
Thu Mar 25 22:49:26 2010
@@ -155,7 +155,7 @@ public class SimpleSearchConditionTest {
@Test
public void testGetConditions() {
- assertEquals(cGt.getConditions(), null);
+ assertEquals(cGt.getSearchConditions(), null);
}
@Test