private Schema erlSchemaToCRUDSchema(string name) { var erlSect = GetErlSchemaSection(name); if (erlSect==null) throw new ErlDataAccessException(StringConsts.ERL_DS_SCHEMA_MAP_NOT_KNOWN_ERROR.Args(name)); var defs = new List<Schema.FieldDef>(); var keyCount = 0; var nodeFields = erlSect.Children.Where(c => c.IsSameName(CONFIG_FIELD_SECTION)); foreach(var nodeField in nodeFields) { var fname = nodeField.AttrByName(Configuration.CONFIG_NAME_ATTR).Value; var ftitle = nodeField.AttrByName(CONFIG_TITLE_ATTR).Value; var isKey = nodeField.AttrByName(CONFIG_KEY_ATTR).ValueAsBool(); var required= nodeField.AttrByName(CONFIG_REQUIRED_ATTR).ValueAsBool(false); var type = nodeField.AttrByName(CONFIG_TYPE_ATTR).Value; var clrType = mapErlTypeToCLR(type); var strDfltValue = nodeField.AttrByName(CONFIG_DEFAULT_ATTR).ValueAsString(string.Empty); object dfltValue = null; if (clrType!=typeof(string)) { if (strDfltValue.IsNotNullOrWhiteSpace()) { if (clrType==typeof(DateTime?)) dfltValue = ((long)strDfltValue.AsType(typeof(long), false)).FromMicrosecondsSinceUnixEpochStart(); else dfltValue = strDfltValue.AsType(clrType, false); } } else { dfltValue = strDfltValue; } if (isKey) keyCount++; List<string> vList = null; var values = nodeField.Children.Where( c => c.IsSameName(CONFIG_VALUE_SECTION)); foreach(var vnode in values) { var code = vnode.AttrByName(CONFIG_CODE_ATTR).Value; var disp = vnode.AttrByName(CONFIG_DISPLAY_ATTR).Value; if (code.IsNullOrWhiteSpace()) continue; if (vList==null) vList = new List<string>(); if (disp.IsNullOrWhiteSpace()) vList.Add(code); else vList.Add("{0}: {1}".Args(code, disp)); } var atr = new FieldAttribute( targetName: m_Store.TargetName, backendName: fname, backendType: type, storeFlag: StoreFlag.LoadAndStore, key: isKey, required: required, dflt: dfltValue, visible: nodeField.AttrByName(CONFIG_VISIBLE_ATTR).ValueAsBool(true), maxLength: nodeField.AttrByName(CONFIG_LEN_ATTR).ValueAsInt(0), description: nodeField.AttrByName(CONFIG_DESCR_ATTR).Value, displayFormat: nodeField.AttrByName(CONFIG_DISPLAY_FORMAT_ATTR).Value, valueList: vList==null ? null : string.Join(",", vList),//"CAR: Car Driver,SMK: Smoker, REL: Religious, CNT: Country music lover, GLD: Gold collector" metadata: nodeField.ToLaconicString()); var def = new Schema.FieldDef(fname ?? ftitle, clrType, new FieldAttribute[]{atr}); defs.Add( def ); }//for fields var result = new Schema(name, false, defs.ToArray()); result.ExtraData[SCHEMA_KEY_COUNT] = keyCount; return result; }
protected virtual void EmitDeserializeField(StringBuilder source, Schema.FieldDef fdef) { var t = fdef.Type; var isNullable = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>); var isValueType = t.IsValueType; var isArray = t.IsArray; var isList = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List <>); var prop = fdef.MemberInfo.Name; var tcName = t.FullNameWithExpandedGenericArgs().Replace('+', '.'); //Specialized handling via dict string code; if (!Reader.DESER_TYPE_MAP.TryGetValue(t, out code)) //we go by the model that we have now, if what was ser does not match put it in amorphous { if (isNullable || !isValueType) { source.AppendLine(" if (dt==DataType.Null) {{ doc.{0} = null; continue;}} ".Args(prop)); } if (t.IsEnum) { source.AppendLine(" if (dt!=DataType.Int32) break;"); source.AppendLine(" var ev = ({0})Reader.ReadInt32(streamer);".Args(tcName)); source.AppendLine(" doc.{0} = ev;".Args(prop)); source.AppendLine(" continue;"); return; } else if (typeof(TypedDoc).IsAssignableFrom(t)) { source.AppendLine(" if (dt!=DataType.Doc) break;"); source.AppendLine(" var vdoc = new {0}();".Args(t.FullName)); source.AppendLine(" if (Reader.TryReadRow(doc, vdoc, streamer, CodeGenerator.GetName(name)))"); source.AppendLine(" doc.{0} = vdoc;".Args(prop)); source.AppendLine(" continue;"); return; } else if (isArray) { var et = t.GetElementType(); if (typeof(TypedDoc).IsAssignableFrom(et)) { source.AppendLine(" if (dt!=DataType.Array) break;"); source.AppendLine(" atp = Reader.ReadDataType(streamer);"); source.AppendLine(" if (atp!=DataType.Doc) break;"); source.AppendLine(" doc.{0} = Reader.ReadRowArray<{1}>(doc, streamer, CodeGenerator.GetName(name));".Args(prop, et.FullName)); source.AppendLine(" continue;"); return; } } else if (isList) { var gat = t.GetGenericArguments()[0]; if (typeof(TypedDoc).IsAssignableFrom(gat)) { source.AppendLine(" if (dt!=DataType.Array) break;"); source.AppendLine(" atp = Reader.ReadDataType(streamer);"); source.AppendLine(" if (atp!=DataType.Doc) break;"); source.AppendLine(" doc.{0} = Reader.ReadRowList<{1}>(doc, streamer, CodeGenerator.GetName(name));".Args(prop, gat.FullName)); source.AppendLine(" continue;"); return; } } } if (code.IsNotNullOrWhiteSpace()) { source.AppendLine(code.Args(fdef.MemberInfo.Name)); return; } //Generate if (isArray) { var et = t.GetElementType(); source.AppendLine(" if (dt==DataType.Null) doc.{0} = null;".Args(prop)); source.AppendLine(" else if (dt!=DataType.Array) break;"); source.AppendLine(" else"); source.AppendLine(" {"); source.AppendLine(" atp = Reader.ReadDataType(streamer);"); source.AppendLine(" if (atp!=DataType.{0}) break;".Args(et.Name)); source.AppendLine(" var len = Reader.ReadArrayLength(streamer);"); source.AppendLine(" var arr = new {0}[len];".Args(et.FullName)); source.AppendLine(" for(var i=0; i<len; i++) arr[i] = Reader.Read{0}(streamer);".Args(et.Name)); source.AppendLine(" doc.{0} = arr;".Args(prop)); source.AppendLine(" }"); source.AppendLine(" continue;"); } else if (isList) { var gat = t.GetGenericArguments()[0]; var tn = gat.Name; source.AppendLine(" if (dt==DataType.Null) doc.{0} = null;".Args(prop)); source.AppendLine(" if (dt!=DataType.Array) break;"); source.AppendLine(" else"); source.AppendLine(" {"); source.AppendLine(" atp = Reader.ReadDataType(streamer);"); source.AppendLine(" if (atp!=DataType.{0}) break;".Args(tn)); source.AppendLine(" var len = Reader.ReadArrayLength(streamer);"); source.AppendLine(" var lst = new List<{0}>(len);".Args(gat.FullName)); source.AppendLine(" for(var i=0; i<len; i++) lst.Add( Reader.Read{0}(streamer) );".Args(tn)); source.AppendLine(" doc.{0} = lst;".Args(prop)); source.AppendLine(" }"); source.AppendLine(" continue;"); } else if (isNullable || t == typeof(string)) { var tn = fdef.NonNullableType.Name; source.AppendLine(" if (dt==DataType.Null) doc.{0} = null;".Args(prop)); source.AppendLine(" else if (dt==DataType.{1}) doc.{0} = Reader.Read{1}(streamer);".Args(prop, tn)); source.AppendLine(" else break;"); source.AppendLine(" continue;"); } else //regular { var tn = fdef.NonNullableType.Name; source.AppendLine(" if (dt==DataType.{1}) doc.{0} = Reader.Read{1}(streamer);".Args(prop, tn)); source.AppendLine(" else break;"); source.AppendLine(" continue;"); } }
protected virtual JSONDataMap FieldDefToJSON(Row row, string schema, Schema.FieldDef fdef, string target, string isoLang, ModelFieldValueListLookupFunc valueListLookup) { var result = new JSONDataMap(); result["Name"] = fdef.Name; result["Type"] = MapCLRTypeToJS(fdef.NonNullableType); var key = fdef.AnyTargetKey; if (key) { result["Key"] = key; } if (fdef.NonNullableType.IsEnum) { //Generate default lookupdict for enum var names = Enum.GetNames(fdef.NonNullableType); var values = new JSONDataMap(true); foreach (var name in names) { values[name] = name; } result["LookupDict"] = values; } var attr = fdef[target]; if (attr != null) { if (attr.Description != null) { result["Description"] = OnLocalizeString(schema, "Description", attr.Description, isoLang); } var str = attr.StoreFlag == StoreFlag.OnlyStore || attr.StoreFlag == StoreFlag.LoadAndStore; if (!str) { result["Stored"] = false; } if (attr.Required) { result["Required"] = attr.Required; } if (!attr.Visible) { result["Visible"] = attr.Visible; } if (attr.Min != null) { result["MinValue"] = attr.Min; } if (attr.Max != null) { result["MaxValue"] = attr.Max; } if (attr.MinLength > 0) { result["MinSize"] = attr.MinLength; } if (attr.MaxLength > 0) { result["Size"] = attr.MaxLength; } if (attr.Default != null) { result["DefaultValue"] = attr.Default; } if (attr.ValueList.IsNotNullOrWhiteSpace()) { var vl = OnLocalizeString(schema, "LookupDict", attr.ValueList, isoLang); result["LookupDict"] = FieldAttribute.ParseValueListString(vl); } else { var valueList = valueListLookup != null?valueListLookup(this, row, fdef, target, isoLang) : row.GetClientFieldValueList(this, fdef, target, isoLang); if (valueList == null && attr.HasValueList) { valueList = attr.ParseValueList(); } if (valueList != null) { result["LookupDict"] = valueList; } } if (attr.Kind != DataKind.Text) { result["Kind"] = MapCLRKindToJS(attr.Kind); } if (attr.CharCase != CharCase.AsIs) { result["Case"] = MapCLRCharCaseToJS(attr.CharCase); } if (attr.Metadata != null) { var sect = attr.Metadata[METADATA_CONFIG_FIELD]; if (sect.Exists) { result[METADATA_CONFIG_FIELD] = sect.ToConfigurationJSONDataMap(); } foreach (var mAt in attr.Metadata.Attributes) { var fn = mAt.Name; if (!METADATA_FIELDS.Contains(fn)) { continue; } var mv = mAt.Value; if (mv.IsNullOrWhiteSpace()) { continue; } if (fn == "Description" || fn == "Placeholder" || fn == "LookupDict" || fn == "Hint") { mv = OnLocalizeString(schema, fn, mv, isoLang); } result[fn] = mv; } } } return(result); }
private Schema getSchema(Query query, MySqlDataReader reader, out Schema.FieldDef[] toLoad) { Schema schema; if (query.ResultRowType!=null) schema = Schema.GetForTypedRow(query.ResultRowType); else schema = GetSchemaFromReader(query.Name, m_Source, reader); //determine what fields to load toLoad = new Schema.FieldDef[reader.FieldCount]; for (int i = 0; i < reader.FieldCount; i++) { var name = reader.GetName(i); var fdef = schema[name]; if (fdef==null) continue; var attr = fdef[StringConsts.MYSQL_CRUD_TARGET]; if (attr!=null) { if (attr.StoreFlag!=StoreFlag.LoadAndStore && attr.StoreFlag!=StoreFlag.OnlyLoad) continue; } toLoad[i] = fdef; } return schema; }
protected virtual void EmitSerializeFieldLine(StringBuilder source, Schema.FieldDef fdef) { if (source == null) { return; } var fatr = fdef.Attrs.FirstOrDefault(a => a.IsArow); if (fatr == null) { return; //do not serialize this field } var name = GetName(fatr.BackendName); if (name == 0) { return; //no name specified } var isValueType = fdef.Type.IsValueType; var isNullable = isValueType ? fdef.NonNullableType != fdef.Type : false; var propertyName = fdef.MemberInfo.Name; var propertyValue = propertyName; if (isNullable) { propertyValue = "{0}.Value".Args(propertyValue); } source.AppendLine(" // '{0}' = {1}".Args(fatr.BackendName, name)); if (isNullable) { source.AppendLine(" if (doc.{0}.HasValue)".Args(propertyName)); } else if (!isValueType) { source.AppendLine(" if (doc.{0} != null)".Args(propertyName)); } var t = fdef.NonNullableType; string expr; if (!Writer.SER_TYPE_MAP.TryGetValue(t, out expr)) { if (t.IsEnum) { source.AppendLine(" Writer.Write(streamer, {0}, (int)doc.{1});".Args(name, propertyName)); } else if (typeof(TypedDoc).IsAssignableFrom(t)) { source.AppendLine(" Writer.WriteRow(streamer, {0}, doc.{1});".Args(name, propertyName)); } else if (t.IsArray && typeof(TypedDoc).IsAssignableFrom(t.GetElementType())) { source.AppendLine(" Writer.WriteRowArray(streamer, {0}, doc.{1});".Args(name, propertyName)); } else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List <>) && typeof(TypedDoc).IsAssignableFrom(t.GetGenericArguments()[0])) { source.AppendLine(" Writer.WriteRowArray(streamer, {0}, doc.{1});".Args(name, propertyName)); } else { throw new ArowException(StringConsts.AROW_MEMBER_TYPE_NOT_SUPPORTED_ERROR.Args(t.Name)); } if (isNullable || !isValueType) { source.AppendLine(" else AW.WriteNull(streamer, {0});".Args(name)); } return; } if (expr.IsNullOrWhiteSpace()) { expr = "doc.{0}"; } source.AppendLine(" AW.Write(streamer, {0}, {1});".Args(name, expr.Args(propertyValue))); if (isNullable || !isValueType) { source.AppendLine(" else AW.WriteNull(streamer, {0});".Args(name)); } }
protected virtual Schema.FieldDef GetFieldDefFromJSON(JSONDataMap def) { var name = def["Name"].AsString(); var type = MapJSToCLRType(def["Type"].AsString()); var key = def["Key"].AsBool(false); var description = def["Description"].AsString(null); var required = def["Required"].AsBool(false); var visible = def["Visible"].AsBool(true); var minValue = def["MinValue"]; var maxValue = def["MaxValue"]; var minLength = def["MinSize"].AsInt(0); var maxLength = def["Size"].AsInt(0); var defaultValue = def["DefaultValue"]; var kind = MapJSToCLRKind(def["Kind"].AsString()); var charCase = MapJSToCLRCharCase(def["Case"].AsString()); var stored = def["Stored"].AsNullableBool(); var storeFlag = (stored == false) ? StoreFlag.OnlyLoad : StoreFlag.LoadAndStore; var lookupValues = def["LookupDict"] as JSONDataMap; var metadata = Configuration.NewEmptyRoot(); foreach (var kvp in def) { if (kvp.Value == null) continue; metadata.AddAttributeNode(kvp.Key, kvp.Value); } var mcontent = metadata.ToLaconicString(LaconfigWritingOptions.Compact); var attr = lookupValues == null ? new FieldAttribute( targetName: TargetedAttribute.ANY_TARGET, storeFlag: storeFlag, key: key, kind: kind, required: required, visible: visible, dflt: defaultValue, min: minValue, max: maxValue, minLength: minLength, maxLength: maxLength, charCase: charCase, description: description, metadata: mcontent // nonUI = false, // formatRegExp = null, // formatDescr = null, // displayFormat = null ) : new FieldAttribute( valueList: lookupValues, targetName: TargetedAttribute.ANY_TARGET, storeFlag: storeFlag, key: key, kind: kind, required: required, visible: visible, dflt: defaultValue, min: minValue, max: maxValue, minLength: minLength, maxLength: maxLength, charCase: charCase, description: description, metadata: mcontent // nonUI = false, // formatRegExp = null, // formatDescr = null, // displayFormat = null ); var fdef = new Schema.FieldDef(name, type, attr); return fdef; }
public static Schema ErlSchemaToCRUDSchema(string name, IConfigSectionNode erlSect) { var defs = new List <Schema.FieldDef>(); var isInsert = erlSect.AttrByName(CONFIG_INSERT_ATTR).ValueAsBool(false); var isUpdate = erlSect.AttrByName(CONFIG_UPDATE_ATTR).ValueAsBool(false); var isDelete = erlSect.AttrByName(CONFIG_DELETE_ATTR).ValueAsBool(false); var schDescr = erlSect.AttrByName(CONFIG_DESCR_ATTR).ValueAsString(); var isReadonly = !(isInsert || isUpdate || isDelete); var keyCount = 0; var nodeFields = erlSect.Children.Where(c => c.IsSameName(CONFIG_FIELD_SECTION)); foreach (var nodeField in nodeFields) { var cfg = new LaconicConfiguration(); cfg.CreateFromNode(nodeField); var node = cfg.Root; var fname = node.AttrByName(Configuration.CONFIG_NAME_ATTR).Value; var ftitle = node.AttrByName(CONFIG_TITLE_ATTR).Value; var fhint = node.AttrByName(CONFIG_DESCR_ATTR).ValueAsString(""); var isKey = node.AttrByName(CONFIG_KEY_ATTR).ValueAsBool(); var required = node.AttrByName(CONFIG_REQUIRED_ATTR).ValueAsBool(false); var type = node.AttrByName(CONFIG_TYPE_ATTR).Value; var clrType = mapErlTypeToCLR(type); var fmtdesc = node.AttrByName(CONFIG_FORMAT_DESCR_ATTR).Value; var dispFmt = node.AttrByName(CONFIG_DISPLAY_FORMAT_ATTR).Value; if (dispFmt != null && (dispFmt.Length < 3 || dispFmt.Substring(0, 3) != "{0:")) { dispFmt = "{{0:{0}}}".Args(dispFmt); } node.AddAttributeNode(CONFIG_TITLE_ATTR, ftitle); object minV = null; object maxV = null; var sv = node.AttrByName(CONFIG_MIN_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) { minV = sv.AsType(clrType, true); } sv = node.AttrByName(CONFIG_MAX_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) { maxV = sv.AsType(clrType, true); } var strDfltValue = node.AttrByName(CONFIG_DEFAULT_ATTR).ValueAsString(string.Empty); object dfltValue = null; if (clrType == typeof(string)) { dfltValue = strDfltValue; } else if (strDfltValue.IsNotNullOrWhiteSpace()) { dfltValue = clrType == typeof(DateTime?) ? ((long)strDfltValue.AsType(typeof(long), false)).FromMicrosecondsSinceUnixEpochStart() : strDfltValue.AsType(clrType, false); } if (isKey) { keyCount++; } List <string> vList = null; var values = node.Children.Where(c => c.IsSameName(CONFIG_VALUE_SECTION)); foreach (var vnode in values) { var code = vnode.AttrByName(CONFIG_CODE_ATTR).Value; var disp = vnode.AttrByName(CONFIG_DISPLAY_ATTR).Value; if (code.IsNullOrWhiteSpace()) { continue; } if (vList == null) { vList = new List <string>(); } if (disp.IsNullOrWhiteSpace()) { vList.Add(code); } else { vList.Add("{0}: {1}".Args(code, disp)); } } var caze = CharCase.AsIs; var ca = node.AttrByName(CONFIG_CASE_ATTR).Value; if (ca.EqualsOrdIgnoreCase("upper")) { caze = CharCase.Upper; } else if (ca.EqualsOrdIgnoreCase("lower")) { caze = CharCase.Lower; } var atr = new FieldAttribute( targetName: TargetedAttribute.ANY_TARGET, backendName: fname, backendType: type, storeFlag: StoreFlag.LoadAndStore, key: isKey, required: required, dflt: dfltValue, min: minV, max: maxV, charCase: caze, visible: node.AttrByName(CONFIG_VISIBLE_ATTR).ValueAsBool(true), maxLength: node.AttrByName(CONFIG_LEN_ATTR).ValueAsInt(0), description: fmtdesc.IsNullOrEmpty() ? fhint : "{0}\nFormat: {1}".Args(fhint, fmtdesc), //Parsing.Utils.ParseFieldNameToDescription(ftitle, true), formatRegExp: node.AttrByName(CONFIG_FORMAT_ATTR).Value, formatDescr: fmtdesc, displayFormat: dispFmt, valueList: vList == null ? null : string.Join(",", vList),//"CAR: Car Driver,SMK: Smoker, REL: Religious, CNT: Country music lover, GLD: Gold collector" metadata: node.ToLaconicString()); var def = new Schema.FieldDef(fname, clrType, new [] { atr }); defs.Add(def); }//for fields var result = new Schema(name, isReadonly, defs.ToArray()); if (schDescr.IsNotNullOrWhiteSpace()) { result.ExtraData[CONFIG_DESCR_ATTR] = schDescr; } result.ExtraData[SCHEMA_KEY_COUNT] = keyCount; result.ExtraData[Schema.EXTRA_SUPPORTS_INSERT_ATTR] = isInsert; result.ExtraData[Schema.EXTRA_SUPPORTS_UPDATE_ATTR] = isUpdate; result.ExtraData[Schema.EXTRA_SUPPORTS_DELETE_ATTR] = isDelete; return(result); }
protected virtual (bool hasValue, Exception error) CheckValueRequired(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value, string scope) { var missing = (value == null) || (value is string strv && strv.IsNullOrWhiteSpace()) || //string null, or whitespace are treated as missing (value is IRequired ireq && !ireq.CheckRequired(targetName)); if (missing) { if (atr.Required) { return(false, new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_REQUIRED_ERROR)); } return(false, null); //no other validations are needed as field is null anyway } return(true, null); }
protected string GetInnerScope(Schema.FieldDef fdef, string scope) => scope.IsNullOrWhiteSpace() ? fdef.Name : scope + "." + fdef.Name;
protected virtual Schema.FieldDef GetFieldDefFromJSON(JSONDataMap def) { var name = def["Name"].AsString(); var type = MapJSToCLRType(def["Type"].AsString()); var key = def["Key"].AsBool(false); var description = def["Description"].AsString(null); var required = def["Required"].AsBool(false); var visible = def["Visible"].AsBool(true); var minValue = def["MinValue"]; var maxValue = def["MaxValue"]; var minLength = def["MinSize"].AsInt(0); var maxLength = def["Size"].AsInt(0); var defaultValue = def["DefaultValue"]; var kind = MapJSToCLRKind(def["Kind"].AsString()); var charCase = MapJSToCLRCharCase(def["Case"].AsString()); var stored = def["Stored"].AsNullableBool(); var storeFlag = (stored == false) ? StoreFlag.OnlyLoad : StoreFlag.LoadAndStore; var lookupValues = def["LookupDict"] as JSONDataMap; var metadata = Configuration.NewEmptyRoot(); foreach (var kvp in def) { if (kvp.Value == null) { continue; } metadata.AddAttributeNode(kvp.Key, kvp.Value); } var mcontent = metadata.ToLaconicString(LaconfigWritingOptions.Compact); var attr = lookupValues == null ? new FieldAttribute( targetName: TargetedAttribute.ANY_TARGET, storeFlag: storeFlag, key: key, kind: kind, required: required, visible: visible, dflt: defaultValue, min: minValue, max: maxValue, minLength: minLength, maxLength: maxLength, charCase: charCase, description: description, metadata: mcontent // nonUI = false, // formatRegExp = null, // formatDescr = null, // displayFormat = null ) : new FieldAttribute( valueList: lookupValues, targetName: TargetedAttribute.ANY_TARGET, storeFlag: storeFlag, key: key, kind: kind, required: required, visible: visible, dflt: defaultValue, min: minValue, max: maxValue, minLength: minLength, maxLength: maxLength, charCase: charCase, description: description, metadata: mcontent // nonUI = false, // formatRegExp = null, // formatDescr = null, // displayFormat = null ); var fdef = new Schema.FieldDef(name, type, attr); return(fdef); }
/// <summary> /// Validates document field using Schema.FieldDef settings. /// This method is invoked by base Validate() implementation. /// The method is not expected to throw exception in case of failed validation, rather return exception instance because /// throwing exception really hampers validation performance when many rows need to be validated /// </summary> public virtual ValidState ValidateField(ValidState state, Schema.FieldDef fdef, string scope = null) { if (fdef == null) { throw new FieldValidationException(Schema.DisplayName, CoreConsts.NULL_STRING, StringConsts.ARGUMENT_ERROR + ".ValidateField(fdef=null)"); } var atr = fdef[state.TargetName]; if (atr == null) { return(state); //not found per target } var value = GetFieldValue(fdef); var(hasValue, error) = CheckValueRequired(state.TargetName, fdef, atr, value, scope); if (error != null) { return(new ValidState(state, error)); } if (!hasValue) { return(state); //nothing else left to check } state = CheckValueIValidatable(state, fdef, atr, value, scope); if (state.ShouldStop) { return(state); } error = CheckValueLength(state.TargetName, fdef, atr, value, scope); if (error != null) { state = new ValidState(state, error); if (state.ShouldStop) { return(state); } } error = CheckValueKind(state.TargetName, fdef, atr, value, scope); if (error != null) { state = new ValidState(state, error); if (state.ShouldStop) { return(state); } } error = CheckValueMinMax(state.TargetName, fdef, atr, value, scope); if (error != null) { state = new ValidState(state, error); if (state.ShouldStop) { return(state); } } error = CheckValueRegExp(state.TargetName, fdef, atr, value, scope); if (error != null) { state = new ValidState(state, error); if (state.ShouldStop) { return(state); } } //this is at the end as ValueList check might induce a database call to get a pick list (when it is not cached) error = CheckValueList(state.TargetName, fdef, atr, value, scope); if (error != null) { state = new ValidState(state, error); if (state.ShouldStop) { return(state); } } return(state); }
protected virtual Exception CheckValueLength(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value, string scope) { if (atr.MinLength < 1 && atr.MaxLength < 1) { return(null); } if (value is ILengthCheck lc) { if (atr.MinLength > 0 && !lc.CheckMinLength(targetName, atr.MinLength)) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MIN_LENGTH_ERROR.Args(atr.MinLength))); } if (atr.MaxLength > 0 && !lc.CheckMaxLength(targetName, atr.MaxLength)) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MAX_LENGTH_ERROR.Args(atr.MaxLength))); } return(null); } var isString = value is string; var eobj = value as IEnumerable; var ecount = !isString && eobj != null?eobj.Cast <object>().Count() : -1; if (atr.MinLength > 0) { if (ecount >= 0) { if (ecount < atr.MinLength) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MIN_LENGTH_ERROR.Args(atr.MinLength))); } } else { if (value.ToString().Length < atr.MinLength) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MIN_LENGTH_ERROR.Args(atr.MinLength))); } } } if (atr.MaxLength > 0) { if (ecount >= 0) { if (ecount > atr.MaxLength) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MAX_LENGTH_ERROR.Args(atr.MaxLength))); } } else { if (value.ToString().Length > atr.MaxLength) { return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MAX_LENGTH_ERROR.Args(atr.MaxLength))); } } } return(null); }
private Schema erlSchemaToCRUDSchema(string name) { var erlSect = GetErlSchemaSection(name); if (erlSect == null) { throw new ErlDataAccessException(StringConsts.ERL_DS_SCHEMA_MAP_NOT_KNOWN_ERROR.Args(name)); } var defs = new List <Schema.FieldDef>(); var isInsert = erlSect.AttrByName(CONFIG_INSERT_ATTR).ValueAsBool(false); var isUpdate = erlSect.AttrByName(CONFIG_UPDATE_ATTR).ValueAsBool(false); var isDelete = erlSect.AttrByName(CONFIG_DELETE_ATTR).ValueAsBool(false); var isReadonly = !(isInsert || isUpdate || isDelete); var keyCount = 0; var nodeFields = erlSect.Children.Where(c => c.IsSameName(CONFIG_FIELD_SECTION)); foreach (var nodeField in nodeFields) { var fname = nodeField.AttrByName(Configuration.CONFIG_NAME_ATTR).Value; var ftitle = nodeField.AttrByName(CONFIG_TITLE_ATTR).Value; var isKey = nodeField.AttrByName(CONFIG_KEY_ATTR).ValueAsBool(); var required = nodeField.AttrByName(CONFIG_REQUIRED_ATTR).ValueAsBool(false); var type = nodeField.AttrByName(CONFIG_TYPE_ATTR).Value; var clrType = mapErlTypeToCLR(type); object minV = null; object maxV = null; var sv = nodeField.AttrByName(CONFIG_MIN_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) { minV = sv.AsType(clrType, true); } sv = nodeField.AttrByName(CONFIG_MAX_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) { maxV = sv.AsType(clrType, true); } var strDfltValue = nodeField.AttrByName(CONFIG_DEFAULT_ATTR).ValueAsString(string.Empty); object dfltValue = null; if (clrType != typeof(string)) { if (strDfltValue.IsNotNullOrWhiteSpace()) { if (clrType == typeof(DateTime?)) { dfltValue = ((long)strDfltValue.AsType(typeof(long), false)).FromMicrosecondsSinceUnixEpochStart(); } else { dfltValue = strDfltValue.AsType(clrType, false); } } } else { dfltValue = strDfltValue; } if (isKey) { keyCount++; } List <string> vList = null; var values = nodeField.Children.Where(c => c.IsSameName(CONFIG_VALUE_SECTION)); foreach (var vnode in values) { var code = vnode.AttrByName(CONFIG_CODE_ATTR).Value; var disp = vnode.AttrByName(CONFIG_DISPLAY_ATTR).Value; if (code.IsNullOrWhiteSpace()) { continue; } if (vList == null) { vList = new List <string>(); } if (disp.IsNullOrWhiteSpace()) { vList.Add(code); } else { vList.Add("{0}: {1}".Args(code, disp)); } } var caze = CharCase.AsIs; var ca = nodeField.AttrByName(CONFIG_CASE_ATTR).Value; if (ca.EqualsOrdIgnoreCase("upper")) { caze = CharCase.Upper; } else if (ca.EqualsOrdIgnoreCase("lower")) { caze = CharCase.Lower; } var atr = new FieldAttribute( targetName: m_Store.TargetName, backendName: fname, backendType: type, storeFlag: StoreFlag.LoadAndStore, key: isKey, required: required, dflt: dfltValue, min: minV, max: maxV, charCase: caze, visible: nodeField.AttrByName(CONFIG_VISIBLE_ATTR).ValueAsBool(true), maxLength: nodeField.AttrByName(CONFIG_LEN_ATTR).ValueAsInt(0), description: ftitle, formatRegExp: nodeField.AttrByName(CONFIG_FORMAT_ATTR).Value, formatDescr: nodeField.AttrByName(CONFIG_FORMAT_DESCR_ATTR).Value, displayFormat: nodeField.AttrByName(CONFIG_DISPLAY_FORMAT_ATTR).Value, valueList: vList == null ? null : string.Join(",", vList), //"CAR: Car Driver,SMK: Smoker, REL: Religious, CNT: Country music lover, GLD: Gold collector" metadata: nodeField.ToLaconicString()); var def = new Schema.FieldDef(fname, clrType, new FieldAttribute[] { atr }); defs.Add(def); }//for fields var result = new Schema(name, isReadonly, defs.ToArray()); result.ExtraData[SCHEMA_KEY_COUNT] = keyCount; result.ExtraData[Schema.EXTRA_SUPPORTS_INSERT_ATTR] = isInsert; result.ExtraData[Schema.EXTRA_SUPPORTS_UPDATE_ATTR] = isUpdate; result.ExtraData[Schema.EXTRA_SUPPORTS_DELETE_ATTR] = isDelete; return(result); }
protected virtual (bool hasValue, Exception error) CheckValueRequired(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value) { if (value == null || (value is string strv && strv.IsNullOrWhiteSpace()) || (value is GDID gdid && gdid.IsZero)) { if (atr.Required) { return(false, new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_REQUIRED_ERROR)); } return(false, null); //no other validations are needed as field is null anyway } return(true, null); }
/// <summary> /// Gets CRUD schema from MySqlReader per particular QuerySource. /// If source is null then all columns from reader are copied. /// Note: this code was purposely made provider specific because other providers may treat some nuances differently /// </summary> public static Schema GetSchemaFromReader(string name, QuerySource source, MySqlDataReader reader) { var table = name; var fdefs = new List<Schema.FieldDef>(); for (int i = 0; i < reader.FieldCount; i++) { var fname = reader.GetName(i); var ftype = reader.GetFieldType(i); var def = new Schema.FieldDef(fname, ftype, source!=null ? ( source.HasPragma ? source.ColumnDefs[fname] : null) : null); fdefs.Add( def ); } if (source!=null) if (source.HasPragma && source.ModifyTarget.IsNotNullOrWhiteSpace()) table = source.ModifyTarget; if (table.IsNullOrWhiteSpace()) table = Guid.NewGuid().ToString(); return new Schema(table, source!=null ? source.ReadOnly : true, fdefs); }
private static (object value, OracleDbType?dbType) getDbFieldValue(Doc doc, Schema.FieldDef fld, FieldAttribute fattr, OracleDataStoreBase store) { var result = doc.GetFieldValue(fld); return(CLRValueToDB(store, result, fattr.BackendType)); }
/// <summary> /// Gets schema from reader taking Query.ResultRowType in consideration /// </summary> public static Schema GetSchemaForQuery(string target, Query query, MySqlDataReader reader, QuerySource qSource, out Schema.FieldDef[] toLoad) { Schema schema; var rtp = query.ResultRowType; if (rtp != null && typeof(TypedRow).IsAssignableFrom(rtp)) schema = Schema.GetForTypedRow(query.ResultRowType); else schema = GetSchemaFromReader(query.Name, qSource, reader); //determine what fields to load toLoad = new Schema.FieldDef[reader.FieldCount]; for (int i = 0; i < reader.FieldCount; i++) { var name = reader.GetName(i); var fdef = schema[name]; //todo A gde GetBackendNameFor target? if (fdef==null) continue; var attr = fdef[target]; if (attr!=null) { if (attr.StoreFlag!=StoreFlag.LoadAndStore && attr.StoreFlag!=StoreFlag.OnlyLoad) continue; } toLoad[i] = fdef; } return schema; }
protected virtual JSONDataMap FieldDefToJSON(string schema, Schema.FieldDef fdef, string target, string isoLang = null) { var result = new JSONDataMap(); result["Name"] = fdef.Name; result["Type"] = MapCLRTypeToJS(fdef.NonNullableType); var key = fdef.AnyTargetKey; if (key) { result["Key"] = key; } if (fdef.NonNullableType.IsEnum) { //Generate default lookupdict for enum var names = Enum.GetNames(fdef.NonNullableType); var values = new JSONDataMap(true); foreach (var name in names) { values[name] = name; } result["LookupDict"] = values; } var attr = fdef[target]; if (attr != null) { if (attr.Description != null) { result["Description"] = OnLocalizeString(schema, "Description", attr.Description, isoLang); } var str = attr.StoreFlag == StoreFlag.OnlyStore || attr.StoreFlag == StoreFlag.LoadAndStore; if (!str) { result["Stored"] = str; } if (attr.Required) { result["Required"] = attr.Required; } if (!attr.Visible) { result["Visible"] = attr.Visible; } if (attr.Min != null) { result["MinValue"] = attr.Min; } if (attr.Max != null) { result["MaxValue"] = attr.Max; } if (attr.MinLength > 0) { result["MinSize"] = attr.MinLength; } if (attr.MaxLength > 0) { result["Size"] = attr.MaxLength; } if (attr.Default != null) { result["DefaultValue"] = attr.Default; } if (attr.ValueList.IsNotNullOrWhiteSpace()) { var vl = OnLocalizeString(schema, "LookupDict", attr.ValueList, isoLang); result["LookupDict"] = FieldAttribute.ParseValueListString(vl); } if (attr.Kind != DataKind.Text) { result["Kind"] = MapCLRKindToJS(attr.Kind); } } if (attr.Metadata != null) { foreach (var fn in METADATA_FIELDS) { var mv = attr.Metadata.AttrByName(fn).Value; if (mv.IsNullOrWhiteSpace()) { continue; } if (fn == "Description" || fn == "Placeholder" || fn == "LookupDict" || fn == "Hint") { mv = OnLocalizeString(schema, fn, mv, isoLang); } result[fn] = mv; } } return(result); }
/// <summary> /// Makes CRUD Schema out of BSON document. The types of all fields are object as documents do not have /// a predictable type of every field (they are dynamic and can change form doc to doc) /// </summary> public virtual Schema InferSchemaFromBSONDocument(BSONDocument doc, string schemaName = null) { var defs = new List<Schema.FieldDef>(); foreach(var elm in doc) { var clrv = elm.ObjectValue; var tv = typeof(object); var def = new Schema.FieldDef(elm.Name, tv, new FieldAttribute[]{ new FieldAttribute(backendName: elm.Name) }); defs.Add( def ); } return new Schema(schemaName.IsNotNullOrWhiteSpace() ? schemaName : Guid.NewGuid().ToString(), true, defs.ToArray()); }
public static Schema ErlSchemaToCRUDSchema(string name, IConfigSectionNode erlSect) { var defs = new List<Schema.FieldDef>(); var isInsert = erlSect.AttrByName(CONFIG_INSERT_ATTR).ValueAsBool(false); var isUpdate = erlSect.AttrByName(CONFIG_UPDATE_ATTR).ValueAsBool(false); var isDelete = erlSect.AttrByName(CONFIG_DELETE_ATTR).ValueAsBool(false); var schDescr = erlSect.AttrByName(CONFIG_DESCR_ATTR).ValueAsString(); var isReadonly = !(isInsert || isUpdate || isDelete); var keyCount = 0; var nodeFields = erlSect.Children.Where(c => c.IsSameName(CONFIG_FIELD_SECTION)); foreach(var nodeField in nodeFields) { var cfg = new LaconicConfiguration(); cfg.CreateFromNode(nodeField); var node = cfg.Root; var fname = node.AttrByName(Configuration.CONFIG_NAME_ATTR).Value; var ftitle = node.AttrByName(CONFIG_TITLE_ATTR).Value; var fhint = node.AttrByName(CONFIG_DESCR_ATTR).ValueAsString(""); var isKey = node.AttrByName(CONFIG_KEY_ATTR).ValueAsBool(); var required = node.AttrByName(CONFIG_REQUIRED_ATTR).ValueAsBool(false); var type = node.AttrByName(CONFIG_TYPE_ATTR).Value; var clrType = mapErlTypeToCLR(type); var fmtdesc = node.AttrByName(CONFIG_FORMAT_DESCR_ATTR).Value; var dispFmt = node.AttrByName(CONFIG_DISPLAY_FORMAT_ATTR).Value; if (dispFmt != null && (dispFmt.Length < 3 || dispFmt.Substring(0, 3) != "{0:")) dispFmt = "{{0:{0}}}".Args(dispFmt); node.AddAttributeNode(CONFIG_TITLE_ATTR, ftitle); object minV = null; object maxV = null; var sv = node.AttrByName(CONFIG_MIN_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) minV = sv.AsType(clrType, true); sv = node.AttrByName(CONFIG_MAX_ATTR).Value; if (sv.IsNotNullOrWhiteSpace()) maxV = sv.AsType(clrType, true); var strDfltValue = node.AttrByName(CONFIG_DEFAULT_ATTR).ValueAsString(string.Empty); object dfltValue = null; if (clrType==typeof(string)) dfltValue = strDfltValue; else if (strDfltValue.IsNotNullOrWhiteSpace()) dfltValue = clrType==typeof(DateTime?) ? ((long)strDfltValue.AsType(typeof(long), false)).FromMicrosecondsSinceUnixEpochStart() : strDfltValue.AsType(clrType, false); if (isKey) keyCount++; List<string> vList = null; var values = node.Children.Where( c => c.IsSameName(CONFIG_VALUE_SECTION)); foreach(var vnode in values) { var code = vnode.AttrByName(CONFIG_CODE_ATTR).Value; var disp = vnode.AttrByName(CONFIG_DISPLAY_ATTR).Value; if (code.IsNullOrWhiteSpace()) continue; if (vList==null) vList = new List<string>(); if (disp.IsNullOrWhiteSpace()) vList.Add(code); else vList.Add("{0}: {1}".Args(code, disp)); } var caze = CharCase.AsIs; var ca = node.AttrByName(CONFIG_CASE_ATTR).Value; if (ca.EqualsOrdIgnoreCase("upper")) caze = CharCase.Upper; else if (ca.EqualsOrdIgnoreCase("lower")) caze = CharCase.Lower; var atr = new FieldAttribute( targetName: TargetedAttribute.ANY_TARGET, backendName: fname, backendType: type, storeFlag: StoreFlag.LoadAndStore, key: isKey, required: required, dflt: dfltValue, min: minV, max: maxV, charCase: caze, visible: node.AttrByName(CONFIG_VISIBLE_ATTR).ValueAsBool(true), maxLength: node.AttrByName(CONFIG_LEN_ATTR).ValueAsInt(0), description: fmtdesc.IsNullOrEmpty() ? fhint : "{0}\nFormat: {1}".Args(fhint,fmtdesc), //Parsing.Utils.ParseFieldNameToDescription(ftitle, true), formatRegExp: node.AttrByName(CONFIG_FORMAT_ATTR).Value, formatDescr: fmtdesc, displayFormat: dispFmt, valueList: vList==null ? null : string.Join(",", vList),//"CAR: Car Driver,SMK: Smoker, REL: Religious, CNT: Country music lover, GLD: Gold collector" metadata: node.ToLaconicString()); var def = new Schema.FieldDef(fname, clrType, new []{atr}); defs.Add( def ); }//for fields var result = new Schema(name, isReadonly, defs.ToArray()); if (schDescr.IsNotNullOrWhiteSpace()) result.ExtraData[CONFIG_DESCR_ATTR] = schDescr; result.ExtraData[SCHEMA_KEY_COUNT] = keyCount; result.ExtraData[Schema.EXTRA_SUPPORTS_INSERT_ATTR] = isInsert; result.ExtraData[Schema.EXTRA_SUPPORTS_UPDATE_ATTR] = isUpdate; result.ExtraData[Schema.EXTRA_SUPPORTS_DELETE_ATTR] = isDelete; return result; }