예제 #1
0
        public override ExprNode Validate(ExprValidationContext validationContext)
        {
            if (ChildNodes.Length == 0 || ChildNodes.Length > 2) {
                throw new ExprValidationException("Cast function node must have one or two child expressions");
            }

            var fromType = ChildNodes[0].Forge.EvaluationType;
            var classIdentifier = ClassIdentifierWArray.ClassIdentifier;
            var classIdentifierInvariant = classIdentifier.Trim();
            var arrayDimensions = ClassIdentifierWArray.ArrayDimensions;

            // Local function to match a class identifier
            bool MatchesClassIdentifier(string identifier)
            {
                return string.Equals(
                    classIdentifierInvariant,
                    identifier,
                    StringComparison.InvariantCultureIgnoreCase);
            }
            
            // determine date format parameter
            var namedParams =
                ExprNodeUtilityValidate.GetNamedExpressionsHandleDups(ChildNodes);
            ExprNodeUtilityValidate.ValidateNamed(namedParams, new[] {"dateformat"});
            var dateFormatParameter = namedParams.Get("dateformat");
            if (dateFormatParameter != null) {
                ExprNodeUtilityValidate.ValidateNamedExpectType(
                    dateFormatParameter,
                    new[] {
                        typeof(string), 
                        typeof(DateFormat), 
                        typeof(DateTimeFormat)
                    });
            }

            // identify target type
            // try the primitive names including "string"
            SimpleTypeCaster caster;
            var targetType = TypeHelper.GetPrimitiveTypeForName(classIdentifier.Trim());
            if (!ClassIdentifierWArray.IsArrayOfPrimitive) {
                targetType = targetType.GetBoxedType();
            }

            targetType = ApplyDimensions(targetType);

            bool numeric;
            CasterParserComputerForge casterParserComputerForge = null;
            if (dateFormatParameter != null) {
                if (fromType != typeof(string)) {
                    throw new ExprValidationException(
                        "Use of the '" +
                        dateFormatParameter.ParameterName +
                        "' named parameter requires a string-type input");
                }

                if (targetType == null) {
                    try {
                        targetType = TypeHelper.GetClassForName(
                            classIdentifier.Trim(),
                            validationContext.ImportService.ClassForNameProvider);
                        targetType = ApplyDimensions(targetType);
                    }
                    catch (TypeLoadException) {
                        // expected
                    }
                }

                // dynamic or static date format
                numeric = false;
                caster = null;

                if (targetType == typeof(DateTimeEx) ||
                    MatchesClassIdentifier("calendar") ||
                    MatchesClassIdentifier("dateTimeEx")) {
                    targetType = typeof(DateTimeEx);

                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeExIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge = new StringToDateTimExWStaticFormatComputer(
                            desc.StaticDateFormat,
                            TimeZoneInfo.Utc); // Note how code-generation does not use the default time zone
                    }
                    else {
                        casterParserComputerForge = new StringToDateTimeExWExprFormatComputer(
                            desc.DynamicDateFormat,
                            TimeZoneInfo.Utc);
                    }
                }
                else if (targetType == typeof(DateTimeOffset) ||
                         targetType == typeof(DateTimeOffset?) ||
                         MatchesClassIdentifier("dto") ||
                         MatchesClassIdentifier("datetimeoffset")) {
                    targetType = typeof(DateTimeOffset);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeOffsetIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge =
                            new StringToDateTimeOffsetWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge =
                            new StringToDateTimeOffsetWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else if (targetType == typeof(DateTime) ||
                         targetType == typeof(DateTime?) ||
                         MatchesClassIdentifier("datetime")) {
                    targetType = typeof(DateTime);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToDateTimeIsoFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge =
                            new StringToDateTimeWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge =
                            new StringToDateTimeWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else if (targetType == typeof(long) || targetType == typeof(long?)) {
                    targetType = typeof(long);
                    var desc = ValidateDateFormat(dateFormatParameter, validationContext);
                    if (desc.IsIso8601Format) {
                        casterParserComputerForge = new StringToLongWStaticISOFormatComputer();
                    }
                    else if (desc.StaticDateFormat != null) {
                        casterParserComputerForge = new StringToLongWStaticFormatComputer(desc.StaticDateFormat);
                    }
                    else {
                        casterParserComputerForge = new StringToLongWExprFormatComputerForge(desc.DynamicDateFormat);
                    }
                }
                else {
                    throw new ExprValidationException(
                        "Use of the '" +
                        dateFormatParameter.ParameterName +
                        "' named parameter requires a target type of long, DateTime, DateTimeOffset or DateEx");
                }
            }
            else if (targetType != null) {
                targetType = targetType.GetBoxedType();
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = caster.IsNumericCast;
            }
            else if (MatchesClassIdentifier("bigint") || MatchesClassIdentifier("biginteger")) {
                targetType = typeof(BigInteger);
                targetType = ApplyDimensions(targetType);
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = true;
            }
            else if (MatchesClassIdentifier("decimal")) {
                targetType = typeof(decimal);
                targetType = ApplyDimensions(targetType);
                caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                numeric = true;
            }
            else {
                try {
                    targetType = TypeHelper.GetClassForName(
                        classIdentifier.Trim(),
                        validationContext.ImportService.ClassForNameProvider);
                }
                catch (TypeLoadException e) {
                    throw new ExprValidationException(
                        "Class as listed in cast function by name '" + classIdentifier + "' cannot be loaded",
                        e);
                }

                targetType = ApplyDimensions(targetType);
                numeric = targetType.IsNumeric();
                if (numeric) {
                    caster = SimpleTypeCasterFactory.GetCaster(fromType, targetType);
                }
                else {
                    caster = new SimpleTypeCasterAnyType(targetType);
                }
            }

            // assign a computer unless already assigned
            if (casterParserComputerForge == null) {
                // to-string
                if (targetType == typeof(string)) {
                    casterParserComputerForge = new StringXFormComputer();
                }
                else if (fromType == typeof(string) && targetType != typeof(char)) {
                    // parse
                    SimpleTypeParserSPI parser = SimpleTypeParserFactory.GetParser(targetType.GetBoxedType());
                    casterParserComputerForge = new StringParserComputer(parser);
                }
                else if (numeric) {
                    // numeric cast with check
                    casterParserComputerForge = new NumberCasterComputer(caster);
                }
                else {
                    // non-numeric cast
                    casterParserComputerForge = new NonnumericCasterComputer(caster);
                }
            }

            // determine constant or not
            object theConstant = null;
            var isConstant = false;
            if (ChildNodes[0].Forge.ForgeConstantType.IsCompileTimeConstant) {
                isConstant = casterParserComputerForge.IsConstantForConstInput;
                if (isConstant) {
                    var @in = ChildNodes[0].Forge.ExprEvaluator.Evaluate(null, true, null);
                    theConstant = @in == null
                        ? null
                        : casterParserComputerForge.EvaluatorComputer.Compute(@in, null, true, null);
                }
            }
            
            forge = new ExprCastNodeForge(this, casterParserComputerForge, targetType, isConstant, theConstant);
            return null;
        }
예제 #2
0
        public void SetObserverParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            ExprValidationContext validationContext)
        {
            this.convertor = convertor;

            // obtains name parameters
            IDictionary<string, ExprNamedParameterNode> namedExpressions;
            try {
                namedExpressions = ExprNodeUtilityValidate.GetNamedExpressionsHandleDups(parameters);
                ExprNodeUtilityValidate.ValidateNamed(namedExpressions, NAMED_PARAMETERS);
            }
            catch (ExprValidationException e) {
                throw new ObserverParameterException(e.Message, e);
            }

            var isoStringExpr = namedExpressions.Get(ISO_NAME);
            if (namedExpressions.Count == 1 && isoStringExpr != null) {
                try {
                    allConstantResult = ExprNodeUtilityValidate.ValidateNamedExpectType(
                        isoStringExpr,
                        new[] {typeof(string)});
                }
                catch (ExprValidationException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }

                scheduleComputer = new TimerScheduleSpecComputeISOStringForge(isoStringExpr.ChildNodes[0]);
            }
            else if (isoStringExpr != null) {
                throw new ObserverParameterException(
                    "The '" + ISO_NAME + "' parameter is exclusive of other parameters");
            }
            else if (namedExpressions.Count == 0) {
                throw new ObserverParameterException("No parameters provided");
            }
            else {
                allConstantResult = true;
                var dateNamedNode = namedExpressions.Get(DATE_NAME);
                var repetitionsNamedNode = namedExpressions.Get(REPETITIONS_NAME);
                var periodNamedNode = namedExpressions.Get(PERIOD_NAME);
                if (dateNamedNode == null && periodNamedNode == null) {
                    throw new ObserverParameterException("Either the date or period parameter is required");
                }

                try {
                    if (dateNamedNode != null) {
                        allConstantResult = ExprNodeUtilityValidate.ValidateNamedExpectType(
                            dateNamedNode,
                            new[] {
                                typeof(string),
                                typeof(DateTimeEx),
                                typeof(DateTimeOffset),
                                typeof(DateTime),
                                typeof(long)
                            });
                    }

                    if (repetitionsNamedNode != null) {
                        allConstantResult &= ExprNodeUtilityValidate.ValidateNamedExpectType(
                            repetitionsNamedNode,
                            new[] {typeof(int), typeof(long)});
                    }

                    if (periodNamedNode != null) {
                        allConstantResult &= ExprNodeUtilityValidate.ValidateNamedExpectType(
                            periodNamedNode,
                            new[] {typeof(TimePeriod)});
                    }
                }
                catch (ExprValidationException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }

                var dateNode = dateNamedNode == null ? null : dateNamedNode.ChildNodes[0];
                var repetitionsNode = repetitionsNamedNode == null ? null : repetitionsNamedNode.ChildNodes[0];
                var periodNode = periodNamedNode == null ? null : (ExprTimePeriod) periodNamedNode.ChildNodes[0];
                scheduleComputer = new TimerScheduleSpecComputeFromExprForge(dateNode, repetitionsNode, periodNode);
            }

            if (allConstantResult) {
                try {
                    scheduleComputer.VerifyComputeAllConst(validationContext);
                }
                catch (ScheduleParameterException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }
            }
        }