package org.orienteer.core.component.table.filter.sql; import com.github.raymanrt.orientqb.query.Query; import com.google.common.collect.Maps; import com.orientechnologies.orient.core.db.ODatabase; import com.orientechnologies.orient.core.db.document.ODatabaseDocument; import com.orientechnologies.orient.core.metadata.schema.OProperty; import com.orientechnologies.orient.core.metadata.schema.OType; import org.apache.wicket.model.IModel; import org.apache.wicket.util.lang.Args; import ru.ydn.wicket.wicketorientdb.filter.IQueryBuilder; import ru.ydn.wicket.wicketorientdb.model.OQueryModel; import ru.ydn.wicket.wicketorientdb.utils.DBClosure; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Map; import static com.github.raymanrt.orientqb.query.Projection.projection; /** * @author Vitaliy Gonchar * @param <K> The provider object type */ public class ODefaultQueryBuilder<K> implements IQueryBuilder<K> { private final String className; public ODefaultQueryBuilder(String className) { Args.notNull(className, "className"); Args.notEmpty(className, "className"); this.className = className; } public OQueryModel<K> build(Map<IModel<OProperty>, IModel<?>> filteredValues) { String sql = "select from " + className; if (needGenerateNewSql(filteredValues.values())) { sql = generateSql(filteredValues); } return new OQueryModel<K>(sql); } @SuppressWarnings("unchecked") private String generateSql(Map<IModel<OProperty>, IModel<?>> filteredValues) { Query query = new Query().from(className); Map<IModel<OProperty>, IModel<?>> fieldsForQuery = getFieldsForQuery(filteredValues); for (IModel<OProperty> propertyModel : fieldsForQuery.keySet()) { OProperty property = propertyModel.getObject(); switch (property.getType()) { case STRING: String expression = getStringExpression((String) fieldsForQuery.get(propertyModel).getObject()); query.where(projection(property.getName()).like(expression)); break; case EMBEDDED: case EMBEDDEDMAP: case EMBEDDEDLIST: break; case LINK: case LINKLIST: case LINKMAP: case LINKBAG: case LINKSET: break; case ANY: case BINARY: case TRANSIENT: case CUSTOM: break; case DATE: case DATETIME: String dateFormat = getDateFormat(property.getType()); SimpleDateFormat df = new SimpleDateFormat(dateFormat); Date date = (Date) fieldsForQuery.get(propertyModel).getObject(); query.where(projection(property.getName()).eq(df.format(date))); break; default: Object object = fieldsForQuery.get(propertyModel).getObject(); query.where(projection(property.getName()).eq(object)); } } return query.toString(); } private Map<IModel<OProperty>, IModel<?>> getFieldsForQuery(Map<IModel<OProperty>, IModel<?>> filteredValues) { Map<IModel<OProperty>, IModel<?>> result = Maps.newHashMap(); for (IModel<OProperty> propertyModel : filteredValues.keySet()) { IModel<?> valueModel = filteredValues.get(propertyModel); if (valueModel.getObject() != null) { result.put(propertyModel, valueModel); } } return result; } private boolean needGenerateNewSql(Collection<IModel<?>> values) { for (IModel<?> model : values) { if (model != null) { return true; } } return false; } private String getStringExpression(String value) { return value.contains("%") ? value : value + "%"; } private String getDateFormat(final OType type) { return new DBClosure<String>() { @Override protected String execute(ODatabaseDocument db) { String format = null; if (type == OType.DATE) { format = (String) db.get(ODatabase.ATTRIBUTES.DATEFORMAT); } else if (type == OType.DATETIME) { format = (String) db.get(ODatabase.ATTRIBUTES.DATETIMEFORMAT); } return format; } }.execute(); } }