package org.ovirt.engine.core.searchbackend; import java.math.BigDecimal; import java.util.Date; import org.ovirt.engine.core.compat.*; import org.ovirt.engine.core.common.businessentities.*; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.interfaces.*; /** * A base class for all condition field auto completers */ public class BaseConditionFieldAutoCompleter extends BaseAutoCompleter implements IConditionFieldAutoCompleter { public static final int DAY_IN_MILLIS = 24 * 60 * 60 * 1000; protected java.util.HashMap<String, java.util.ArrayList<valueValidationFunction>> mValidationDict = null; private java.util.HashMap<String, Class> mTypeDict = null; protected java.util.HashMap<String, String> mColumnNameDict = null; protected java.util.ArrayList<String> mNotFreeTextSearchableFieldsList = new java.util.ArrayList<String>(); public BaseConditionFieldAutoCompleter() { mValidationDict = new java.util.HashMap<String, java.util.ArrayList<valueValidationFunction>>(); mTypeDict = new java.util.HashMap<String, Class>(); mColumnNameDict = new java.util.HashMap<String, String>(); } /** * Gets the LIKE clause syntax for non case-sensitive search * * @return the LIKE syntax according to current DBEngine. */ public static String getLikeSyntax(boolean caseSensitive) { // for tests we don't have the Config class initialized // also if caseSensitive flag is set we will use LIKE if (Config.getConfigUtils() == null || caseSensitive) return "LIKE"; else return Config.<String> GetValue(ConfigValues.DBLikeSyntax); } /** * Gets the I18N prefix used for value compare. * @return */ public static String getI18NPrefix() { // for tests we don't have the Config class initialized if (Config.getConfigUtils() == null) return ""; else return Config.<String> GetValue(ConfigValues.DBI18NPrefix); } public static ITagsHandler TagsHandler; public java.util.HashMap<String, java.lang.Class> getTypeDictionary() { return mTypeDict; } protected void buildBasicValidationTable() { valueValidationFunction charValidation = validCahracters; valueValidationFunction intValidationFunc = validInteger; valueValidationFunction decimalValidationFunction = validDecimal; valueValidationFunction dateValidationFunc = validDateTime; valueValidationFunction timeSpanValidationFunc = validTimeSpan; valueValidationFunction valueValidationFunc = validateFieldValueByValueAC; valueValidationFunction dateEnumValidationFunc = validateDateEnumValueByValueAC; for (String key : mVerbs.keySet()) { java.util.ArrayList<valueValidationFunction> curList = new java.util.ArrayList<valueValidationFunction>(); java.lang.Class curType = mTypeDict.get(key); if (curType == java.math.BigDecimal.class) { curList.add(decimalValidationFunction); } else if (curType == Integer.class) { curList.add(intValidationFunc); } else if (curType == java.util.Date.class) { curList.add(dateValidationFunc); } else if (curType == TimeSpan.class) { curList.add(timeSpanValidationFunc); } else { curList.add(charValidation); } IConditionValueAutoCompleter tmp = getFieldValueAutoCompleter(key); if (tmp != null) { if (tmp.getClass() == DateEnumValueAutoCompleter.class) { curList.add(dateEnumValidationFunc); } else { curList.add(valueValidationFunc); } } mValidationDict.put(key, curList); } } public boolean validateFieldValue(String fieldName, String fieldValue) { if (mValidationDict.containsKey(fieldName)) { java.util.ArrayList<valueValidationFunction> validationList = mValidationDict.get(fieldName); for (valueValidationFunction curValidationFunc : validationList) { if (!curValidationFunc.invoke(fieldName, fieldValue)) { return false; } } } return true; } public String getDbFieldName(String fieldName) { String retval = null; if (mColumnNameDict.containsKey(fieldName)) { retval = mColumnNameDict.get(fieldName); } return retval; } public java.lang.Class getDbFieldType(String fieldName) { java.lang.Class retval = null; if (mTypeDict.containsKey(fieldName)) { retval = mTypeDict.get(fieldName); } return retval; } // FIXME Probably Not Hibernate Friendly public String buildFreeTextConditionSql(String tableName, String relations, String value, boolean caseSensitive) { StringBuilder sb = new StringBuilder(" ( "); boolean firstTime = true; if (!StringHelper.isNullOrEmpty(value) && !StringHelper.EqOp(value, "''")) { value = StringFormat.format(getI18NPrefix() + "'%%%1$s%%'", StringHelper.trim(value, '\'')); } if (StringHelper.EqOp(relations, "=")) { relations = getLikeSyntax(caseSensitive); } else if (StringHelper.EqOp(relations, "!=")) { relations = "NOT " + getLikeSyntax(caseSensitive); } for (String field : mColumnNameDict.keySet()) { if (mTypeDict.get(field) == String.class && !mNotFreeTextSearchableFieldsList.contains(field)) { if (firstTime) { firstTime = false; } else { sb.append(" OR "); } sb.append(StringFormat.format(" %1$s.%2$s %3$s %4$s", tableName, mColumnNameDict.get(field), relations, value)); } } sb.append(" ) "); return sb.toString(); } public valueValidationFunction validCahracters = new valueValidationFunction() { public boolean invoke(String field, String value) { Regex validChar = new Regex("^[^\\<\\>&^#!']*$"); // Regex validChar = new Regex("^[a-zA-Z0-9%-_@:\\*\\. ]*$"); return validChar.IsMatch(value); } }; public valueValidationFunction validDateTime = new valueValidationFunction() { public boolean invoke(String field, String value) { Date test = DateUtils.parse(value); if (test != null) { // For some reason this is the oldest possible time in SQL server Date dbOldestPossibleDate = new Date(Date.parse("01/01/1753 00:00:00")); if (test.compareTo(dbOldestPossibleDate) >= 0) { return true; } } else { // check for enum for (DateEnumForSearch val : DateEnumForSearch.values()) { if (StringHelper.EqOp(value.toUpperCase(), val.name().toUpperCase())) { return true; } } // check for week before for (DayOfWeek day : DayOfWeek.class.getEnumConstants()) { if (StringHelper.EqOp(value.toUpperCase(), day.toString().toUpperCase())) { return true; } } } return false; } }; public valueValidationFunction validTimeSpan = new valueValidationFunction() { public boolean invoke(String field, String value) { TimeSpan test = new TimeSpan(); boolean retval = false; RefObject<TimeSpan> tempRefObject = new RefObject<TimeSpan>(test); boolean tempVar = TimeSpan.TryParse(value, tempRefObject); test = tempRefObject.argvalue; if (tempVar) { retval = true; } return retval; } }; public valueValidationFunction validInteger = new valueValidationFunction() { public boolean invoke(String field, String value) { Integer test = new Integer(0); boolean retval = false; RefObject<Integer> tempRefObject = new RefObject<Integer>(test); boolean tempVar = IntegerCompat.TryParse(value, tempRefObject); test = tempRefObject.argvalue; if (tempVar) { retval = true; } return retval; } }; public valueValidationFunction validDecimal = new valueValidationFunction() { public boolean invoke(String field, String value) { BigDecimal test = new BigDecimal(0); boolean retval = false; RefObject<java.math.BigDecimal> tempRefObject = new RefObject<java.math.BigDecimal>(test); boolean tempVar = DoubleCompat.TryParse(value, tempRefObject); test = tempRefObject.argvalue; if (tempVar) { retval = true; } return retval; } }; public valueValidationFunction validateDateEnumValueByValueAC = new valueValidationFunction() { public boolean invoke(String field, String value) { boolean retval = true; IConditionValueAutoCompleter vlaueAc = getFieldValueAutoCompleter(field); if (vlaueAc != null) // check if this enum first { retval = vlaueAc.validate(value); } if (!retval) // check for week before { for (DayOfWeek day : DayOfWeek.values()) { if (StringHelper.EqOp(value.toUpperCase(), day.toString().toUpperCase())) // Enum.GetName(typeof(DayOfWeek), // day).ToUpper() { return true; } } } if (!retval) // check for free date { retval = DateUtils.parse(StringHelper.trim(value, '\'')) != null; } return retval; } }; public valueValidationFunction validateFieldValueByValueAC = new valueValidationFunction() { public boolean invoke(String field, String value) { boolean retval = true; IConditionValueAutoCompleter vlaueAc = getFieldValueAutoCompleter(field); if (vlaueAc != null) { retval = vlaueAc.validate(value); } return retval; } }; public IAutoCompleter getFieldRelationshipAutoCompleter(String fieldName) { return null; } public IConditionValueAutoCompleter getFieldValueAutoCompleter(String fieldName) { return null; } public void formatValue(String fieldName, RefObject<String> relations, RefObject<String> value, boolean caseSensitive) { if (fieldName == null) { return; } if (fieldName.equals("TIME") || fieldName.equals("CREATIONDATE")) { Date temp = DateUtils.parse(StringHelper.trim(value.argvalue, '\'')); DateTime result; if (temp == null) { result = DealWithDateEnum(value.argvalue); } else { result = new DateTime(temp); } if (relations.argvalue != null && relations.argvalue.equals("=")) { relations.argvalue = "between"; DateTime nextDay = result.AddDays(1); value.argvalue = StringFormat.format("'%1$s' and '%2$s'", result.toString(DateUtils.getFormat(DateFormatCompat.DEFAULT, DateFormatCompat.SHORT)), nextDay.toString(DateUtils.getFormat(DateFormatCompat.DEFAULT, DateFormatCompat.SHORT))); } else { // ">" or "<" // value.argvalue = String.format("'%1$s'", result); value.argvalue = StringFormat.format("'%1$s'", result.toString(DateUtils.getFormat(DateFormatCompat.DEFAULT, DateFormatCompat.SHORT))); } } else if (fieldName.equals("TAG")) { value.argvalue = value.argvalue.startsWith("N'") ? value.argvalue.substring(2) : value.argvalue; if (relations.argvalue != null && relations.argvalue.equals("=")) { relations.argvalue = "IN"; value.argvalue = StringHelper.trim(value.argvalue, '\''); tags tag = TagsHandler.GetTagByTagName(value.argvalue); if (tag != null) { value.argvalue = StringFormat.format("(%1$s)", TagsHandler.GetTagNameAndChildrenNames(tag.gettag_id())); } else { value.argvalue = StringFormat.format("('%1$s')", Guid.Empty); } } else if (relations.argvalue != null && relations.argvalue.equals("LIKE")) { relations.argvalue = "IN"; value.argvalue = StringHelper.trim(value.argvalue, '\'').replace("%", "*"); String IDs = TagsHandler.GetTagNamesAndChildrenNamesByRegExp(value.argvalue); if (StringHelper.isNullOrEmpty(IDs)) { value.argvalue = StringFormat.format("('%1$s')", Guid.Empty); } else { value.argvalue = StringFormat.format("(%1$s)", IDs); } } } } // private static final String DATE_FORMAT = "MMM dd,yyyy"; private static DateTime DealWithDateEnum(String value) { DateTime formatedValue = new DateTime(); Integer result = new Integer(0); RefObject<Integer> tempRefObject = new RefObject<Integer>(result); boolean tempVar = IntegerCompat.TryParse(StringHelper.trim(value, '\''), tempRefObject); result = tempRefObject.argvalue; if (tempVar) { DateEnumForSearch dateEnumVal = DateEnumForSearch.forValue(result); switch (dateEnumVal) { case Today: formatedValue = DateTime.getNow(); break; case Yesterday: formatedValue = DateTime.getNow().AddDays(-1); break; default: break; } } else { for (int i = -2; i > -8; i--) { if (StringHelper.EqOp(DateUtils.getDayOfWeek(i), StringHelper.trim(value, '\'').toUpperCase())) { formatedValue = DateTime.getNow(); return formatedValue.resetToMidnight(); } } } return formatedValue.resetToMidnight(); } public String buildConditionSql(String fieldName, String customizedValue, String customizedRelation, String tableName, boolean caseSensitive) { String condition; RefObject<String> tempRefObject = new RefObject<String>(customizedRelation); RefObject<String> tempRefObject2 = new RefObject<String>(customizedValue); formatValue(fieldName, tempRefObject, tempRefObject2, caseSensitive); customizedRelation = tempRefObject.argvalue; customizedValue = tempRefObject2.argvalue; if ((StringHelper.EqOp(customizedValue, "''") || StringHelper.EqOp(customizedValue.toLowerCase(), "n'null'")) && ((StringHelper.EqOp(customizedRelation, "=")) || (StringHelper.EqOp(customizedRelation, "!=")))) // handling // the // NULL // value // in // case // the // search // is // for // empty // value; { String nullRelation = (StringHelper.EqOp(customizedRelation, "=")) ? "IS" : "IS NOT"; String SqlCond = (StringHelper.EqOp(customizedRelation, "=")) ? "OR" : "AND"; condition = StringFormat.format("( %1$s.%2$s %3$s %4$s %5$s %1$s.%2$s %6$s NULL)", tableName, getDbFieldName(fieldName), customizedRelation, customizedValue, SqlCond, nullRelation); } else { condition = StringFormat.format(" %1$s.%2$s %3$s %4$s ", tableName, getDbFieldName(fieldName), customizedRelation, customizedValue); } return condition; } }