public ActionResult Download(int id) { var part = _orchardServices.ContentManager.Get(id).As <PipelineConfigurationPart>(); var process = new Process { Name = "Export" }; if (part == null) { process.Name = "Not Found"; return(new FileStreamResult(GenerateStreamFromString(process.Serialize()), "text/xml") { FileDownloadName = id + ".xml" }); } if (!_orchardServices.Authorizer.Authorize(Permissions.ViewContent, part)) { process.Name = "Not Authorized"; return(new FileStreamResult(GenerateStreamFromString(process.Serialize()), "text/xml") { FileDownloadName = id + ".xml" }); } return(new FileStreamResult(GenerateStreamFromString(part.Configuration), "text/" + part.EditorMode) { FileDownloadName = _slugService.Slugify(part.Title()) + "." + part.EditorMode }); }
protected static void ReverseConfiguration(Transformalize.Configuration.Process process) { //swap input and output process.Connections.First(c => c.Name.Equals("output")).Name = "temp"; process.Connections.First(c => c.Name.Equals("input")).Name = "output"; process.Connections.First(c => c.Name.Equals("temp")).Name = "input"; var entity = process.Entities[0]; entity.Name = entity.OutputViewName(process.Name); //if no primary key is set, make all the fields a composite primary key if (!entity.Fields.Any(f => f.PrimaryKey)) { foreach (var field in entity.Fields) { field.PrimaryKey = true; } } //aliases are used to write to output, so swap when reversing foreach (var field in entity.Fields.Where(f => !f.System)) { var temp = field.Name; field.Name = field.Alias; field.Alias = temp; } entity.Update = false; entity.Delete = false; entity.Filter.Add(new Transformalize.Configuration.Filter { Expression = "TflDeleted = 0" }); }
protected static void TransformConfigurationForDownload(Transformalize.Configuration.Process root, Dictionary <string, string> query) { ReverseConfiguration(root); var output = root.Connections.First(c => c.Name == "output"); output.Provider = "file"; output.File = query.ContainsKey("OutputFile") ? query["OutputFile"] : string.Empty; }
public void TestMethod1() { var process = new Process { Name = "Test", ReadOnly = true, Connections = new List <Connection> { new Connection { Name = "input", Provider = "activedirectory" }, new Connection { Name = "output", Provider = "internal" } }, Entities = new List <Entity> { new Entity { Name = "Users", Page = 1, Size = 20, Filter = new List <Filter> { new Filter { Expression = "(&(mail=*)(objectClass=user)(objectCategory=person))" } }, Fields = new List <Field> { new Field { Name = "mail" }, new Field { Name = "title" }, new Field { Name = "whenChanged", Type = "datetime" } } } } }; process.Load(); Assert.AreEqual(0, process.Errors().Length); var logger = new ConsoleLogger(LogLevel.Debug); var context = new PipelineContext(logger, process, process.Entities[0]); var input = new InputContext(context); var reader = new ActiveDirectoryReader(input, new RowFactory(context.Entity.Fields.Count, true, false)); var rows = reader.Read(); var count = 0; foreach (var row in rows) { ++count; Trace.WriteLine(count + ". " + row.ToString()); } }
protected static void TransformConfigurationForLoad(Transformalize.Configuration.Process root) { ReverseConfiguration(root); root.ReadOnly = true; foreach (var entity in root.Entities) { foreach (var field in entity.Fields.Where(f => f.System)) { field.Output = false; } } }
private void ConvertToExport(string user, Process process, PipelineConfigurationPart part, string exportType, IDictionary <string, string> parameters) { var o = process.Output(); switch (exportType) { case "xlsx": if (!_appDataFolder.DirectoryExists(Common.FileFolder)) { _appDataFolder.CreateDirectory(Common.FileFolder); } var fileName = $"{user}-{_clock.UtcNow.ToString(FileTimestamp)}-{_slugService.Slugify(part.Title())}.xlsx"; o.Provider = "excel"; o.File = _appDataFolder.MapPath(_appDataFolder.Combine(Common.FileFolder, fileName)); break; case "geojson": o.Stream = true; o.Provider = "geojson"; o.File = _slugService.Slugify(part.Title()) + ".geojson"; break; case "kml": o.Stream = true; o.Provider = "kml"; o.File = _slugService.Slugify(part.Title()) + ".kml"; break; default: //csv o.Stream = true; o.Provider = "file"; o.Delimiter = ","; o.File = _slugService.Slugify(part.Title()) + ".csv"; break; } parameters["page"] = "0"; foreach (var entity in process.Entities) { entity.Page = 0; entity.Fields.RemoveAll(f => f.System); foreach (var field in entity.GetAllFields()) { field.Output = field.Output && field.Export == "defer" || field.Export == "true"; } } }
public void ConfineData(Process process, IDictionary <string, string> required) { foreach (var entity in process.Entities) { var all = entity.GetAllFields().ToArray(); var dependencies = new HashSet <Field>(); foreach (var field in all) { if (required.ContainsKey(field.Alias)) { dependencies.Add(field); field.Output = true; if (!required[field.Alias].Equals(field.Alias, StringComparison.OrdinalIgnoreCase)) { field.Alias = required[field.Alias]; } } else if (field.Property) { dependencies.Add(field); field.Output = true; } } // optimize download if it's not a manually written query if (entity.Query == string.Empty) { foreach (var field in entity.FindRequiredFields(dependencies, process.Maps)) { dependencies.Add(field); } foreach (var unnecessary in all.Except(dependencies)) { unnecessary.Input = false; unnecessary.Output = false; unnecessary.Transforms.Clear(); } } } }
public ILifetimeScope CreateScope(string cfg, IPipelineLogger logger, IDictionary <string, string> parameters = null, string placeHolderStyle = "@[]") { if (placeHolderStyle == null || placeHolderStyle.Length != 3) { throw new ArgumentException("The placeHolderStyle parameter must be three characters (e.g. @[], or @())"); } if (parameters == null) { parameters = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } var builder = new ContainerBuilder(); builder.Register((ctx) => logger).As <IPipelineLogger>(); builder.Register <IReader>(c => new DefaultReader(new FileReader(), new WebReader())).As <IReader>(); // register short-hand for t attribute var transformModule = new TransformModule(new Process { Name = "TransformShorthand" }, _methods, _shortHand, logger); foreach (var t in _transforms) { transformModule.AddTransform(t); } builder.RegisterModule(transformModule); // register short-hand for v attribute var validateModule = new ValidateModule(new Process { Name = "ValidateShorthand" }, _methods, _shortHand, logger); foreach (var v in _validators) { validateModule.AddValidator(v); } builder.RegisterModule(validateModule); // register the validator short hand builder.Register((c, p) => _shortHand).Named <ShorthandRoot>(ValidateModule.FieldsName).InstancePerLifetimeScope(); builder.Register((c, p) => new ShorthandCustomizer(c.ResolveNamed <ShorthandRoot>(ValidateModule.FieldsName), new[] { "fields", "calculated-fields", "calculatedfields" }, "v", "validators", "method")).Named <IDependency>(ValidateModule.FieldsName).InstancePerLifetimeScope(); // register the transform short hand builder.Register((c, p) => _shortHand).Named <ShorthandRoot>(TransformModule.FieldsName).InstancePerLifetimeScope(); builder.Register((c, p) => _shortHand).Named <ShorthandRoot>(TransformModule.ParametersName).InstancePerLifetimeScope(); builder.Register((c, p) => new ShorthandCustomizer(c.ResolveNamed <ShorthandRoot>(TransformModule.FieldsName), new[] { "fields", "calculated-fields", "calculatedfields" }, "t", "transforms", "method")).Named <IDependency>(TransformModule.FieldsName).InstancePerLifetimeScope(); builder.Register((c, p) => new ShorthandCustomizer(c.ResolveNamed <ShorthandRoot>(TransformModule.ParametersName), new[] { "parameters" }, "t", "transforms", "method")).Named <IDependency>(TransformModule.ParametersName).InstancePerLifetimeScope(); #if PLUGINS // the shorthand registrations are stored in the builder's properties for plugins to add to builder.Properties["ShortHand"] = _shortHand; builder.Properties["Methods"] = _methods; #endif foreach (var module in _modules) { builder.RegisterModule(module); } builder.Register((c, p) => _methods).Named <HashSet <string> >("Methods").InstancePerLifetimeScope(); builder.Register((c, p) => _shortHand).As <ShorthandRoot>().InstancePerLifetimeScope(); builder.Register(ctx => { var transformed = TransformParameters(ctx, cfg); var dependancies = new List <IDependency>(); dependancies.Add(ctx.Resolve <IReader>()); dependancies.AddRange(_dependencies); dependancies.Add(new ParameterModifier(new PlaceHolderReplacer(placeHolderStyle[0], placeHolderStyle[1], placeHolderStyle[2]), "parameters", "name", "value")); dependancies.Add(ctx.ResolveNamed <IDependency>(TransformModule.FieldsName)); dependancies.Add(ctx.ResolveNamed <IDependency>(TransformModule.ParametersName)); dependancies.Add(ctx.ResolveNamed <IDependency>(ValidateModule.FieldsName)); var process = new Process(transformed ?? cfg, parameters, dependancies.ToArray()); if (process.Errors().Any()) { var c = new PipelineContext(logger, new Process() { Name = "Errors" }); c.Error("The configuration has errors."); foreach (var error in process.Errors()) { c.Error(error); } } return(process); }).As <Process>().InstancePerDependency(); return(builder.Build().BeginLifetimeScope()); }
private static string TransformParameters(IComponentContext ctx, string cfg) { var preProcess = new ConfigurationFacade.Process( cfg, new Dictionary <string, string>(), new List <IDependency> { ctx.Resolve <IReader>(), new DateMathModifier(), new ParameterModifier(new NullPlaceHolderReplacer()), ctx.ResolveNamed <IDependency>(TransformModule.ParametersName) }.ToArray()); if (!preProcess.Parameters.Any(pr => pr.Transforms.Any())) { return(null); } var fields = preProcess.Parameters.Select(pr => new Field { Name = pr.Name, Alias = pr.Name, Default = pr.Value, Type = pr.Type, Transforms = pr.Transforms.Select(o => o.ToOperation()).ToList() }).ToList(); var len = fields.Count; var entity = new Entity { Name = "Parameters", Alias = "Parameters", Fields = fields }; var mini = new Process { Name = "ParameterTransform", ReadOnly = true, Entities = new List <Entity> { entity }, Maps = preProcess.Maps.Select(m => m.ToMap()).ToList(), // for map transforms Scripts = preProcess.Scripts.Select(s => s.ToScript()).ToList() // for transforms that use scripts (e.g. js) }; mini.Load(); // very important to check after creating, as it runs validation and even modifies! if (!mini.Errors().Any()) { // modification in Load() do not make it out to local variables so overwrite them fields = mini.Entities.First().Fields; entity = mini.Entities.First(); var c = new PipelineContext(ctx.Resolve <IPipelineLogger>(), mini, entity); var transforms = new List <ITransform> { new Transforms.System.DefaultTransform(c, fields) }; transforms.AddRange(TransformFactory.GetTransforms(ctx, c, fields)); // make an input out of the parameters var input = new List <IRow>(); var row = new MasterRow(len); for (var i = 0; i < len; i++) { row[fields[i]] = preProcess.Parameters[i].Value; } input.Add(row); var output = transforms.Aggregate(input.AsEnumerable(), (rows, t) => t.Operate(rows)).ToList().First(); for (var i = 0; i < len; i++) { var parameter = preProcess.Parameters[i]; parameter.Value = output[fields[i]].ToString(); parameter.T = string.Empty; parameter.Transforms.Clear(); } return(preProcess.Serialize()); } var context = new PipelineContext(ctx.Resolve <IPipelineLogger>(), mini, entity); foreach (var error in mini.Errors()) { context.Error(error); } return(null); }
private string ModifyInternal(string cfg, int id, IDictionary <string, string> parameters) { var process = new Process(cfg) { Id = id }; // if there aren't any parameters, just leave if (!process.Parameters.Any()) { return(cfg); } // if there isn't a primary key, just leave var key = process.Parameters.FirstOrDefault(p => p.PrimaryKey); if (key == null || parameters == null || !parameters.ContainsKey(key.Name)) { return(cfg); } // if the value being passed in for the primary key is the type's default value, just leave because it's an insert if (parameters[key.Name] == Transformalize.Constants.TypeDefaults()[key.Type].ToString()) { return(cfg); } _settings.ApplyCommonSettings(process); var fields = new List <Field>(); // get all the fields that should be in the form's table and are not specific to insert or update scope foreach (var pr in process.Parameters.Where(p => p.Output && p.Scope == "[default]")) { var field = new Field { Name = pr.Name, Alias = pr.Name, Type = pr.Type, Default = pr.Value, Length = pr.Length, Format = pr.Format, InputType = pr.InputType, Precision = pr.Precision, Scale = pr.Scale }; fields.Add(field); } var connection = process.Connections.First(c => c.Table != "[default]"); // create entity var entity = new Entity { Name = connection.Table, Fields = fields, Input = connection.Name, Filter = new List <Filter>() { new Filter { Field = key.Name, Value = parameters[key.Name] } } }; // create process to load the form submission var modified = new Process { Id = id, Name = "Load Form", ReadOnly = true, Entities = new List <Entity> { entity }, Connections = new List <Connection> { connection } }; modified.Load(); if (!modified.Errors().Any()) { // run the process which should get a single row (the form submission) into output CfgRow output; using (var scope = _container.CreateScope(modified, _logger)) { scope.Resolve <IProcessController>().Execute(); output = modified.Entities[0].Rows.FirstOrDefault(); } if (output != null) { foreach (var parameter in process.Parameters) { var field = modified.Entities[0].Fields.FirstOrDefault(f => f.Name == parameter.Name); // put the form submission value in the parameters if (field != null) { parameters[parameter.Name] = output[field.Name].ToString(); } } } } foreach (var error in process.Errors()) { _logger.Error(() => error); } return(cfg); }
protected static void TransformConfigurationForLoad(Transformalize.Configuration.Process root) { ReverseConfiguration(root); }
private void ConvertToExport(string user, Process process, PipelineConfigurationPart part, string exportType) { var o = process.Output(); switch (exportType) { case "xlsx": var folder = Common.GetAppFolder(); if (!_appDataFolder.DirectoryExists(folder)) { _appDataFolder.CreateDirectory(folder); } var fileName = Common.GetSafeFileName(user, _slugService.Slugify(part.Title()), "xlsx"); o.Provider = "excel"; o.File = _appDataFolder.MapPath(_appDataFolder.Combine(folder, fileName)); break; case "geojson": o.Stream = true; o.Provider = "geojson"; o.File = _slugService.Slugify(part.Title()) + ".geo.json"; var suppress = new HashSet <string>() { Common.BatchValueFieldName, part.MapColorField, part.MapPopUpField }; var coordinates = new HashSet <string>() { part.MapLatitudeField, part.MapLongitudeField }; foreach (var entity in process.Entities) { foreach (var field in entity.GetAllFields()) { if (suppress.Contains(field.Alias)) { field.Output = false; field.Property = false; field.Alias += "Suppressed"; } else if (coordinates.Contains(field.Alias)) { field.Property = field.Export == "true"; } else { field.Property = field.Property || field.Output && field.Export == "defer" || field.Export == "true"; } } } break; case "map": o.Stream = true; o.Provider = "geojson"; o.File = _slugService.Slugify(part.Title()) + ".geo.json"; var mapFields = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { part.MapColorField, "geojson-color" }, { part.MapPopUpField, "geojson-description" }, { part.MapLatitudeField, "latitude" }, { part.MapLongitudeField, "longitude" }, { Common.BatchValueFieldName, Common.BatchValueFieldName } }; ConfineData(process, mapFields); break; case "json": o.Stream = true; o.Provider = "json"; o.File = _slugService.Slugify(part.Title()) + ".json"; break; case "calendar": o.Stream = true; o.Provider = "json"; o.File = _slugService.Slugify(part.Title()) + ".json"; var calendarFields = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { part.CalendarIdField, "id" }, { part.CalendarTitleField, "title" }, { part.CalendarUrlField, "url" }, { part.CalendarClassField, "class" }, { part.CalendarStartField, "start" }, { part.CalendarEndField, "end" }, { Common.BatchValueFieldName, Common.BatchValueFieldName } }; ConfineData(process, calendarFields); break; case "kml": o.Stream = true; o.Provider = "kml"; o.File = _slugService.Slugify(part.Title()) + ".kml"; break; default: // csv o.Stream = true; o.Provider = "file"; o.Delimiter = ","; o.TextQualifier = "\""; o.File = _slugService.Slugify(part.Title()) + ".csv"; break; } // common foreach (var entity in process.Entities) { entity.Fields.RemoveAll(f => f.System); foreach (var field in entity.GetAllFields()) { field.T = string.Empty; // because short-hand has already been expanded switch (exportType) { case "map": case "calendar": case "geojson": // already been modified break; default: if (field.Alias == Common.BatchValueFieldName) { field.Output = false; } field.Output = field.Output && field.Export == "defer" || field.Export == "true"; break; } } } }
public ActionResult Report(int id) { var timer = new Stopwatch(); timer.Start(); var process = new Process { Name = "Report" }; var part = _orchardServices.ContentManager.Get(id).As <PipelineConfigurationPart>(); if (part == null) { process.Name = "Not Found"; } else { var user = _orchardServices.WorkContext.CurrentUser == null ? "Anonymous" : _orchardServices.WorkContext.CurrentUser.UserName ?? "Anonymous"; if (_orchardServices.Authorizer.Authorize(Permissions.ViewContent, part)) { process = _processService.Resolve(part.EditorMode, part.EditorMode); var parameters = Common.GetParameters(Request, _secureFileService, _orchardServices); if (part.NeedsInputFile && Convert.ToInt32(parameters[Common.InputFileIdName]) == 0) { _orchardServices.Notifier.Add(NotifyType.Error, T("This transformalize expects a file.")); process.Name = "File Not Found"; } process.Load(part.Configuration, parameters); process.Buffer = false; // no buffering for reports process.ReadOnly = true; // force reporting to omit system fields // secure actions var actions = process.Actions.Where(a => !a.Before && !a.After && !a.Description.StartsWith("Batch", StringComparison.OrdinalIgnoreCase)); foreach (var action in actions) { var p = _orchardServices.ContentManager.Get(action.Id); if (!_orchardServices.Authorizer.Authorize(Permissions.ViewContent, p)) { action.Description = "BatchUnauthorized"; } } var output = process.Output(); if (output.Provider.In("internal", "file")) { Common.TranslatePageParametersToEntities(process, parameters, "page"); // change process for export and batch purposes var reportType = Request["output"] ?? "page"; if (!_renderedOutputs.Contains(reportType)) { if (reportType == "batch" && Request.HttpMethod.Equals("POST") && parameters.ContainsKey("action")) { var action = process.Actions.FirstOrDefault(a => a.Description == parameters["action"]); if (action != null) { // check security var actionPart = _orchardServices.ContentManager.Get(action.Id); if (actionPart != null && _orchardServices.Authorizer.Authorize(Permissions.ViewContent, actionPart)) { // security okay parameters["entity"] = process.Entities.First().Alias; var batchParameters = _batchCreateService.Create(process, parameters); batchParameters["count"] = parameters.ContainsKey("count") ? parameters["count"] : "0"; var count = _batchWriteService.Write(Request, process, batchParameters); if (count > 0) { if (_batchRunService.Run(action, batchParameters)) { if (action.Url == string.Empty) { if (batchParameters.ContainsKey("BatchId")) { _orchardServices.Notifier.Information(T($"Processed {count} records in batch {batchParameters["BatchId"]}.")); } else { _orchardServices.Notifier.Information(T($"Processed {count} records.")); } } else { return(_batchRedirectService.Redirect(action.Url, batchParameters)); } } } } else { return(new HttpUnauthorizedResult("You do not have access to this bulk action.")); } } } else // export { ConvertToExport(user, process, part, reportType, parameters); process.Load(process.Serialize(), parameters); } } if (Request["sort"] != null) { _sortService.AddSortToEntity(process.Entities.First(), Request["sort"]); } if (process.Errors().Any()) { foreach (var error in process.Errors()) { _orchardServices.Notifier.Add(NotifyType.Error, T(error)); } } else { if (process.Entities.Any(e => !e.Fields.Any(f => f.Input))) { _orchardServices.WorkContext.Resolve <ISchemaHelper>().Help(process); } if (!process.Errors().Any()) { var runner = _orchardServices.WorkContext.Resolve <IRunTimeExecute>(); try { runner.Execute(process); process.Request = "Run"; process.Time = timer.ElapsedMilliseconds; if (process.Errors().Any()) { foreach (var error in process.Errors()) { _orchardServices.Notifier.Add(NotifyType.Error, T(error)); } process.Status = 500; process.Message = "There are errors in the pipeline. See log."; } else { process.Status = 200; process.Message = "Ok"; } var o = process.Output(); switch (o.Provider) { case "kml": case "geojson": case "file": Response.AddHeader("content-disposition", "attachment; filename=" + o.File); switch (o.Provider) { case "kml": Response.ContentType = "application/vnd.google-earth.kml+xml"; break; case "geojson": Response.ContentType = "application/vnd.geo+json"; break; default: Response.ContentType = "application/csv"; break; } Response.Flush(); Response.End(); return(new EmptyResult()); case "excel": return(new FilePathResult(o.File, ExcelContentType) { FileDownloadName = _slugService.Slugify(part.Title()) + ".xlsx" }); default: // page and map are rendered to page break; } } catch (Exception ex) { Logger.Error(ex, ex.Message); _orchardServices.Notifier.Error(T(ex.Message)); } } } } } else { _orchardServices.Notifier.Warning(user == "Anonymous" ? T("Sorry. Anonymous users do not have permission to view this report. You may need to login.") : T("Sorry {0}. You do not have permission to view this report.", user)); } } return(View(new ReportViewModel(process, part))); }
private string ModifyInternal(string cfg, int id, IDictionary <string, string> parameters) { // using facade (which is all string properties) so things can be // transformed before types are checked or place-holders are replaced var builder = new ContainerBuilder(); builder.RegisterModule(new ShorthandModule(_logger)); Transformalize.ConfigurationFacade.Process facade; using (var scope = builder.Build().BeginLifetimeScope()) { facade = new Transformalize.ConfigurationFacade.Process( cfg, parameters: parameters, dependencies: new List <IDependency> { new TransferParameterModifier(), // consumes parameters scope.ResolveNamed <IDependency>(TransformModule.ParametersName), scope.ResolveNamed <IDependency>(ValidateModule.ParametersName) }.ToArray() ); facade.Id = id.ToString(); } if (!facade.Parameters.Any()) { return(cfg); } _settings.ApplyCommonSettings(facade); var fields = new List <Field>(); foreach (var pr in facade.Parameters) { var field = new Field { Name = pr.Name, Alias = pr.Name, // Default = pr.Value, (something has changed, this value didn't cause problems before but it is now in DefaultRowReader) Label = pr.Label, PostBack = pr.PostBack, Type = pr.Type, Help = pr.Help, InputType = pr.InputType, // used in ParameterRowReader to identify files Transforms = pr.Transforms.Select(o => o.ToOperation()).ToList(), Validators = pr.Validators.Select(o => o.ToOperation()).ToList() }; if (!string.IsNullOrEmpty(pr.Length)) { field.Length = pr.Length; } if (!string.IsNullOrEmpty(pr.Precision) && int.TryParse(pr.Precision, out int precision)) { field.Precision = precision; } if (!string.IsNullOrEmpty(pr.Scale) && int.TryParse(pr.Scale, out int scale)) { field.Scale = scale; } fields.Add(field); } var validatorFields = new List <Field>(); foreach (var field in fields.Where(f => f.Validators.Any())) { field.ValidField = field.Name + "Valid"; field.MessageField = field.Name + "Message"; validatorFields.Add(new Field { Name = field.ValidField, Input = false, Default = "true", Type = "bool" }); validatorFields.Add(new Field { Name = field.MessageField, Input = false, Default = string.Empty, Type = "string", Length = "255" }); } // create an internal connection for input var connections = new List <Transformalize.ConfigurationFacade.Connection> { new Transformalize.ConfigurationFacade.Connection() { Name = _tpInput, Provider = "internal" } }; // add existing connections in case maps need to be loaded connections.AddRange(facade.Connections); //create an internal connection for output connections.Add(new Transformalize.ConfigurationFacade.Connection() { Name = _tpOutput, Provider = "internal" }); // create entity var entity = new Entity { Name = "Parameters", Fields = fields, CalculatedFields = validatorFields, Input = _tpInput }; // disable checking for invalid characters unless set var arrangementParameters = new List <Parameter>(); foreach (var parameter in facade.Parameters) { var add = parameter.ToParameter(); if (parameter.InvalidCharacters == null) { add.InvalidCharacters = string.Empty; } arrangementParameters.Add(add); } // create process to transform and validate the parameter values var process = new Process { Id = id, Name = "Transformalize Parameters", ReadOnly = true, Mode = "form", // causes auto post-back's to resolve to either true or false Output = _tpOutput, Parameters = arrangementParameters, Maps = facade.Maps.Select(m => m.ToMap()).ToList(), Scripts = facade.Scripts.Select(m => m.ToScript()).ToList(), Entities = new List <Entity> { entity }, Connections = connections.Select(c => c.ToConnection()).ToList() }; process.Load(); // very important to check after creating, as it runs validation and even modifies! if (!process.Errors().Any()) { // modification in Load() do not make it out to local variables so overwrite them entity = process.Entities.First(); fields = entity.Fields; validatorFields = entity.CalculatedFields; CfgRow output; _container.GetReaderAlternate = (input, rowFactory) => new ParameterRowReader(input, new DefaultRowReader(input, rowFactory)); using (var scope = _container.CreateScope(process, _logger)) { scope.Resolve <IProcessController>().Execute(); output = process.Entities[0].Rows.FirstOrDefault(); } for (int i = 0; i < process.Maps.Count; i++) { var source = process.Maps[i]; var target = facade.Maps[i]; if (source.Items.Any() && !target.Items.Any()) { foreach (var item in source.Items) { target.Items.Add(new Transformalize.ConfigurationFacade.MapItem() { From = item.From.ToString(), To = item.To.ToString(), Parameter = item.Parameter, Value = item.Value }); } target.Query = string.Empty; // remove the query so they are not queried again } } if (output != null) { JintVisibility jintVisibility = null; foreach (var parameter in facade.Parameters) { var field = fields.First(f => f.Name == parameter.Name); // set the transformed value parameter.Value = output[field.Name].ToString(); parameter.PostBack = field.PostBack; // auto is changed to true|false in transformalize // set the validation results if (parameter.Validators.Any()) { if ((bool)output[field.ValidField]) { parameter.Valid = "true"; } else { parameter.Valid = "false"; parameter.Message = ((string)output[field.MessageField]).TrimEnd('|'); } } // set the visibility if (string.IsNullOrEmpty(parameter.Visible)) { parameter.Visible = "true"; } else { if (jintVisibility == null) { jintVisibility = new JintVisibility(); } var response = jintVisibility.Visible(new JvRequest(output, parameter.Visible)); if (response.Faulted) { _logger.Error(() => $"Parameter {parameter.Name} has a visible script error: {response.Message}"); _notifier.Error(H[$"Parameter {parameter.Name} has a visible script error: {response.Message}"]); } parameter.Visible = response.Visible.ToString().ToLower(); if (parameter.Visible == "false") { parameter.Valid = "true"; // because they won't be able to fix it } } // remove this stuff because all the transforming and validating is done at this point parameter.T = null; parameter.Transforms.Clear(); parameter.V = null; parameter.Validators.Clear(); } } return(facade.Serialize()); } foreach (var error in process.Errors()) { _logger.Error(() => error); } return(cfg); }