Example #1
0
            private void ctor(string name, int order, Type type, IEnumerable <FieldAttribute> attrs, PropertyInfo memberInfo = null)
            {
                if (name.IsNullOrWhiteSpace() || type == null || attrs == null)
                {
                    throw new DataException(StringConsts.ARGUMENT_ERROR + "FieldDef.ctor(..null..)");
                }

                m_Name  = name;
                m_Order = order;
                m_Type  = type;
                m_Attrs = new List <FieldAttribute>(attrs);

                if (m_Attrs.Count < 1)
                {
                    throw new DataException(StringConsts.CRUD_FIELDDEF_ATTR_MISSING_ERROR.Args(name));
                }

                //add ANY_TARGET attribute
                if (!m_Attrs.Any(a => a.TargetName == TargetedAttribute.ANY_TARGET))
                {
                    var isAnyKey = m_Attrs.Any(a => a.Key);
                    var ata      = new FieldAttribute(FieldAttribute.ANY_TARGET, key: isAnyKey);
                    m_Attrs.Add(ata);
                }

                m_MemberInfo = memberInfo;

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    m_NonNullableType = type.GetGenericArguments()[0];
                }
                else
                {
                    m_NonNullableType = type;
                }

                m_AnyTargetKey = this[null].Key;
            }
Example #2
0
        protected Exception CheckMinMax(FieldAttribute atr, string fName, IComparable val)
        {
            if (atr.Min != null)
            {
                var bound = atr.Min as IComparable;
                if (bound != null)
                {
                    var tval = val.GetType();

                    bound = Convert.ChangeType(bound, tval) as IComparable;

                    if (val.CompareTo(bound) < 0)
                    {
                        return(new FieldValidationException(Schema.Name, fName, StringConsts.CRUD_FIELD_VALUE_MIN_BOUND_ERROR));
                    }
                }
            }

            if (atr.Max != null)
            {
                var bound = atr.Max as IComparable;
                if (bound != null)
                {
                    var tval = val.GetType();

                    bound = Convert.ChangeType(bound, tval) as IComparable;

                    if (val.CompareTo(bound) > 0)
                    {
                        return(new FieldValidationException(Schema.Name, fName, StringConsts.CRUD_FIELD_VALUE_MAX_BOUND_ERROR));
                    }
                }
            }

            return(null);
        }
Example #3
0
        protected virtual Exception CheckValueMinMax(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (!(value is IComparable val))
            {
                return(null);
            }

            if (atr.Min != null)
            {
                var bound = atr.Min as IComparable;
                if (bound != null)
                {
                    var tval = val.GetType();

                    bound = Convert.ChangeType(bound, tval) as IComparable;

                    if (val.CompareTo(bound) < 0)
                    {
                        return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MIN_BOUND_ERROR));
                    }
                }
            }

            if (atr.Max != null)
            {
                var bound = atr.Max as IComparable;
                if (bound != null)
                {
                    var tval = val.GetType();

                    bound = Convert.ChangeType(bound, tval) as IComparable;

                    if (val.CompareTo(bound) > 0)
                    {
                        return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MAX_BOUND_ERROR));
                    }
                }
            }

            return(null);
        }
Example #4
0
        protected virtual Exception CheckValueList(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (atr.HasValueList)//check dictionary
            {
                var parsed = atr.ParseValueList();
                if (isSimpleKeyStringMap(parsed))
                {
                    var fv = value.ToString();
                    if (!parsed.ContainsKey(fv))
                    {
                        return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_IS_NOT_IN_LIST_ERROR.Args(fv.TakeFirstChars(16, ".."))));
                    }
                }
            }

            //check dynamic value list
            var dynValueList = GetDynamicFieldValueList(fdef, targetName, null);

            if (dynValueList != null)//check dictionary
            {
                var fv = value.ToString();
                if (!dynValueList.ContainsKey(fv))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_IS_NOT_IN_LIST_ERROR.Args(fv.TakeFirstChars(16, ".."))));
                }
            }

            return(null);
        }
Example #5
0
        protected virtual Exception CheckValueIValidatable(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (value is IValidatable validatable)
            {
                return(validatable.Validate(targetName));
            }

            if (value is IDictionary dict)//Dictionary<string, IValidatable>
            {
                foreach (var v in dict.Values)
                {
                    if (v is IValidatable vv)
                    {
                        var error = vv.Validate(targetName);
                        if (error != null)
                        {
                            return(error);
                        }
                    }
                }
            }
            else if (value is IEnumerable enm)//List<IValidatable>, IValidatable[]
            {
                foreach (var v in enm)
                {
                    if (!(v is IValidatable vv))
                    {
                        continue;
                    }
                    var error = vv.Validate(targetName);
                    if (error != null)
                    {
                        return(error);
                    }
                }
            }

            return(null);
        }
Example #6
0
        protected virtual Exception CheckValueKind(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (atr.Kind == DataKind.ScreenName)
            {
                if (!Azos.Text.DataEntryUtils.CheckScreenName(value.ToString()))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_SCREEN_NAME_ERROR));
                }
            }
            else if (atr.Kind == DataKind.EMail)
            {
                if (!Azos.Text.DataEntryUtils.CheckEMail(value.ToString()))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_EMAIL_ERROR));
                }
            }
            else if (atr.Kind == DataKind.Telephone)
            {
                if (!Azos.Text.DataEntryUtils.CheckTelephone(value.ToString()))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_PHONE_ERROR));
                }
            }

            return(null);
        }
Example #7
0
        protected virtual Exception CheckValueLength(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (atr.MinLength > 0)
            {
                if (value is IEnumerable <object> eobj && eobj.Count() < atr.MinLength)
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MIN_LENGTH_ERROR.Args(atr.MinLength)));
                }

                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 (value is IEnumerable <object> eobj && eobj.Count() > atr.MaxLength)
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_MAX_LENGTH_ERROR.Args(atr.MaxLength)));
                }

                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);
        }
Example #8
0
        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);
        }
Example #9
0
        private Schema(Type tdoc)
        {
            lock (s_TypeLatch)
            {
                if (s_TypeLatch.Contains(tdoc))
                {
                    throw new DataException(StringConsts.CRUD_TYPED_DOC_RECURSIVE_FIELD_DEFINITION_ERROR.Args(tdoc.FullName));
                }

                s_TypeLatch.Add(tdoc);
                try
                {
                    m_Name = tdoc.AssemblyQualifiedName;

                    var tattrs = tdoc.GetCustomAttributes(typeof(SchemaAttribute), false).Cast <SchemaAttribute>();
                    tattrs.ForEach(a => a.StopPropAssignmentTracking());
                    m_SchemaAttrs = new List <SchemaAttribute>(tattrs);

                    //20191026 DKh. Expand resource references in Descriptions
                    m_SchemaAttrs.ForEach(a => { a.ExpandResourceReferencesRelativeTo(tdoc, null); a.Seal(); });

                    m_FieldDefs = new OrderedRegistry <FieldDef>();
                    var props = GetFieldMembers(tdoc);
                    var order = 0;
                    foreach (var prop in props)
                    {
                        var fattrs = prop.GetCustomAttributes(typeof(FieldAttribute), false)
                                     .Cast <FieldAttribute>()
                                     .ToArray();

                        fattrs.ForEach(a => a.StopPropAssignmentTracking());

                        //Interpret [Field(CloneFromType)]
                        for (var i = 0; i < fattrs.Length; i++)
                        {
                            var attr = fattrs[i];

                            if (attr.CloneFromDocType == null)
                            {
                                //20190831 DKh. Expand resource references in Descriptions
                                attr.ExpandResourceReferencesRelativeTo(tdoc, prop.Name);
                                continue;
                            }

                            if (fattrs.Length > 1)
                            {
                                throw new DataException(StringConsts.CRUD_TYPED_DOC_SINGLE_CLONED_FIELD_ERROR.Args(tdoc.FullName, prop.Name));
                            }

                            var clonedSchema = Schema.GetForTypedDoc(attr.CloneFromDocType);
                            var clonedDef    = clonedSchema[prop.Name];
                            if (clonedDef == null)
                            {
                                throw new DataException(StringConsts.CRUD_TYPED_DOC_CLONED_FIELD_NOTEXISTS_ERROR.Args(tdoc.FullName, prop.Name));
                            }

                            fattrs = clonedDef.Attrs.ToArray();//replace these attrs from the cloned target
                            break;
                        }

                        FieldAttribute.FixupInheritedTargets($"{tdoc.Name}.{prop.Name}", fattrs);

                        var fdef = new FieldDef(prop.Name, order, prop.PropertyType, fattrs, prop);
                        m_FieldDefs.Register(fdef);

                        order++;
                    }
                    s_TypedRegistry.Register(this);
                    m_TypedDocType = tdoc;
                }
                finally
                {
                    s_TypeLatch.Remove(tdoc);
                }
            }//lock
        }
Example #10
0
        /// <summary>
        ///Dynamic value lists override static ones:
        /// * If a dynamic value list is null then hard coded ValueList is enforced if it is specified;
        /// * If a dynamic list is non-null then it is enforced if it is not blank, otherwise nothing is checked;
        /// Therefore: you may return an empty non-null dynamic list to prevent application of ValueList check for specific field/target
        /// </summary>
        protected virtual Exception CheckValueList(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            //try to obtain dynamic value list
            var dynValueList = GetDynamicFieldValueList(fdef, targetName, null);

            if (dynValueList != null)//check dynamic list is supplied
            {
                if (dynValueList.Count == 0)
                {
                    return(null);                //Nothing to check against; this is used to return empty list to override ValueList list
                }
                var fv = value.ToString();
                if (!dynValueList.ContainsKey(fv))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_IS_NOT_IN_LIST_ERROR.Args(fv.TakeFirstChars(9, ".."))));
                }
            }
            else if (atr.HasValueList)//check ValueList dictionary
            {
                var parsed = atr.ParseValueList();
                var fv     = value.ToString();
                if (!parsed.ContainsKey(fv))
                {
                    return(new FieldValidationException(Schema.DisplayName, fdef.Name, StringConsts.CRUD_FIELD_VALUE_IS_NOT_IN_LIST_ERROR.Args(fv.TakeFirstChars(9, ".."))));
                }
            }

            return(null);
        }
Example #11
0
        protected virtual Exception CheckValueLength(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (atr.MinLength < 1 && atr.MaxLength < 1)
            {
                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);
        }
Example #12
0
 internal FieldDescriptor(string name, Schema.FieldDef def, FieldAttribute atr)
 {
     TargetFieldName = name;
     FieldDef        = def;
     Attr            = atr;
 }
Example #13
0
        protected virtual ValidState CheckValueIValidatable(ValidState state, Schema.FieldDef fdef, FieldAttribute atr, object value, string scope)
        {
            //20200517 DKh using ObjectGraph.Scope()
            //--------------------------------------

            if (value is IValidatable validatable)
            {
                var got = ObjectGraph.Scope("Doc.CheckValueIValidatable.IVal", //name of the state machine
                                            this,                              //reference to cycle subject - the document itself
                                            validatable,                       //arg1
                                            state,                             //arg2
                                            GetInnerScope(fdef, scope),        //arg3
                                            body: validateIValidatable
                                            );                                 //machine
                return(got.OK ? got.result : state);
            }

            //precedence of IFs is important, IDictionary is IEnumerable
            if (value is IDictionary dict)//Dictionary<string, IValidatable>
            {
                var got = ObjectGraph.Scope("Doc.CheckValueIValidatable.IDict",
                                            this,
                                            dict,
                                            state,
                                            GetInnerScope(fdef, scope),
                                            body: validateIDictionary
                                            );
                return(got.OK ? got.result : state);
            }

            if (value is IEnumerable enm)//List<IValidatable>, IValidatable[]
            {
                var got = ObjectGraph.Scope("Doc.CheckValueIValidatable.IEnum",
                                            this,
                                            enm,
                                            state,
                                            GetInnerScope(fdef, scope),
                                            body: validateIEnumerable
                                            );
                return(got.OK ? got.result : state);
            }

            return(state);
        }
Example #14
0
        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 IRequiredCheck 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);
        }
Example #15
0
        protected virtual Exception CheckValueRegExp(string targetName, Schema.FieldDef fdef, FieldAttribute atr, object value)
        {
            if (atr.FormatRegExp.IsNotNullOrWhiteSpace())
            {
                //For those VERY RARE cases when RegExpFormat may need to be applied to complex types, i.e. StringBuilder
                //set the flag in metadata to true, otherwise regexp gets matched only for STRINGS
                var complex = atr.Metadata == null ? false
                                        : atr.Metadata
                              .AttrByName("validate-format-regexp-complex-types")
                              .ValueAsBool(false);
                if (complex || value is string)
                {
                    if (!System.Text.RegularExpressions.Regex.IsMatch(value.ToString(), atr.FormatRegExp))
                    {
                        return(new FieldValidationException(Schema.DisplayName, fdef.Name,
                                                            StringConsts.CRUD_FIELD_VALUE_REGEXP_ERROR.Args(atr.FormatDescription ?? "Input format: {0}".Args(atr.FormatRegExp))));
                    }
                }
            }

            return(null);
        }
Example #16
0
 public FieldDef(string name, Type type, FieldAttribute attr)
 {
     ctor(name, 0, type, new[] { attr }, null);
 }
Example #17
0
        private static void inheritAttribute(FieldAttribute parent, FieldAttribute self, string callSite)
        {
            //merge attributes from parent into self prop by prop
            foreach (var pi in ALL_PROPS)
            {
                if (pi.Name == nameof(MetadataContent))
                {
                    if (self.MetadataContent.IsNullOrWhiteSpace())
                    {
                        self.MetadataContent = parent.MetadataContent;
                    }
                    else if (parent.MetadataContent.IsNotNullOrWhiteSpace())
                    { //merge
                        var conf1 = ParseMetadataContent(parent.MetadataContent, callSite);
                        var conf2 = ParseMetadataContent(self.MetadataContent, callSite);

                        var merged = new LaconicConfiguration();
                        merged.CreateFromMerge(conf1, conf2);
                        self.MetadataContent = merged.SaveToString();
                    }

                    continue;
                }//metadata merge

                if (pi.Name == nameof(ValueList))
                {
                    if (self.ValueList == null && self.PropertyWasAssigned(nameof(ValueList)))//explicit reset
                    {
                        self.ValueList = null;
                        continue;
                    }
                    else if (!self.HasValueList)
                    {
                        self.ValueList = parent.ValueList;
                    }
                    else if (parent.HasValueList)
                    { //merge
                        var vl1 = parent.ParseValueList(true);
                        var vl2 = self.ParseValueList(true);

                        vl2.Append(vl1);//merge missing in self from parent



                        //remove all that start with REMOVE
                        // to remove a key include an override with:  `keyABC: #del#` (item keyed on `keyABC` will be removed)
                        const string DELETE = "#del#";
                        vl2.Where(kvp => kvp.Value.AsString().EqualsOrdIgnoreCase(DELETE))
                        .ToArray()
                        .ForEach(kvp => vl2.Remove(kvp.Key));

                        self.ValueList = BuildValueListString(vl2);//reconstitute jsonmap back into string
                    }

                    continue;
                }

                if (self.PropertyWasAssigned(pi.Name))
                {
                    continue;                           //was overridden
                }
                pi.SetValue(self, pi.GetValue(parent)); //set value
            }
        }