예제 #1
0
        private static SpecificationValue ParseSpecificationValue(
            XElement element,
            XmlSchema schema,
            XmlSchemaSet schemaSet,
            string ns)
        {
            SpecificationValue value;
            string             isRef = GetRef(element, ns);

            if (isRef != null)
            {
                element.Validate(
                    schema.SchemaTypes[new XmlQualifiedName("valueReference", ns)],
                    schemaSet,
                    (sender, args) => throw new ArgumentException(args.Message, args.Exception));

                value = SpecificationValue.Ref(isRef);
            }
            else
            {
                SpecificationValue.Multiplicity mul  = GetMul(element, ns);
                SpecificationValue.DataType     type = GetType(element, ns);
                string[] values = GetValues(element, ns).ToArray();

                if (values.Length <= 1)
                {
                    element.Validate(
                        schema.SchemaTypes[new XmlQualifiedName("valueSingle", ns)],
                        schemaSet,
                        (sender, args) => throw new ArgumentException(args.Message, args.Exception));
                }
                else
                {
                    element.Validate(
                        schema.SchemaTypes[new XmlQualifiedName("valueMultiple", ns)],
                        schemaSet,
                        (sender, args) => throw new ArgumentException(args.Message, args.Exception));
                }

                SpecificationValueSettings settings = ValueSettings.GetOrAdd(
                    (int)mul * 1000 + (int)type,
                    i => new SpecificationValueSettings
                {
                    AllowCast           = true,
                    DefaultMultiplicity = mul,
                    IncludeDetails      = true,
                    ExpectedType        = type
                });

                if (!SpecificationValue.TryFrom(values, settings, out value, out string error))
                {
                    throw new ArgumentException(error);
                }
            }

            return(value);
        }
예제 #2
0
        public static SpecificationValue Ref(string key)
        {
            SpecificationValue result = new SpecificationValue();

            result.Values      = new[] { key };
            result.IsReference = true;

            return(result);
        }
예제 #3
0
 public static bool TryFrom(
     string key,
     IReadOnlyDictionary <string, object> values,
     SpecificationValueSettings settings,
     out SpecificationValue result,
     out string error)
 {
     return(TryFrom(key, values, settings, new HashSet <SpecificationValue>(), out result, out error));
 }
예제 #4
0
 private static void SetType(Type type, SpecificationValue result, string paramName)
 {
     if (TypeHelper.Mapping.ContainsKey(type))
     {
         result.ValueType = TypeHelper.Mapping[type];
     }
     else
     {
         throw new ArgumentException(
                   string.Format(
                       SpecAbsRes.SpecificationValueTypeNotSupported,
                       type,
                       string.Join(", ", TypeHelper.Mapping.Keys)),
                   paramName);
     }
 }
예제 #5
0
        public static SpecificationValue Single(object value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            SpecificationValue result = new SpecificationValue();

            result.ValueMultiplicity = Multiplicity.AllOf;
            result.Values            = new[] { value };

            SetType(value.GetType(), result, nameof(value));

            return(result);
        }
예제 #6
0
        public static string Serialize(this SpecificationValue value, int index = 0)
        {
            switch (value.ValueType)
            {
            case SpecificationValue.DataType.Int:
                return(value.Values.OfType <int>().ElementAt(index).ToString("D"));

            case SpecificationValue.DataType.Float:
                return(value.Values.OfType <float>().ElementAt(index).ToString("F"));

            case SpecificationValue.DataType.DateTime:
                return(value.Values.OfType <DateTime>().ElementAt(index).ToUniversalTime().ToString("u"));

            case SpecificationValue.DataType.String:
                return(value.Values.ElementAt(index).ToString());

            default: throw new InvalidOperationException();
            }
        }
예제 #7
0
        private static Specification FromXmlValidated(
            XElement element,
            XmlSchema schema,
            XmlSchemaSet schemaSet,
            string ns)
        {
            if (element.Name.LocalName == Consts.And || element.Name.LocalName == Consts.Or)
            {
                List <Specification> inner =
                    new List <Specification>(element.Elements().Count(el => el.Name.Namespace == ns));

                foreach (XElement item in element.Elements().Where(el => el.Name.Namespace == ns))
                {
                    inner.Add(FromXmlValidated(item, schema, schemaSet, ns));
                }

                if (element.Name.LocalName == Consts.And)
                {
                    return(new AndSpecification(inner));
                }

                if (element.Name.LocalName == Consts.Or)
                {
                    return(new OrSpecification(inner));
                }
            }

            if (element.Name.LocalName == Consts.Not)
            {
                Specification inner = FromXmlValidated(element.Elements().Single(), schema, schemaSet, ns);
                return(new NotSpecification(inner));
            }

            if (element.Name.LocalName == Consts.HasValue)
            {
                return(new HasValueSpecification(GetKey(element, ns)));
            }

            if (element.Name.LocalName == Consts.Ref)
            {
                return(new ReferenceSpecification(GetKey(element, ns)));
            }

            if (element.Name.LocalName == Consts.True)
            {
                return(ConstantSpecification.True);
            }

            if (element.Name.LocalName == Consts.False)
            {
                return(ConstantSpecification.False);
            }

            if (Consts.CompareOperators.Contains(element.Name.LocalName))
            {
                string             key   = GetKey(element, ns);
                SpecificationValue value = ParseSpecificationValue(element, schema, schemaSet, ns);

                if (element.Name.LocalName == Consts.Eq)
                {
                    return(new EqualSpecification(key, value));
                }

                if (element.Name.LocalName == Consts.Gt)
                {
                    return(new GreaterSpecification(key, value));
                }

                if (element.Name.LocalName == Consts.Ge)
                {
                    return(new GreaterOrEqualSpecification(key, value));
                }

                if (element.Name.LocalName == Consts.Lt)
                {
                    return(new LessSpecification(key, value));
                }

                if (element.Name.LocalName == Consts.Le)
                {
                    return(new LessOrEqualSpecification(key, value));
                }
            }

            throw new NotImplementedException();
        }
예제 #8
0
        private static void CollectionFromValidated(
            SpecificationsCollection collection,
            XElement element,
            XmlSchema schema,
            XmlSchemaSet schemaSet,
            string ns)
        {
            var values = element.Element(XName.Get(Consts.RefValuesCollection, ns));

            if (values != null)
            {
                foreach (XElement add in values.Elements(XName.Get(Consts.Add, ns)))
                {
                    string             key   = GetKey(add, ns);
                    SpecificationValue value = ParseSpecificationValue(add, schema, schemaSet, ns);
                    collection.ValuesForReference.Add(key, value);
                }

                foreach (XElement runtime in values.Elements(XName.Get(Consts.Runtime, ns)))
                {
                    string key = GetKey(runtime, ns);
                    collection.AllowedRuntimeValueReferenceKeys.Add(key);
                }
            }

            var definitions = element.Element(XName.Get(Consts.RefSpecCollection, ns));

            if (definitions != null)
            {
                foreach (XElement add in definitions.Elements(XName.Get(Consts.Add, ns)))
                {
                    string        key  = GetKey(add, ns);
                    Specification spec = FromXmlValidated(
                        add.Elements().First(e => e.Name.Namespace == ns),
                        schema,
                        schemaSet,
                        ns);
                    collection.SpecificationsForReference.Add(key, spec);
                }

                foreach (XElement runtime in definitions.Elements(XName.Get(Consts.Runtime, ns)))
                {
                    string key = GetKey(runtime, ns);
                    collection.AllowedRuntimeSpecificationReferenceKeys.Add(key);
                }
            }

            var specifications = element.Element(XName.Get(Consts.SpecCollection, ns));

            if (specifications != null)
            {
                foreach (XElement add in specifications.Elements(XName.Get(Consts.Add, ns)))
                {
                    string        key  = GetKey(add, ns);
                    Specification spec = FromXmlValidated(
                        add.Elements().First(e => e.Name.Namespace == ns),
                        schema,
                        schemaSet,
                        ns);
                    collection.Specifications.Add(key, spec);
                }
            }
        }
예제 #9
0
        public static bool TryFrom(object value, SpecificationValueSettings settings, out SpecificationValue result, out string error)
        {
            error  = null;
            result = null;

            if (value == null)
            {
                if (settings.IncludeDetails)
                {
                    error = SpecAbsRes.SpecValueTryFromNull;
                }

                return(false);
            }

            Type type = value.GetType();

            if (value is SpecificationValue sv)
            {
                result = sv;
                return(true);
            }

            if (TypeHelper.Mapping.ContainsKey(type))
            {
                if (!settings.ExpectedType.HasValue || TypeHelper.Mapping[type] == settings.ExpectedType.Value)
                {
                    result = Single(value);
                    return(true);
                }

                if (TypeHelper.HasMappingOrCast(value, settings.ExpectedType.Value, settings, out object casted))
                {
                    result = Single(casted);
                    return(true);
                }

                result = null;
                if (settings.IncludeDetails)
                {
                    error = string.Format(SpecAbsRes.SpecValueAssumedTypeError, settings.ExpectedType.Value, value, type);
                }

                return(false);
            }

            if (value is IEnumerable en)
            {
                result = new SpecificationValue();
                result.ValueMultiplicity = settings.DefaultMultiplicity;
                List <object> resultValues = new List <object>(5);

                int j = 0;
                foreach (object o in en)
                {
                    if (o == null)
                    {
                        if (settings.IncludeDetails)
                        {
                            error = string.Format(SpecAbsRes.ValueSpecificationElementNull, j);
                        }

                        result = null;
                        return(false);
                    }

                    j++;
                    resultValues.Add(o);
                }

                if (resultValues.Count == 0)
                {
                    if (settings.IncludeDetails)
                    {
                        error = SpecAbsRes.ValueSpecificationZeroCount;
                    }

                    result = null;
                    return(false);
                }

                result.Values = resultValues;
                Type itemType = null;

                if (settings.ExpectedType.HasValue)
                {
                    itemType         = TypeHelper.Mapping.Single(p => p.Value == settings.ExpectedType.Value).Key;
                    result.ValueType = settings.ExpectedType.Value;
                }

                for (int i = 0; i < resultValues.Count; i++)
                {
                    Type currentType = resultValues[i].GetType();

                    if (itemType != null)
                    {
                        if (itemType != currentType)
                        {
                            if (TypeHelper.HasMappingOrCast(resultValues[i], result.ValueType, settings, out object casted))
                            {
                                resultValues[i] = casted;
                                currentType     = casted.GetType();
                            }
                            else
                            {
                                if (settings.IncludeDetails)
                                {
                                    if (settings.ExpectedType.HasValue)
                                    {
                                        error = string.Format(SpecAbsRes.SpecValueAssumedTypeError, settings.ExpectedType.Value, resultValues[i], currentType);
                                    }
                                    else
                                    {
                                        error = SpecAbsRes.ValueSpecificationMixedTypes;
                                    }
                                }

                                result = null;
                                return(false);
                            }
                        }
                    }

                    itemType = currentType;

                    if (i == 0 && !settings.ExpectedType.HasValue)
                    {
                        if (TypeHelper.Mapping.ContainsKey(itemType))
                        {
                            result.ValueType = TypeHelper.Mapping[itemType];
                        }
                        else
                        {
                            if (settings.IncludeDetails)
                            {
                                error = string.Format(
                                    SpecAbsRes.SpecificationValueTypeNotSupportedElement,
                                    itemType,
                                    i,
                                    string.Join(", ", TypeHelper.Mapping.Keys));
                            }

                            result = null;
                            return(false);
                        }
                    }
                }

                return(true);
            }

            if (settings.IncludeDetails)
            {
                error = string.Format(
                    SpecAbsRes.SpecificationValueTypeNotSupported,
                    type,
                    string.Join(", ", TypeHelper.Mapping.Keys));
            }

            return(false);
        }
예제 #10
0
        private static bool TryFrom(
            string key,
            IReadOnlyDictionary <string, object> values,
            SpecificationValueSettings settings,
            HashSet <SpecificationValue> processed,
            out SpecificationValue result,
            out string error)
        {
            result = null;
            error  = null;
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (values == null)
            {
                throw new ArgumentNullException(nameof(values));
            }
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            if (processed == null)
            {
                throw new ArgumentNullException(nameof(processed));
            }

            if (values.ContainsKey(key))
            {
                object value = values[key];

                if (TryFrom(value, settings, out result, out error))
                {
                    if (result.IsReference)
                    {
                        if (processed.Contains(result))
                        {
                            if (settings.IncludeDetails)
                            {
                                processed.Add(result); // Add to display correct message
                                error = SpecAbsRes.SpecValueFromCircular + string.Format(
                                    SpecAbsRes.SpecValueFromProcessed,
                                    string.Join(", ", processed));
                            }

                            result = null;
                            return(false);
                        }

                        processed.Add(result);

                        string next = result.Values.Single().ToString();

                        bool tryNext = TryFrom(next, values, settings, processed, out var nextResult, out error);

                        if (tryNext)
                        {
                            result = nextResult;
                        }

                        return(tryNext);
                    }

                    return(true);
                }

                if (settings.IncludeDetails && processed.Any())
                {
                    error += string.Format(SpecAbsRes.SpecValueFromProcessed, string.Join(", ", processed));
                }

                return(false);
            }

            if (settings.IncludeDetails)
            {
                error = string.Format(SpecAbsRes.KeyValueSpecificationMissingKey, key);

                if (processed.Any())
                {
                    error += string.Format(
                        SpecAbsRes.SpecValueFromProcessed,
                        string.Join(", ", processed));
                }
            }

            return(false);
        }