private void AddBranches(IEnumerable <TflBranch> branches, Entity entity, Field field, ITransformParametersReader reader) { foreach (var branch in branches) { foreach (var transform in branch.Transforms) { Field f; transform.RunField = branch.RunField; transform.RunType = _process.TryGetField(entity.Name, transform.RunField, out f) ? f.SimpleType : "boolean"; transform.RunOperator = branch.RunOperator; transform.RunValue = branch.RunValue; var operation = new TransformOperationFactory(_process, entity.Name).Create(field, transform, reader.Read(transform)); entity.OperationsAfterAggregation.Add(operation); if (transform.Branches.Count > 0) { AddBranches(transform.Branches, entity, field, reader); } } } }
public IOperation Create(Field field, TflTransform element, IParameters parameters) { if (_isInitMode) { return(new EmptyOperation()); } Func <Row, bool> shouldRun = row => true; var toTimeZone = string.IsNullOrEmpty(element.ToTimeZone) ? _process.TimeZone : element.ToTimeZone; var hasParameters = parameters.Count > 0; var inKey = hasParameters ? parameters[0].Name : field.Alias; var inType = hasParameters ? parameters[0].SimpleType : field.SimpleType; var outKey = field.Alias; var outType = field.SimpleType; var scripts = new Dictionary <string, Script>(); if (!hasParameters) { parameters.Add(field.Alias, field.Alias, null, field.SimpleType); } if (!element.RunField.Equals(string.Empty)) { var op = (ComparisonOperator)Enum.Parse(typeof(ComparisonOperator), element.RunOperator, true); var simpleType = Common.ToSimpleType(element.RunType.Equals(Common.DefaultValue) ? "boolean" : element.RunType); var runValue = simpleType.StartsWith("bool") && element.RunValue.Equals(Common.DefaultValue) ? "true" : element.RunValue; var value = Common.ConversionMap[simpleType](runValue); shouldRun = row => Common.CompareMap[op](row[element.RunField], value); } var templates = ComposeTemplates(field, element); switch (element.Method.ToLower()) { case "convert": return(new ConvertOperation( inKey, inType, outKey, element.To.Equals(Common.DefaultValue) ? outType : element.To, element.Encoding, element.Format ) { ShouldRun = shouldRun, EntityName = _entityName }); case "copy": if (parameters.Count > 1) { return new CopyMultipleOperation(outKey, parameters) { ShouldRun = shouldRun, EntityName = _entityName } } ; return(new CopyOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "collapse": var partial = new PartialProcessOperation(_process); partial.Register(new RegexReplaceOperation(inKey, outKey, "[\r\n]{2,}", "\r\n", 0) { ShouldRun = shouldRun, EntityName = _entityName }); partial.Register(new RegexReplaceOperation(inKey, outKey, " {2,}", " ", 0) { ShouldRun = shouldRun, EntityName = _entityName }); partial.Register(new TrimOperation(inKey, outKey, " ") { ShouldRun = shouldRun, EntityName = _entityName }); return(partial); case "compress": return(new CompressOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "toyesno": return(new ToYesNoOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "decompress": return(new DecompressOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "elipse": return(new ElipseOperation(inKey, outKey, element.Length, element.Elipse) { ShouldRun = shouldRun, EntityName = _entityName }); case "replace": return(new ReplaceOperation( inKey, outKey, element.OldValue, element.NewValue ) { ShouldRun = shouldRun, EntityName = _entityName }); case "regexreplace": return(new RegexReplaceOperation( inKey, outKey, element.Pattern, element.Replacement, element.Count ) { ShouldRun = shouldRun, EntityName = _entityName }); case "striphtml": return(new RegexReplaceOperation( inKey, outKey, @"<[^>]+>| ", string.Empty, 0 ) { ShouldRun = shouldRun, EntityName = _entityName }); case "insert": return(new InsertOperation( inKey, outKey, element.StartIndex, element.Value, parameters[0].Name.Equals(outKey) ? null : GetParameter(_entityName, parameters[0].Name) ) { ShouldRun = shouldRun, EntityName = _entityName }); case "insertinterval": return(new InsertIntervalOperation( inKey, outKey, element.Interval, element.Value ) { ShouldRun = shouldRun, EntityName = _entityName }); case "append": return(new AppendOperation( inKey, outKey, element.Value, parameters[0].Name.Equals(outKey) ? null : GetParameter(_entityName, parameters[0].Name) ) { ShouldRun = shouldRun, EntityName = _entityName }); case "if": var leftParameter = GetParameter(_entityName, element.Left, parameters); return(new IfOperation( leftParameter, (ComparisonOperator)Enum.Parse(typeof(ComparisonOperator), element.Operator, true), GetParameter(_entityName, element.Right, parameters, leftParameter.SimpleType), GetParameter(_entityName, element.Then, parameters), GetParameter(_entityName, element.Else, parameters), outKey, outType ) { ShouldRun = shouldRun, EntityName = _entityName }); case "distinctwords": if (element.Separator.Equals(Common.DefaultValue)) { element.Separator = SPACE; } return(new DistinctWordsOperation( inKey, outKey, element.Separator ) { ShouldRun = shouldRun, EntityName = _entityName }); case "guid": return(new GuidOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "utcnow": return(new UtcNowOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "now": return(new NowOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "remove": return(new RemoveOperation( inKey, outKey, element.StartIndex, element.Length ) { ShouldRun = shouldRun, EntityName = _entityName }); case "trimstart": return(new TrimStartOperation( inKey, outKey, element.TrimChars ) { ShouldRun = shouldRun, EntityName = _entityName }); case "trimstartappend": return(new TrimStartAppendOperation( inKey, outKey, element.TrimChars, element.Separator ) { ShouldRun = shouldRun, EntityName = _entityName }); case "trimend": return(new TrimEndOperation( inKey, outKey, element.TrimChars ) { ShouldRun = shouldRun, EntityName = _entityName }); case "trim": return(new TrimOperation( inKey, outKey, element.TrimChars ) { ShouldRun = shouldRun, EntityName = _entityName }); case "substring": return(new SubstringOperation( inKey, outKey, element.StartIndex, element.Length ) { ShouldRun = shouldRun, EntityName = _entityName }); case "left": return(new LeftOperation( inKey, outKey, element.Length ) { ShouldRun = shouldRun, EntityName = _entityName }); case "right": return(new RightOperation( inKey, outKey, element.Length ) { ShouldRun = shouldRun, EntityName = _entityName }); case "hashcode": case "gethashcode": return(new GetHashCodeOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "mail": var connection = _process.Connections.GetConnectionByName(element.Connection).Connection; if (!parameters.ContainsName("body")) { parameters.Add(field.Alias, "body", null, "string"); } return(new MailOperation( (MailConnection)connection, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "map": var equals = _process.MapEquals.ContainsKey(element.Map) ? _process.MapEquals[element.Map] : new Map(); var startsWith = _process.MapStartsWith.ContainsKey(element.Map) ? _process.MapStartsWith[element.Map] : new Map(); var endsWith = _process.MapEndsWith.ContainsKey(element.Map) ? _process.MapEndsWith[element.Map] : new Map(); //TODO: Move to Modify and Validate if (equals.Count == 0 && startsWith.Count == 0 && endsWith.Count == 0) { if (element.Map.Contains("=")) { foreach (var item in element.Map.Split(new[] { ',' })) { var split = item.Split(new[] { '=' }); if (split.Length == 2) { var left = split[0]; var right = split[1]; Field tryField; if (_process.TryGetField(_entityName, right, out tryField, false)) { equals.Add(left, new Item(tryField.Alias, right)); } else { equals.Add(left, new Item(right)); } } } if (equals.Count == 0) { _logger.EntityWarn(_entityName, "Map '{0}' is empty.", element.Map); } } else { _logger.EntityWarn(_entityName, "Map '{0}' is empty.", element.Map); } } return(new MapOperation( inKey, outKey, outType, new[] { @equals, startsWith, endsWith } ) { ShouldRun = shouldRun, EntityName = _entityName }); case "markdown": return(new MarkDownOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "padleft": return(new PadLeftOperation( inKey, outKey, element.TotalWidth, element.PaddingChar ) { ShouldRun = shouldRun, EntityName = _entityName }); case "padright": return(new PadRightOperation( inKey, outKey, element.TotalWidth, element.PaddingChar ) { ShouldRun = shouldRun, EntityName = _entityName }); case "tostring": return(new ToStringOperation( inKey, inType, outKey, element.Format ) { ShouldRun = shouldRun, EntityName = _entityName }); case "toupper": return(new ToUpperOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "tolower": return(new ToLowerOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "javascript": foreach (var script in element.Scripts) { //TODO: Move to Validate if (!_process.Scripts.ContainsKey(script.Name)) { throw new TransformalizeException(_logger, _entityName, "Invalid script reference: {0}.", script.Name); } scripts[script.Name] = _process.Scripts[script.Name]; } return(new JavascriptOperation( outKey, element.Script, scripts, parameters, _logger ) { ShouldRun = shouldRun, EntityName = _entityName }); case "csharp": foreach (var script in element.Scripts) { // TODO: Move to Validate if (!_process.Scripts.ContainsKey(script.Name)) { throw new TransformalizeException(_logger, _entityName, "Invalid script reference: {0}.", script.Name); } scripts[script.Name] = _process.Scripts[script.Name]; } return(new CSharpOperation( outKey, outType, //TODO: Move to Modify (element.ReplaceSingleQuotes ? Regex.Replace(element.Script, @"(?<=[^'])'{1}(?=[^'])", "\"") : element.Script), scripts, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "razor": case "template": return(new RazorOperation( outKey, outType, element.Template, element.Model, templates, parameters, _logger ) { ShouldRun = shouldRun, EntityName = _entityName }); case "velocity": return(new VelocityOperation( outKey, outType, element.Template, templates, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "tag": return(new TagOperation( outKey, element.Tag, parameters, element.Decode, element.Encode ) { ShouldRun = shouldRun, EntityName = _entityName }); case "format": return(new FormatOperation( outKey, element.Format, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "timespan": return(new TimeSpanOperation( parameters, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "concat": return(new ConcatOperation( outKey, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "totitlecase": return(new ToTitleCaseOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "formatphone": return(new FormatPhoneOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "join": //TODO: Move to Modify if (element.Separator.Equals(Common.DefaultValue)) { element.Separator = SPACE; } return(new JoinTransformOperation( outKey, element.Separator, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "tolocaltime": return(new ToLocalTimeOperation( inKey, outKey, element.FromTimeZone, element.ToTimeZone ) { ShouldRun = shouldRun, EntityName = _entityName }); case "timeago": return(new RelativeTimeOperation( inKey, outKey, element.FromTimeZone, true ) { ShouldRun = shouldRun, EntityName = _entityName }); case "timeahead": return(new RelativeTimeOperation( inKey, outKey, element.FromTimeZone, false ) { ShouldRun = shouldRun, EntityName = _entityName }); case "timezone": //TODO: Move to Modify element.FromTimeZone = TimeZoneOperation.GuardTimeZone(field.Process, _entityName, element.FromTimeZone, "UTC", _process.Logger); toTimeZone = TimeZoneOperation.GuardTimeZone(field.Process, _entityName, toTimeZone, TimeZoneInfo.Local.Id, _process.Logger); return(new TimeZoneOperation( inKey, outKey, element.FromTimeZone, toTimeZone ) { ShouldRun = shouldRun, EntityName = _entityName }); case "tojson": return(new ToJsonOperation( outKey, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "fromxml": switch ((XmlMode)Enum.Parse(typeof(XmlMode), element.XmlMode)) { case XmlMode.First: return(new FromFirstXmlOperation( outKey, new Fields(_process, parameters, _entityName) ) { ShouldRun = shouldRun, EntityName = _entityName }); case XmlMode.All: return(new FromXmlOperation( outKey, element.Root, new Fields(_process, parameters, _entityName) ) { ShouldRun = shouldRun, EntityName = _entityName }); default: return(new FromNanoXmlOperation( outKey, new Fields(_process, parameters, _entityName) ) { ShouldRun = shouldRun, EntityName = _entityName }); } case "fromregex": return(new FromRegexOperation( outKey, element.Pattern, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "fromjson": return(new FromJsonOperation( TryRemoveInputParameters(element, parameters) ? inKey : outKey, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "fromsplit": return(new FromSplitOperation(outKey, element.Separator, parameters) { ShouldRun = shouldRun, EntityName = _entityName }); case "distance": return(new DistanceOperation( outKey, element.Units, GetParameter(_entityName, element.FromLat), GetParameter(_entityName, element.FromLong), GetParameter(_entityName, element.ToLat), GetParameter(_entityName, element.ToLong) ) { ShouldRun = shouldRun, EntityName = _entityName }); case "length": return(new LengthOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "timeofday": return(new TimeOfDayOperation(inKey, inType, outKey, outType, element.TimeComponent) { ShouldRun = shouldRun, EntityName = _entityName }); case "value": return(new ValueOperation(outKey, outType, element.Value, parameters) { ShouldRun = shouldRun, EntityName = _entityName }); case "xpath": return(new XPathOperation(inKey, outKey, outType, element.Xpath) { ShouldRun = shouldRun, EntityName = _entityName }); case "xmlencode": return(new XmlEncodeOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "urlencode": return(new UrlEncodeOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "htmlencode": return(new HtmlEncodeOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "htmldecode": case "xmldecode": return(new HtmlDecodeOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "filter": return(new FilterOperation( inKey, outKey, outType, element.Value, (ComparisonOperator)Enum.Parse(typeof(ComparisonOperator), element.Operator, true) ) { ShouldRun = shouldRun, EntityName = _entityName }); case "splitindex": return(new SplitIndexOperation( inKey, outKey, outType, element.Separator, element.Count, element.Index ) { ShouldRun = shouldRun, EntityName = _entityName }); case "datepart": return(new DatePartOperation( inKey, outKey, outType, element.TimeComponent ) { ShouldRun = shouldRun, EntityName = _entityName }); case "average": return(new AverageOperation( outKey, outType, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "add": return(new AddOperation( outKey, outType, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "geocode": return(new GeoCodeOperation( inKey, outKey, element.Sleep, element.UseHttps, parameters ) { ShouldRun = shouldRun, EntityName = _entityName }); case "transliterate": return(new TransliterateOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "slug": return(new SlugOperation(inKey, outKey, element.Length) { ShouldRun = shouldRun, EntityName = _entityName }); case "cyrtolat": return(new CyrToLatOperation(inKey, outKey) { ShouldRun = shouldRun, EntityName = _entityName }); case "web": return(new WebOperation( element.Url.Equals(string.Empty) ? parameters[0] : GetParameter(_entityName, element.Url, parameters), outKey, element.Sleep, element.WebMethod, GetParameter(_entityName, element.Data, parameters), element.ContentType ) { ShouldRun = shouldRun, EntityName = _entityName }); case "run": return(new RunOperation( inKey, _process.Connections.GetConnectionByName(element.Connection).Connection, element.TimeOut ) { ShouldRun = shouldRun, EntityName = _entityName }); case "weekofyear": return(new WeekOfYearOperation( inKey, outKey, (CalendarWeekRule)Enum.Parse(typeof(CalendarWeekRule), element.CalendarWeekRule, true), (DayOfWeek)Enum.Parse(typeof(DayOfWeek), element.DayOfWeek, true) ) { ShouldRun = shouldRun, EntityName = _entityName }); // validators case "equals": return(new EqualsOperation(outKey, parameters) { ShouldRun = shouldRun, EntityName = _entityName }); case "isempty": return(new IsEmptyOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "isdaylightsavings": return(new IsDaylightSavingsOperation( inKey, outKey ) { ShouldRun = shouldRun, EntityName = _entityName }); case "any": return(new AnyOperation( string.IsNullOrEmpty(element.Value) ? GetParameter(_entityName, element.Left, parameters) : new Parameter(element.Value, element.Value), outKey, (ComparisonOperator)Enum.Parse(typeof(ComparisonOperator), element.Operator, true), parameters, element.Negated ) { ShouldRun = shouldRun, EntityName = _entityName }); case "containscharacters": return(new ContainsCharactersValidatorOperation( inKey, outKey, element.Characters, (ContainsCharacters)Enum.Parse(typeof(ContainsCharacters), element.ContainsCharacters, true), element.Negated )); case "datetimerange": return(new DateTimeRangeValidatorOperation( inKey, outKey, (DateTime)_conversionMap[inType](element.LowerBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.LowerBoundType, true), (DateTime)_conversionMap[inType](element.UpperBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.UpperBoundType, true), element.Negated )); case "domain": if (element.Separator.Equals(Common.DefaultValue)) { element.Separator = COMMA; } var domain = element.Domain.Split(element.Separator.ToCharArray()).Select(s => _conversionMap[inType](s)); return(new DomainValidatorOperation( inKey, outKey, domain, element.Negated )); case "isjson": return(new JsonValidatorOperation(inKey, outKey, element.Negated)); case "notnull": return(new NotNullValidatorOperation(inKey, outKey, element.Negated)); case "fieldcomparison": return(new PropertyComparisonValidatorOperation(inKey, element.TargetField, outKey, element.Operator, element.Negated)); case "range": return(new RangeValidatorOperation( inKey, outKey, (IComparable)_conversionMap[field.SimpleType](element.LowerBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.LowerBoundType, true), (IComparable)_conversionMap[field.SimpleType](element.UpperBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.UpperBoundType, true), element.Negated )); case "regex": return(new RegexValidatorOperation( inKey, outKey, element.Pattern, element.Negated )); case "relativedatetime": return(new RelativeDateTimeValidatorOperation( inKey, outKey, Convert.ToInt32(element.LowerBound), (DateTimeUnit)Enum.Parse(typeof(DateTimeUnit), element.LowerUnit, true), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.LowerBoundType, true), Convert.ToInt32(element.UpperBound), (DateTimeUnit)Enum.Parse(typeof(DateTimeUnit), element.UpperUnit, true), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.UpperBoundType, true), element.Negated )); case "startswith": return(new StartsWithValidatorOperation( inKey, element.Value, outKey, element.Negated )); case "stringlength": return(new StringLengthValidatorOperation( inKey, outKey, Convert.ToInt32(element.LowerBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.LowerBoundType, true), Convert.ToInt32(element.UpperBound), (RangeBoundaryType)Enum.Parse(typeof(RangeBoundaryType), element.UpperBoundType, true), element.Negated )); case "typeconversion": return(new TypeConversionValidatorOperation( inKey, outKey, Common.ToSystemType(element.Type), element.Negated, element.IgnoreEmpty )); } _logger.EntityWarn(_entityName, "{0} method is undefined. It will not be used.", element.Method); return(new EmptyOperation()); }