private static void ErrorWhenSpecified(ValueKinds errorOnKinds, XArray source, bool[] couldNotConvert, string errorContextMessage)
        {
            // If not erroring on anything, nothing to check
            if (errorOnKinds == ValueKinds.None)
            {
                return;
            }

            // TODO: Use table failure logs. Log should track absolute row count to improve message because this is an IColumn and can't tell.
            if (errorOnKinds == ValueKinds.InvalidOrNull)
            {
                if (couldNotConvert != null)
                {
                    throw new InvalidOperationException($"{errorContextMessage} failed for at least one value.");
                }
            }
            else if (errorOnKinds == ValueKinds.Invalid)
            {
                if (couldNotConvert != null && source.HasNulls)
                {
                    for (int i = 0; i < source.Count; ++i)
                    {
                        if (couldNotConvert[i] == true && !source.NullRows[source.Index(i)])
                        {
                            throw new InvalidOperationException($"{errorContextMessage} failed for at least one value.");
                        }
                    }
                }
            }
            else
            {
                throw new NotImplementedException(errorOnKinds.ToString());
            }
        }
Esempio n. 2
0
        public IXColumn Build(IXTable source, XDatabaseContext context)
        {
            // Column and ToType are required
            IXColumn column = context.Parser.NextColumn(source, context);
            Type     toType = context.Parser.NextType();

            // ErrorOn, DefaultValue, and ChangeToDefaultOn are optional
            ValueKinds errorOn           = ValueKindsDefaults.ErrorOn;
            object     defaultValue      = null;
            ValueKinds changeToDefaultOn = ValueKindsDefaults.ChangeToDefault;

            if (context.Parser.HasAnotherArgument)
            {
                // Parse ErrorOn if there's another argument
                errorOn = context.Parser.NextEnum <ValueKinds>();

                // If there's another argument, both of the last two are required
                if (context.Parser.HasAnotherArgument)
                {
                    defaultValue      = context.Parser.NextLiteralValue();
                    changeToDefaultOn = context.Parser.NextEnum <ValueKinds>();
                }
            }

            return(CastedColumn.Build(source, column, toType, errorOn, defaultValue, changeToDefaultOn));
        }
Esempio n. 3
0
        private CastedColumn(IXColumn column, Type targetType, ValueKinds errorOnKinds = ValueKindsDefaults.ErrorOn, object defaultValue = null, ValueKinds changeToDefaultKinds = ValueKindsDefaults.ChangeToDefault)
        {
            _column       = column;
            ColumnDetails = column.ColumnDetails.ChangeType(targetType);
            _converter    = TypeConverterFactory.GetConverter(column.ColumnDetails.Type, targetType, errorOnKinds, defaultValue, changeToDefaultKinds);

            _targetType           = targetType;
            _errorOnKinds         = errorOnKinds;
            _defaultValue         = defaultValue;
            _changeToDefaultKinds = changeToDefaultKinds;
        }
        public static Func <XArray, XArray> TryGetConverter(Type sourceType, Type targetType, ValueKinds errorOn = ValueKindsDefaults.ErrorOn, object defaultValue = null, ValueKinds changeToDefault = ValueKindsDefaults.ChangeToDefault)
        {
            // Error if there's a default but nothing will be changed to it
            if (defaultValue != null && changeToDefault == ValueKinds.None)
            {
                throw new ArgumentException("Cast with a default value must have [ChangeToDefaultOn] not 'None'.");
            }

            // Convert the defaultValue to the right type
            defaultValue = ConvertSingle(defaultValue, targetType);

            Func <XArray, XArray> converter = null;

            // See if the target type provides conversion
            ITypeProvider targetTypeProvider = TypeProviderFactory.TryGet(targetType);

            if (targetTypeProvider != null)
            {
                converter = NegatedTryConvertToConverter(targetTypeProvider.TryGetNegatedTryConvert(sourceType, targetType, defaultValue), "", errorOn, changeToDefault);
                if (converter != null)
                {
                    return(converter);
                }
            }

            // See if the source type provides conversion
            ITypeProvider sourceTypeProvider = TypeProviderFactory.TryGet(sourceType);

            if (sourceTypeProvider != null)
            {
                converter = NegatedTryConvertToConverter(sourceTypeProvider.TryGetNegatedTryConvert(sourceType, targetType, defaultValue), "", errorOn, changeToDefault);
                if (converter != null)
                {
                    return(converter);
                }
            }

            // Try again with implicit string to String8 conversion
            if (sourceType == typeof(string))
            {
                converter = TryGetConverter(typeof(String8), targetType, errorOn, defaultValue, changeToDefault);

                // If found, encode the string to String8 conversion and then the String8 to target conversion
                if (converter != null)
                {
                    Func <XArray, XArray> innerConverter = GetConverter(typeof(string), typeof(String8), errorOn, defaultValue, changeToDefault);
                    return((xarray) => converter(innerConverter(xarray)));
                }
            }

            return(null);
        }
        public static Func <XArray, XArray> GetConverter(Type sourceType, Type targetType, ValueKinds errorOn = ValueKindsDefaults.ErrorOn, object defaultValue = null, ValueKinds changeToDefault = ValueKindsDefaults.ChangeToDefault)
        {
            Func <XArray, XArray> converter = TryGetConverter(sourceType, targetType, errorOn, defaultValue, changeToDefault);

            if (converter == null)
            {
                throw new ArgumentException($"No converter available from {sourceType.Name} to {targetType.Name}.");
            }
            return(converter);
        }
        public static Func <XArray, XArray> NegatedTryConvertToConverter(NegatedTryConvert negatedTryConvert, string errorContextMessage, ValueKinds errorOn = ValueKindsDefaults.ErrorOn, ValueKinds changeToDefault = ValueKindsDefaults.ChangeToDefault)
        {
            if (negatedTryConvert == null)
            {
                return(null);
            }

            Array result;

            bool[] couldNotConvert;
            bool[] buffer = null;

            if (changeToDefault == ValueKinds.None)
            {
                // Invalid/Null/Empty -> Null, so couldNotConvert becomes IsNull
                return((values) =>
                {
                    couldNotConvert = negatedTryConvert(values, out result);
                    ErrorWhenSpecified(errorOn, values, couldNotConvert, errorContextMessage);
                    return XArray.All(result, values.Count, MergeNulls(values, couldNotConvert, ref buffer), values.Selector.IsSingleValue);
                });
            }
            else if (changeToDefault == ValueKinds.Invalid)
            {
                // Invalid -> Default, so keep nulls from source
                return((values) =>
                {
                    couldNotConvert = negatedTryConvert(values, out result);
                    ErrorWhenSpecified(errorOn, values, couldNotConvert, errorContextMessage);
                    return XArray.All(result, values.Count, XArray.RemapNulls(values, ref couldNotConvert), values.Selector.IsSingleValue);
                });
            }
            else if (changeToDefault == ValueKinds.InvalidOrNull)
            {
                // Invalid/Null/Empty -> Default, so negate all nulls
                return((values) =>
                {
                    couldNotConvert = negatedTryConvert(values, out result);
                    ErrorWhenSpecified(errorOn, values, couldNotConvert, errorContextMessage);
                    return XArray.All(result, values.Count, null, values.Selector.IsSingleValue);
                });
            }
            else
            {
                throw new NotImplementedException(changeToDefault.ToString());
            }
        }
Esempio n. 7
0
 public static Func <XArray, XArray> TryGetConverter(Type sourceType, Type targetType, ValueKinds errorOnKinds, object defaultValue, ValueKinds changeToDefaultKinds)
 {
     return(TypeConverterFactory.TryGetConverter(sourceType, targetType, errorOnKinds, defaultValue, changeToDefaultKinds));
 }
Esempio n. 8
0
        public static IXColumn Build(IXTable source, IXColumn column, Type targetType, ValueKinds errorOnKinds = ValueKindsDefaults.ErrorOn, object defaultValue = null, ValueKinds changeToDefaultKinds = ValueKindsDefaults.ChangeToDefault)
        {
            // If the column is already the right type, just return it
            if (column.ColumnDetails.Type == targetType)
            {
                return(column);
            }

            // Convert constants individually
            if (column.IsConstantColumn())
            {
                XArray array = column.ValuesGetter()();
                return(new ConstantColumn(source, TypeConverterFactory.ConvertSingle(array.Array.GetValue(0), targetType), targetType));
            }

            // Otherwise, wrap in a CastedColumn [Enums are automatically converted just once]
            return(new CastedColumn(column, targetType, errorOnKinds, defaultValue, changeToDefaultKinds));
        }