Ejemplo n.º 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);
        }
Ejemplo n.º 2
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));
 }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        public static bool HasMappingOrCast(
            object value,
            SpecificationValue.DataType desiredType,
            SpecificationValueSettings settings,
            out object result)
        {
            result = value;

            if (value == null)
            {
                return(false);
            }

            Type type = value.GetType();

            if (Mapping.ContainsKey(type))
            {
                SpecificationValue.DataType actualType = Mapping[type];

                if (actualType == desiredType)
                {
                    return(true);
                }
            }

            if (settings.AllowCast)
            {
                switch (desiredType)
                {
                case SpecificationValue.DataType.DateTime:
                {
                    if (value is string str)
                    {
                        if (DateTime.TryParseExact(
                                str,
                                "u",
                                DateTimeFormatInfo.InvariantInfo,
                                DateTimeStyles.AssumeUniversal,
                                out DateTime dtv))
                        {
                            result = dtv;
                            return(true);
                        }
                    }
                }
                break;

                case SpecificationValue.DataType.Int:
                {
                    if (value is float fv && Math.Round(fv) == fv)
                    {
                        result = (int)fv;
                        return(true);
                    }

                    if (value is string str)
                    {
                        if (int.TryParse(str, out int iv))
                        {
                            result = iv;
                            return(true);
                        }
                    }
                }
                break;

                case SpecificationValue.DataType.Float:
                {
                    if (value is int iv)
                    {
                        result = (float)iv;
                        return(true);
                    }

                    if (value is string str)
                    {
                        if (float.TryParse(str, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out float fv))
                        {
                            result = fv;
                            return(true);
                        }
                    }
                }
                break;

                case SpecificationValue.DataType.String:
                {
                    if (value is int iv)
                    {
                        result = iv.ToString("D");
                    }
                    else if (value is float fv)
                    {
                        result = fv.ToString("F");
                    }
                    else if (value is DateTime dtv)
                    {
                        result = dtv.ToString("u");
                    }
                    else
                    {
                        result = value.ToString();
                    }

                    return(true);
                }

                default: return(false);
                }
            }

            return(false);
        }