use of siena.QueryFilter in project siena by mandubian.
the class JdbcPersistenceManager method appendSqlWhere.
public <T> void appendSqlWhere(Query<T> query, StringBuilder sql, List<Object> parameters) {
Class<T> clazz = query.getQueriedClass();
JdbcClassInfo info = JdbcClassInfo.getClassInfo(clazz);
List<QueryFilter> filters = query.getFilters();
if (filters.isEmpty()) {
return;
}
sql.append(JdbcDBUtils.WHERE);
boolean first = true;
for (QueryFilter filter : filters) {
if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
QueryFilterSimple qf = (QueryFilterSimple) filter;
String op = qf.operator;
Object value = qf.value;
Field f = qf.field;
if (!first) {
sql.append(JdbcDBUtils.AND);
}
first = false;
String[] columns = ClassInfo.getColumnNames(f, info.tableName);
if ("IN".equals(op)) {
if (!Collection.class.isAssignableFrom(value.getClass()))
throw new SienaException("Collection needed when using IN operator in filter() query");
StringBuilder s = new StringBuilder();
Collection<?> col = (Collection<?>) value;
for (Object object : col) {
// TODO: if object isModel
parameters.add(object);
s.append(",?");
}
sql.append(columns[0] + " IN(" + s.toString().substring(1) + ")");
} else if (ClassInfo.isModel(f.getType())) {
if (!op.equals("=")) {
throw new SienaException("Unsupported operator for relationship: " + op);
}
JdbcClassInfo classInfo = JdbcClassInfo.getClassInfo(f.getType());
int i = 0;
JdbcMappingUtils.checkForeignKeyMapping(classInfo.keys, columns, query.getQueriedClass(), f);
for (Field key : classInfo.keys) {
if (value == null) {
sql.append(columns[i++] + JdbcDBUtils.IS_NULL);
} else {
sql.append(columns[i++] + "=?");
key.setAccessible(true);
Object o;
try {
o = key.get(value);
parameters.add(o);
} catch (Exception e) {
throw new SienaException(e);
}
}
}
} else {
if (value == null && op.equals("=")) {
sql.append(columns[0] + JdbcDBUtils.IS_NULL);
} else if (value == null && op.equals("!=")) {
sql.append(columns[0] + JdbcDBUtils.IS_NOT_NULL);
} else {
sql.append(columns[0] + op + "?");
if (value == null) {
parameters.add(Types.NULL);
} else {
if (value instanceof Date) {
value = Util.translateDate(f, (Date) value);
} else if (value instanceof Enum) {
value = value.toString();
}
parameters.add(value);
}
}
}
} else if (QueryFilterSearch.class.isAssignableFrom(filter.getClass())) {
// TODO MYSQL implementation manages only 1 search in a query
if (query.getSearches().size() > 1) {
throw new SienaRestrictedApiException(DB, "search", "MySQL implementation manages only on single search at a time in a query");
}
// adds querysearch
QueryFilterSearch qf = (QueryFilterSearch) filter;
appendSqlSearch(qf, clazz, info, sql, parameters);
}
}
}
use of siena.QueryFilter in project siena by mandubian.
the class SdbMappingUtils method buildFilterOrder.
public static <T> StringBuilder buildFilterOrder(Query<T> query, StringBuilder q) {
List<QueryFilter> filters = query.getFilters();
Set<Field> filteredFields = new HashSet<Field>();
boolean first = true;
if (!filters.isEmpty()) {
q.append(WHERE);
for (QueryFilter filter : filters) {
if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
QueryFilterSimple qf = (QueryFilterSimple) filter;
Field f = qf.field;
Object value = qf.value;
String op = qf.operator;
// for order verification in case the order is not on a filtered field
filteredFields.add(f);
if (!first) {
q.append(AND);
}
first = false;
String[] columns = ClassInfo.getColumnNames(f);
if ("IN".equals(op)) {
if (!Collection.class.isAssignableFrom(value.getClass()))
throw new SienaException("Collection needed when using IN operator in filter() query");
StringBuilder s = new StringBuilder();
Collection<?> col = (Collection<?>) value;
for (Object object : col) {
// TO BE VERIFIED: SHOULD BE MANAGED by toString!!!
if (object != null) {
s.append("," + SimpleDB.quote(toString(f, object)));
} else {
throw new SienaException("Can't use NULL in collection for IN operator");
}
}
String column = null;
if (ClassInfo.isId(f)) {
column = ITEM_NAME;
} else {
column = ClassInfo.getColumnNames(f)[0];
}
q.append(column + " in(" + s.toString().substring(1) + ")");
} else if (ClassInfo.isModel(f.getType())) {
// TODO could manage other ops here
if (!op.equals("=")) {
throw new SienaException("Unsupported operator for relationship: " + op);
}
ClassInfo relInfo = ClassInfo.getClassInfo(f.getType());
int i = 0;
for (Field key : relInfo.keys) {
if (value == null) {
q.append(columns[i++] + IS_NULL);
} else {
q.append(columns[i++] + op + SimpleDB.quote(objectFieldToString(value, key)));
}
}
} else {
String column = null;
if (ClassInfo.isId(f)) {
column = "itemName()";
if (value == null && op.equals("=")) {
throw new SienaException("SDB filter on @Id field with 'IS NULL' is not possible");
}
} else {
column = ClassInfo.getColumnNames(f)[0];
}
if (value == null && op.equals("=")) {
q.append(column + IS_NULL);
} else if (value == null && op.equals("!=")) {
q.append(column + IS_NOT_NULL);
} else {
q.append(column + op + SimpleDB.quote(toString(f, value)));
}
}
} else if (QueryFilterSearch.class.isAssignableFrom(filter.getClass())) {
Class<T> clazz = query.getQueriedClass();
QueryFilterSearch qf = (QueryFilterSearch) filter;
// throw new SienaException("Search not possible for several fields in SDB: only one field");
try {
// Field field = Util.getField(clazz, qf.fields[0]);
// if(field.isAnnotationPresent(Unindexed.class)){
// throw new SienaException("Cannot search the @Unindexed field "+field.getName());
// }
// cuts match into words
String[] words = qf.match.split("\\s");
// if several words, then only OR operator represented by IN GAE
Pattern pNormal = Pattern.compile("[\\%]*(\\w+)[\\%]*");
if (!first) {
q.append(AND);
}
// forces true
first = true;
q.append(" ( ");
for (String f : qf.fields) {
Field field = Util.getField(clazz, f);
if (!first) {
q.append(OR);
}
first = false;
q.append(" ( ");
String column = null;
if (ClassInfo.isId(field)) {
column = "itemName()";
} else {
column = ClassInfo.getColumnNames(field)[0];
}
first = true;
for (String word : words) {
if (!first) {
q.append(OR);
}
first = false;
if (!pNormal.matcher(word).matches()) {
throw new SienaException("'" + word + "' doesn't match pattern [\\%]*(\\w+)[\\%]*");
}
if (word.contains("%")) {
q.append(column + LIKE + SimpleDB.quote(word));
} else {
q.append(column + EQ + SimpleDB.quote(word));
}
}
q.append(" ) ");
}
q.append(" ) ");
} catch (Exception e) {
throw new SienaException(e);
}
}
}
}
List<QueryOrder> orders = query.getOrders();
if (!orders.isEmpty()) {
QueryOrder last = orders.get(orders.size() - 1);
Field field = last.field;
if (ClassInfo.isId(field)) {
if (!filteredFields.contains(field)) {
if (filters.isEmpty()) {
q.append(WHERE);
} else {
q.append(AND);
}
q.append(ITEM_NAME + IS_NOT_NULL);
}
q.append(ORDER_BY + ITEM_NAME);
} else {
String column = ClassInfo.getColumnNames(field)[0];
if (!filteredFields.contains(field)) {
if (filters.isEmpty()) {
q.append(WHERE);
} else {
q.append(AND);
}
q.append(column + IS_NOT_NULL);
}
q.append(ORDER_BY + column);
}
if (!last.ascending)
q.append(DESC);
}
QueryOptionSdbContext sdbCtx = (QueryOptionSdbContext) query.option(QueryOptionSdbContext.ID);
QueryOptionOffset off = (QueryOptionOffset) query.option(QueryOptionOffset.ID);
if (sdbCtx != null && sdbCtx.realPageSize != 0) {
if (off != null && off.isActive()) {
// if offset is active, adds it to the page size to be sure to retrieve enough elements
q.append(LIMIT + (sdbCtx.realPageSize + off.offset));
} else {
q.append(LIMIT + sdbCtx.realPageSize);
}
}
return q;
}
use of siena.QueryFilter in project siena by mandubian.
the class RemotePersistenceManager method createRequest.
private <T> Document createRequest(Query<T> query) {
Class<?> clazz = query.getQueriedClass();
Document request = createRequest("query");
request.getRootElement().addAttribute("class", clazz.getName());
List<QueryFilter> filters = query.getFilters();
for (QueryFilter filter : filters) {
if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
QueryFilterSimple qf = (QueryFilterSimple) filter;
Field field = qf.field;
Object value = qf.value;
Element filtr = request.getRootElement().addElement("filter");
filtr.addAttribute("field", field.getName());
filtr.addAttribute("operator", qf.operator);
if (ClassInfo.isModel(value.getClass())) {
Common.fillRequestElement((Model) value, filtr, true);
} else {
filtr.setText(Util.toString(field, value));
}
}
}
List<QueryOrder> orders = query.getOrders();
for (QueryOrder order : orders) {
Field field = order.field;
request.getRootElement().addElement("order").addAttribute("field", field.getName()).addAttribute("ascending", Boolean.toString(order.ascending));
}
return request;
}
use of siena.QueryFilter in project siena by mandubian.
the class GaeQueryUtils method addFiltersOrders.
public static <T> com.google.appengine.api.datastore.Query addFiltersOrders(QueryData<T> query, com.google.appengine.api.datastore.Query q, Key parentKey) {
List<QueryFilter> filters = query.getFilters();
for (QueryFilter filter : filters) {
if (QueryFilterSimple.class.isAssignableFrom(filter.getClass())) {
QueryFilterSimple qf = (QueryFilterSimple) filter;
Field f = qf.field;
String propertyName = ClassInfo.getColumnNames(f)[0];
Object value = qf.value;
FilterOperator op = operators.get(qf.operator);
// IN and NOT_EQUAL doesn't allow to use cursors
if (op == FilterOperator.IN || op == FilterOperator.NOT_EQUAL) {
QueryOptionGaeContext gaeCtx = (QueryOptionGaeContext) query.option(QueryOptionGaeContext.ID);
if (gaeCtx == null) {
gaeCtx = new QueryOptionGaeContext();
query.options().put(gaeCtx.type, gaeCtx);
}
gaeCtx.useCursor = false;
query.option(QueryOptionOffset.ID).activate();
}
if (value != null && ClassInfo.isModel(value.getClass())) {
Key key = GaeMappingUtils.getKey(value);
q.addFilter(propertyName, op, key);
} else {
if (ClassInfo.isId(f)) {
Id id = f.getAnnotation(Id.class);
switch(id.value()) {
case NONE:
if (value != null) {
if (!Collection.class.isAssignableFrom(value.getClass())) {
// long or string goes toString
Key key;
if (parentKey == null) {
key = KeyFactory.createKey(q.getKind(), value.toString());
} else {
key = KeyFactory.createKey(parentKey, q.getKind(), value.toString());
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, key);
} else {
List<Key> keys = new ArrayList<Key>();
for (Object val : (Collection<?>) value) {
if (parentKey == null) {
keys.add(KeyFactory.createKey(q.getKind(), val.toString()));
} else {
keys.add(KeyFactory.createKey(parentKey, q.getKind(), val.toString()));
}
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, keys);
}
}
break;
case AUTO_INCREMENT:
if (value != null) {
if (!Collection.class.isAssignableFrom(value.getClass())) {
Key key;
Class<?> type = f.getType();
if (Long.TYPE == type || Long.class.isAssignableFrom(type)) {
if (parentKey == null) {
key = KeyFactory.createKey(q.getKind(), (Long) value);
} else {
key = KeyFactory.createKey(parentKey, q.getKind(), (Long) value);
}
} else {
if (parentKey == null) {
key = KeyFactory.createKey(q.getKind(), value.toString());
} else {
key = KeyFactory.createKey(parentKey, q.getKind(), value.toString());
}
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, key);
} else {
List<Key> keys = new ArrayList<Key>();
for (Object val : (Collection<?>) value) {
if (value instanceof String)
val = Long.parseLong((String) val);
if (parentKey == null) {
keys.add(KeyFactory.createKey(q.getKind(), (Long) val));
} else {
keys.add(KeyFactory.createKey(parentKey, q.getKind(), (Long) val));
}
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, keys);
}
}
break;
case UUID:
if (value != null) {
if (!Collection.class.isAssignableFrom(value.getClass())) {
// long or string goes toString
Key key;
if (parentKey == null) {
key = KeyFactory.createKey(q.getKind(), value.toString());
} else {
key = KeyFactory.createKey(parentKey, q.getKind(), value.toString());
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, key);
} else {
List<Key> keys = new ArrayList<Key>();
for (Object val : (Collection<?>) value) {
keys.add(KeyFactory.createKey(q.getKind(), val.toString()));
}
q.addFilter(Entity.KEY_RESERVED_PROPERTY, op, keys);
}
}
break;
default:
throw new SienaException("Id Generator " + id.value() + " not supported");
}
} else if (Enum.class.isAssignableFrom(f.getType())) {
value = value.toString();
q.addFilter(propertyName, op, value);
} else {
q.addFilter(propertyName, op, value);
}
}
} else if (QueryFilterSearch.class.isAssignableFrom(filter.getClass())) {
Class<T> clazz = query.getQueriedClass();
QueryFilterSearch qf = (QueryFilterSearch) filter;
if (qf.fields.length > 1)
throw new SienaException("Search not possible for several fields in GAE: only one field");
try {
Field field = Util.getField(clazz, qf.fields[0]);
if (field.isAnnotationPresent(Unindexed.class)) {
throw new SienaException("Cannot search the @Unindexed field " + field.getName());
}
// cuts match into words
String[] words = qf.match.split("\\s");
// if several words, then only OR operator represented by IN GAE
Pattern pNormal = Pattern.compile("[^\\*](\\w+)[^\\*]");
if (words.length > 1) {
for (String word : words) {
if (!pNormal.matcher(word).matches()) {
throw new SienaException("Cannot do a multiwords search with the * operator");
}
}
List<String> wordList = new ArrayList<String>();
Collections.addAll(wordList, words);
addSearchFilterIn(q, field, wordList);
} else {
// searches for pattern such as "alpha*" or "*alpha" or "alpha"
Pattern pStart = Pattern.compile("(\\w+)\\*");
String word = words[0];
Matcher matcher = pStart.matcher(word);
if (matcher.matches()) {
String realWord = matcher.group(1);
addSearchFilterBeginsWith(q, field, realWord);
continue;
}
matcher = pNormal.matcher(word);
if (matcher.matches()) {
addSearchFilterEquals(q, field, word);
continue;
}
Pattern pEnd = Pattern.compile("\\*(\\w+)");
matcher = pEnd.matcher(word);
if (matcher.matches()) {
throw new SienaException("Cannot do a \"*word\" search in GAE");
}
}
} catch (Exception e) {
throw new SienaException(e);
}
break;
} else if (QueryFilterEmbedded.class.isAssignableFrom(filter.getClass())) {
QueryFilterEmbedded qf = (QueryFilterEmbedded) filter;
String propName = "";
int sz = qf.fields.size();
for (int i = 0; i < sz; i++) {
propName += ClassInfo.getSingleColumnName(qf.fields.get(i));
if (i < sz - 1) {
propName += qf.fieldSeparator;
}
}
Object value = qf.value;
FilterOperator op = operators.get(qf.operator);
// IN and NOT_EQUAL doesn't allow to use cursors
if (op == FilterOperator.IN || op == FilterOperator.NOT_EQUAL) {
QueryOptionGaeContext gaeCtx = (QueryOptionGaeContext) query.option(QueryOptionGaeContext.ID);
if (gaeCtx == null) {
gaeCtx = new QueryOptionGaeContext();
query.options().put(gaeCtx.type, gaeCtx);
}
gaeCtx.useCursor = false;
query.option(QueryOptionOffset.ID).activate();
}
q.addFilter(propName, op, value);
}
}
// adds filter on owners
List<QueryOwned> ownees = query.getOwnees();
for (QueryOwned ownee : ownees) {
String propertyName = ClassInfo.getSimplestColumnName(ownee.field);
FilterOperator op = operators.get("=");
Key key = GaeMappingUtils.getKey(ownee.owner);
q.addFilter(propertyName, op, key);
}
List<QueryOrder> orders = query.getOrders();
for (QueryOrder order : orders) {
Field f = order.field;
if (ClassInfo.isId(f)) {
q.addSort(Entity.KEY_RESERVED_PROPERTY, order.ascending ? SortDirection.ASCENDING : SortDirection.DESCENDING);
} else {
q.addSort(ClassInfo.getColumnNames(f)[0], order.ascending ? SortDirection.ASCENDING : SortDirection.DESCENDING);
}
}
return q;
}
Aggregations