private List <Action <ValueBag> > CompileImportActions(XElement statement, ValueBag validAssignments)
        {
            List <Action <ValueBag> > actions = new List <Action <ValueBag> >();

            foreach (var stmt in statement.Elements())
            {
                switch (stmt.Name.LocalName.ToLower())
                {
                case "console.print":
                    actions.Add((data) => this.console.Print(stmt.Value, data));
                    break;

                case "console.warn":
                    actions.Add((data) => this.console.Warn(stmt.Value, data));
                    break;

                case "console.error":
                    actions.Add((data) => this.console.Error(stmt.Value, data));
                    break;

                case "console.debug":
                    actions.Add((data) => this.console.Debug(stmt.Value, data));
                    break;

                case "let":
                    // a setter takes the form of
                    //   <let propertyname="column name" default="default value"><values><add text="if this" value="then this value" /></values></let>
                    // we need to validate that the setters propertyname is valid
                    var assignment = new Setter(stmt);

                    if (validAssignments.ContainsKey(assignment.Target))
                    {
                        actions.Add((data) => assignment.Assign(data["sourceValues"], data["targetValues"]));
                    }
                    else
                    {
                        this.log.Warn(string.Format("'{0}' is not a valid assignment attribute. Assignment skipped.", assignment.Target));
                    }
                    break;
                }
            }

            return(actions);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Imports the specified data using the specified intructions.
        /// </summary>
        /// <param name="instructions">The instructions.</param>
        /// <param name="data">The data.</param>
        /// <param name="log">The log.</param>
        /// <param name="context">The import context information.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public override void Import(XElement instructions, XElement[] data, Action <int, string> log = null, dynamic context = null)
        {
            log.Info("Running ...");
            if (instructions == null)
            {
                throw new ArgumentNullException("instructions");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            var console = new Terminal(log);

            // compile into an actionable list
            List <Action> actions = new List <Action>();

            foreach (var statement in instructions.Elements())
            {
                switch (statement.Name.LocalName.ToLower())
                {
                case "console.print":
                    actions.Add(() => console.Print(statement.Value));
                    break;

                case "console.warn":
                    actions.Add(() => console.Warn(statement.Value));
                    break;

                case "console.error":
                    actions.Add(() => console.Error(statement.Value));
                    break;

                case "console.debug":
                    actions.Add(() => console.Debug(statement.Value));
                    break;

                case "foreach":
                    actions.Add(() => {
                        List <Action> forEachActions = new List <Action>();
                        List <Importer> importers    = new List <Importer>();

                        // the "foreach" statment is a fairly complex definition to parse
                        // it contains the instructions on which fields and method are to be used to lookup the thing
                        // it also specifies the data element to be used as input

                        //// the "asset" attribute specifies which fields and method to use to lookup the equipment item
                        //if (foreachStatement.Attribute("asset") == null) {
                        //    log.Error("Missing asset attribute. A foreach element must contain an asset attribute.");
                        //    continue;
                        //}

                        //var assetFinder = new EquipmentFinder(foreachStatement.Attribute("asset").Value, organizationID);

                        // the "in" or "rowIn" attribute specifies which data element contains the source data to update from
                        var inAttribute = statement.Attribute("in", "rowIn");

                        if (inAttribute == null)
                        {
                            log.Warn("Missing 'in' attribute. Defaulting to first data element");
                        }

                        // locate the data element that contains the source data to update from
                        XElement dataSource = null;

                        if (inAttribute != null)
                        {
                            foreach (var item in data)
                            {
                                if (item.Attribute("id") != null && item.Attribute("id").Value.ToLower() == inAttribute.Value.ToLower())
                                {
                                    dataSource = item;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            dataSource = data.FirstOrDefault();
                        }

                        if (dataSource == null)
                        {
                            log.Error(string.Format("Unable to determine the data set to use. '{0}'", inAttribute != null ? inAttribute.Value : ""));
                            return;     // continue;
                        }

                        // A foreach element contains a collection of import elements that provide instructions to perform an import operation
                        foreach (var stmt in statement.Elements("console.print", "console.warn", "console.error", "console.debug", "import"))
                        {
                            switch (stmt.Name.LocalName.ToLower())
                            {
                            case "console.print":
                                forEachActions.Add(() => console.Print(stmt.Value));
                                break;

                            case "import":
                                forEachActions.Add(() => {
                                    var importStatement = stmt;
                                    // every import element must minimally define an into attribute
                                    var intoAttribute = importStatement.Attribute("into");

                                    if (intoAttribute == null)
                                    {
                                        log.Error("Missing into attribute. An import element must contain an 'into' attribute.");
                                        return;         // continue;
                                    }

                                    switch (intoAttribute.Value.ToLower())
                                    {
                                    case "alarm":
                                    case "labresult":
                                        // import lab result
                                        // An import element contains a collection of let elements that provide instructions as to which data columns
                                        // are to be assigned to which lab result properties
                                        var setters = new List <Setter>();

                                        // a setter takes the form of
                                        //   <let propertyname="column name" default="default value"><values><add text="if this" value="then this value" /></values></let>
                                        // we need to validate that the setters propertyname is valid for a lab result
                                        // review each setter and ensure that the setter is within the vocabulary of a lab result definition
                                        var labResultAttributes = new ValueBag(new LabResult());

                                        foreach (var item in importStatement.Elements("let"))
                                        {
                                            var assignment = new Setter(item);

                                            if (labResultAttributes.ContainsKey(assignment.Target))
                                            {
                                                setters.Add(new Setter(item));
                                            }
                                            else
                                            {
                                                log.Warn(string.Format("'{0}' is not a valid lab result attribute. Assignment skipped.", assignment.Target));
                                            }
                                        }

                                        importers.Add(new LabResultImporter(setters, log));
                                        break;

                                    //case "values":
                                    //    // import gassing values
                                    //    importers.Add(new ValuesImporter(ValueHarvester.Load(importStatement), log));
                                    //    break;

                                    default:
                                        log.Warn(string.Format("'{0}' is not a recognized import subject. Ignoring import operation.", intoAttribute.GetValueOrDefault()));
                                        break;
                                    }
                                });
                                break;
                            }
                        }

                        foreach (var act in forEachActions)
                        {
                            act();
                        }

                        // Prepare to read the source data
                        int rowNumber     = 0;
                        DataReader reader = DataReader.Load(dataSource);

                        // import each row in the data source using the defined let statements
                        foreach (var row in reader.DataEnumerator())
                        {
                            //Equipment asset = assetFinder.Find(row);
                            var sourceValues = new ValueBag(row);

                            rowNumber++;

                            ////if (asset == null)
                            ////    log.Warn(string.Format("RowNumber: {1:00000#} equipment not found. Failed to resolve {0}.", assetFinder.Statement(row) as string, rowNumber));
                            ////else
                            foreach (var importer in importers)
                            {
                                try {
                                    importer.Import(sourceValues, rowNumber);
                                } catch (Exception ex) {
                                    log.Error(ex.Message);
                                }
                            }
                        }
                    });
                    break;

                default:
                    break;
                }
            }

            foreach (var action in actions)
            {
                action();
            }

            // first up, parse the instructions into something actionable here
            // execute the instructions

            foreach (var foreachStatement in instructions.Elements("foreach"))
            {
            }

            log.Info("Running ... Done.");
        }