package foundation.dao; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.json.JSONArray; import foundation.data.meta.field.Field; import foundation.data.meta.field.FieldsRuntime; import foundation.json.JArrayReader; import foundation.json.JSONReader; import foundation.json.JType; import foundation.server.config.DBaseType; import foundation.translator.ITranslator; import foundation.translator.Translator; import foundation.translator.ValueType; import foundation.util.ContentBuilder; import foundation.util.ID; import foundation.util.MapList; import foundation.util.Util; import foundation.variant.provider.DataEvent; import foundation.variant.provider.IVariantsConsumer; import foundation.variant.provider.IVariantsProvider; import foundation.variant.provider.VariantLink; import foundation.variant.provider.VariantProviderType; public class Filter implements IVariantsConsumer, IVariantsProvider, Iterable { public static final Filter All = new Filter(); public static String ProviderName = "filter"; private DBaseType dbaseType; private Set VariantNames; private FieldsRuntime entityMeta; private MapList items; private String rawFilter; private boolean raw = false; private boolean empty; private Set marks; public Filter() { this(DBaseType.getMain()); } public Filter(DBaseType dbaseType) { this.dbaseType = dbaseType; items = new MapList(); VariantNames = new HashSet(); VariantNames.add("filter"); } public Filter(String filter) { this(DBaseType.getMain(), filter); } public Filter(DBaseType dbaseType, String filter) { this.dbaseType = dbaseType; items = new MapList(); VariantNames = new HashSet(); VariantNames.add("filter"); rawFilter = filter; raw = true; } public Filter(String fieldName, String value) { this(); add(fieldName, "=", Util.quotedStr(value)); } public Filter(DBaseType dbaseType, String fieldName, String value) { this(dbaseType); add(fieldName, "=", Util.quotedStr(value)); } public Filter(String fieldName, int value) { this(); add(fieldName, "=", String.valueOf(value)); } public Filter(DBaseType dbaseType, String fieldName, int value) { this(dbaseType); add(fieldName, "=", String.valueOf(value)); } public Filter(String fieldName, Date date) throws Exception { this(DBaseType.getMain(), fieldName, date); } public Filter(DBaseType dbaseType, String fieldName, Date date) throws Exception { this(dbaseType); add(fieldName, "=", Translator.toSqlString(dbaseType, date)); } public Filter(String fieldName, String operator, String value) { this(); add(fieldName, operator, value); } public Filter(DBaseType dbaseType, String fieldName, String operator, String value) throws Exception { this(dbaseType); add(fieldName, operator, value); } public Filter addAll(FieldsRuntime entityMeta, Set excludeNames, IVariantsProvider...valueProviders) throws Exception { this.entityMeta = entityMeta; for (int i = 0; i < valueProviders.length; i++) { IVariantsProvider provider = valueProviders[i]; VariantLink.moveOnConsumer(null, provider, this, excludeNames); } return this; } public Filter addAll(Filter other) { if (other == null) { return this; } for (FilterItem item: other) { items.add(item.getFieldName(), item); } if (other.isRaw()) { this.rawFilter = other.rawFilter; this.raw = other.raw; } return this; } public Filter add(DataReader dataReader) { Object filterObject = dataReader.getValue("filter"); if (filterObject instanceof String) { this.add(String.valueOf(filterObject)); return this; } if (filterObject instanceof JSONArray) { JArrayReader jsonArray = dataReader.getReader("filter", JType.Array); for (JSONReader jsonObject: jsonArray) { this.add(jsonObject.getString("field"), jsonObject.getString("operator"), Util.quotedStr(jsonObject.getString("value"))); } return this; } return this; } public Filter add(String segment) { if (Util.isEmpty(segment)) { return this; } FilterItem item = new FilterItem(segment); items.add(ID.newValue(), item); return this; } public Filter add(String fieldName, String value) { if (value == null) { this.add(fieldName, "is", "null"); return this; } this.add(fieldName, "=", Util.quotedStr(value)); return this; } public Filter add(String fieldName, Object value) { if (value == null) { this.add(fieldName, "is", "null"); return this; } this.add(fieldName, "=", String.valueOf(value)); return this; } public Filter add(String fieldName, String operator, String value) { if (Util.isEmpty(fieldName)) { return this; } if (Util.isEmpty(operator)) { operator = "="; } operator = operator.trim().toLowerCase(); if ("like".equals(operator)) { if (value.indexOf("%") < 0) { value = "%" + value + "%"; } } else if ("in".equals(operator)) { if (value.startsWith("'")) { value = value.substring(1); } if (value.endsWith("'")) { value = value.substring(0, value.length() - 1); } } FilterItem item = new FilterItem(fieldName, operator, value); items.add(fieldName, item); VariantNames.add(fieldName.toLowerCase()); return this; } @Override public void setVariant(DataEvent dataEvent, String name, Object value) throws Exception { if (value == null) { return; } if (entityMeta == null) { throw new Exception("filter entityMeta is null"); } if(!entityMeta.contains(name)) { return; } Field field = entityMeta.get(name); if (field == null) { return; } ITranslator translator = field.getValueTranslator(); ValueType type = field.getType(); if (ValueType.String == type) { String stringValue = value.toString(); String segmentValue = null; //1. like if (stringValue.startsWith("(like)")) { if (stringValue.endsWith("(like)")) { //1.1 all like segmentValue = "'%" + stringValue.substring(7, stringValue.length() - 6) + "%'"; add(name, "like", segmentValue); } else { //1.2 left like segmentValue = "'%" + stringValue.substring(7) + "'"; add(name, "like", segmentValue); } } else if (stringValue.endsWith("(like)")) { //1.3 right like segmentValue = "'" + stringValue.substring(0, stringValue.length() - 6) + "%'"; add(name, "like", segmentValue); } else { //1.3 no like segmentValue = "'" + stringValue + "'"; add(name, "=", segmentValue); } } else { String segmentValue = translator.toSqlString(dbaseType, value); add(name, "=", segmentValue); } } @Override public void setVariants(DataEvent dataEvent, IVariantsProvider... providers) throws Exception { if (providers == null || providers.length == 0) { return; } Set keySet = items.keySet(); for (String key: keySet) { for (IVariantsProvider provider: providers) { if (provider.containsVariant(key)) { FilterItem item = items.get(key); Object value = provider.getVariantValue(dataEvent, key); if (!Util.isEmpty(value)) { item.setValue(String.valueOf(value)); } } } } } @Override public boolean isVariantNull(String name) { return empty; } public FilterItem getItemByName(String name) { if (items == null) { return null; } return items.get(name); } public FilterItem removeItemByName(String name) { if (items == null) { return null; } return items.remove(name); } public boolean isRaw() { return raw; } public String getRawFilter() { return rawFilter; } public boolean isEmpty() { return items.isEmpty() && Util.isEmpty(rawFilter); } public boolean containsSlaveTables(String... tableNames) { String sql = toString(); if (Util.isEmpty(sql) || tableNames == null || tableNames.length == 0) { return false; } sql = sql.toLowerCase(); int max = tableNames.length; for (int i = 0; i < max; i++) { String tableName = tableNames[i]; if (Util.isEmpty(tableName)) { continue; } tableName = tableName.toLowerCase() + "."; if (sql.indexOf(tableName) >= 0) { return true; } } return false; } public synchronized void addMark(Object mark) { if (marks == null) { marks = new HashSet(); } marks.add(mark); } public boolean containsMark(Object mark) { if (marks == null || mark == null) { return false; } return marks.contains(mark); } @Override public String toString() { if (raw) { return rawFilter; } if (items.isEmpty()) { return "1=1"; } ContentBuilder result = new ContentBuilder(" and "); Set keySet = items.keySet(); for (String key : keySet) { FilterItem filterItem = items.get(key); result.append(filterItem.toSQLString()); } if (result.isEmpty()) { result.append(" 1 = 1 "); } return "(" + result + ")"; } @Override public String getProviderName() { return ProviderName; } @Override public VariantProviderType getProviderType() { return VariantProviderType.Transiant; } @Override public boolean containsVariant(String name) { if (name == null) { return false; } return VariantNames.contains(name); } @Override public Object getVariantValue(DataEvent dataEvent, String name) { if ("filter".equalsIgnoreCase(name)) { return toString(); } FilterItem item = items.get(name); if (item == null) { return null; } return item.getValue(); } @Override public Set getVariantNames() { return VariantNames; } @Override public Iterator iterator() { return items.iterator(); } }