예제 #1
0
        private List <Dictionary <string, object> > GetJson(DataTable dt)
        {
            var rows = new List <Dictionary <string, object> >();

            var reportColumns = new IReportColumn[dt.Columns.Count];

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                reportColumns[i] = _reportColumns.Single(x => x.SqlAlias == dt.Columns[i].ColumnName);
            }

            foreach (DataRow dr in dt.Rows)
            {
                var row = new Dictionary <string, object>();

                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    string value = "";
                    if (dr[j] != null)
                    {
                        value = reportColumns[j].OutputValueTransformation(dr[j].ToString());
                    }

                    row.Add(dt.Columns[j].ColumnName, value);
                }

                rows.Add(row);
            }

            return(rows);
        }
예제 #2
0
        public void AddReportColumn(IReportColumn reportColumn)
        {
            if (reportColumn == null)
            {
                throw new ArgumentNullException("reportColumn");
            }

            if (_reportColumns.Any(x => x.SqlAlias == reportColumn.SqlAlias))
            {
                throw new ReportException(string.Format("Report model can not contain columns with equal SqlAliaces: {0}", reportColumn.SqlAlias));
            }

            _reportColumns.Add(reportColumn);
        }
예제 #3
0
        /// <summary>
        /// Insert, at the correct location, the specified column into the columns list
        /// Need to ensure that array columns are kept in order.
        /// </summary>
        /// <param name="column">The column to insert.</param>
        /// <param name="flattenedColumns">The returned flattened columns.</param>
        private static void InsertColumn(IReportColumn column, List <IReportColumn> flattenedColumns)
        {
            int indexOfBracket = column.Name.IndexOf('(');

            if (indexOfBracket != -1)
            {
                // find the last column that has a name is identical up to bracketed value.
                string namePrefixToMatch  = column.Name.Substring(0, indexOfBracket);
                int    indexToInsertAfter = flattenedColumns.FindLastIndex(col => col.Name.StartsWith(namePrefixToMatch));
                if (indexToInsertAfter != -1)
                {
                    flattenedColumns.Insert(indexToInsertAfter + 1, column);
                    return;
                }
            }
            flattenedColumns.Add(column);
        }
예제 #4
0
        public void BuildQuery_GivenMultipleReportColumns_ValidSqlCommand()
        {
            var reportColumns = new IReportColumn[]
            {
                new ReportColumn
                {
                    Title = "First Field",
                    SqlValueExpression = "TestTable.fField",
                },
                new ReportColumn
                {
                    Title = "Second Field",
                    SqlValueExpression = "TestTable.sField",
                },
            };

            SqlCommand command = queryBuilder.BuildQuery(reportColumns, Enumerable.Empty <IReportFilter>(), _dataSource);

            Assert.That(command.CommandText, Is.EqualTo("SELECT (TestTable.fField) AS FirstField, (TestTable.sField) AS SecondField FROM TestTable"));
            Assert.That(command.Parameters.Count, Is.EqualTo(0));
        }
예제 #5
0
파일: Locater.cs 프로젝트: lie112/ApsimX
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</param>
        /// <param name="relativeTo">The model calling this method</param>
        /// <param name="ignoreCase">If true, ignore case when searching for the object or property</param>
        /// <returns>The found object or null if not found</returns>
        public IVariable GetInternal(string namePath, Model relativeTo, bool ignoreCase = false)
        {
            Model            relativeToModel = relativeTo;
            string           cacheKey        = namePath;
            StringComparison compareType     = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = GetFromCache(cacheKey, relativeToModel);

            if (value != null)
            {
                return(value as IVariable);
            }

            IVariable returnVariable = null;

            if (namePath == null || namePath.Length == 0)
            {
                return(null);
            }
            else if (namePath[0] != '.' &&
                     namePath.Replace("()", "").IndexOfAny("(+*/".ToCharArray()) != -1)
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeToModel);
            }
            else
            {
                // Remove a square bracketed model name and change our relativeTo model to
                // the referenced model.
                if (namePath.StartsWith("["))
                {
                    int posCloseBracket = namePath.IndexOf(']');
                    if (posCloseBracket == -1)
                    {
                        return(null);
                    }
                    string modelName = namePath.Substring(1, posCloseBracket - 1);
                    namePath = namePath.Remove(0, posCloseBracket + 1);
                    Model foundModel = relativeToModel.FindInScope(modelName) as Model;
                    if (foundModel == null)
                    {
                        // Didn't find a model with a name matching the square bracketed string so
                        // now try and look for a model with a type matching the square bracketed string.
                        Type[] modelTypes = GetTypeWithoutNameSpace(modelName);
                        if (modelTypes.Length == 1)
                        {
                            foundModel = relativeToModel.FindAllInScope().FirstOrDefault(m => modelTypes[0].IsAssignableFrom(m.GetType())) as Model;
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeToModel = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    Model root = relativeToModel;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeToModel = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        // Path starts with a . and only contains a single period.
                        // If name matches then no problem. Otherwise we need to return null.
                        posPeriod = namePath.IndexOf('.');
                        if (namePath.Remove(0, posPeriod) == relativeToModel.Name)
                        {
                            posPeriod = namePath.Length;
                        }
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath = namePath.Remove(0, 1);
                    }
                }
                else
                {
                    // Try a report column.
                    foreach (Report report in relativeTo.FindAllInScope <Report>())
                    {
                        IReportColumn column = report.Columns?.Find(c => c.Name == namePath);
                        if (column != null)
                        {
                            return(new VariableObject(column.GetValue(0)));
                        }
                    }
                }

                // Now walk the series of '.' separated path bits, assuming the path bits
                // are child models. Stop when we can't find the child model.
                string[] namePathBits = namePath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (namePathBits.Length == 0 && !string.IsNullOrEmpty(namePath))
                {
                    throw new Exception($"Invalid variable name: '{cacheKey}'");
                }

                int i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeToModel.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                    if (localModel == null)
                    {
                        // Allow for the possibility that the first path element may point to
                        // the starting parent model, rather than to a child within that model
                        if ((i == 0) && relativeToModel.Name.Equals(namePathBits[i], compareType))
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        relativeToModel = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo or the path is invalid.
                // We now need to loop through the remaining path bits and keep track of each
                // section of the path as each section will have to be evaulated everytime a
                // a get is done for this path.
                // The variable 'i' will point to the name path that cannot be found as a model.
                object           relativeToObject = relativeToModel;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeToModel));
                for (int j = i; j < namePathBits.Length; j++)
                {
                    // look for an array specifier e.g. sw[2]
                    string arraySpecifier = null;
                    if (namePathBits[j].Contains("["))
                    {
                        arraySpecifier = StringUtilities.SplitOffBracketedValue(ref namePathBits[j], '[', ']');
                    }

                    // Look for either a property or a child model.
                    IModel localModel = null;
                    if (relativeToObject == null)
                    {
                        return(null);
                    }
                    PropertyInfo propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j]);
                    if (propertyInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                    {
                        propertyInfo = relativeToObject.GetType().GetProperty(namePathBits[j], BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    }
                    if (relativeToObject is IFunction && namePathBits[j] == "Value()")
                    {
                        MethodInfo method = relativeToModel.GetType().GetMethod("Value");
                        properties.Add(new VariableMethod(relativeToModel, method));
                    }
                    else if (propertyInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                        if (localModel == null)
                        {
                            return(null);
                        }

                        properties.Add(new VariableObject(localModel));
                        relativeToObject = localModel;
                    }
                    else if (propertyInfo != null)
                    {
                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else if (relativeToObject is IList)
                    {
                        // Special case: we are trying to get a property of an array(IList). In this case
                        // we want to return the property value for all items in the array.
                        VariableProperty property = new VariableProperty(relativeToObject, namePathBits[j], arraySpecifier);
                        properties.Add(property);
                        relativeToObject = property.Value;
                    }
                    else
                    {
                        return(null);
                    }
                }

                // We now have a list of IVariable instances that can be evaluated to
                // produce a return value for the given path. Wrap the list into an IVariable.
                returnVariable = new VariableComposite(namePath, properties);
            }

            // Add variable to cache.
            AddToCache(cacheKey, relativeTo, returnVariable);

            return(returnVariable);
        }
예제 #6
0
        /// <summary>
        /// 'Flatten' the object passed in, into a list of columns ready to be added
        /// to a data table.
        /// </summary>
        /// <param name="name">Column name where the value came from.</param>
        /// <param name="units">Units of measurement; null if not applicable</param>
        /// <param name="value">The object to be analyzed and flattened</param>
        /// <param name="rowIndex">The row index of the specified value.</param>
        /// <param name="flattenedColumns">The returned flattened columns.</param>
        /// <returns>The list of values that can be written to a data table</returns>
        private static void FlattenValue(string name, string units, object value, int rowIndex, List <IReportColumn> flattenedColumns)
        {
            if (value == null || value.GetType() == typeof(DateTime) || value.GetType() == typeof(string) || !value.GetType().IsClass)
            {
                // Scalar
                IReportColumn flattenedColumn = flattenedColumns.Find(col => col.Name == name);
                if (flattenedColumn == null)
                {
                    flattenedColumn = new ReportColumnWithValues(name, units);
                    InsertColumn(flattenedColumn, flattenedColumns);
                }

                // Ensure all columns have the correct number of values.
                foreach (IReportColumn column in flattenedColumns)
                {
                    if (column is ReportColumnConstantValue)
                    {
                    }
                    else
                    {
                        while (column.Values.Count <= rowIndex)
                        {
                            column.Values.Add(null);
                        }
                    }
                }

                flattenedColumn.Values[rowIndex] = value;
            }
            else if (value.GetType().IsArray)
            {
                // Array
                Array array = value as Array;

                for (int columnIndex = 0; columnIndex < array.Length; columnIndex++)
                {
                    string heading = name;
                    heading += "(" + (columnIndex + 1).ToString() + ")";

                    object arrayElement = array.GetValue(columnIndex);
                    FlattenValue(heading, units, arrayElement, rowIndex, flattenedColumns);  // recursion
                }
            }
            else if (value.GetType().GetInterface("IList") != null)
            {
                // List
                IList array = value as IList;
                for (int columnIndex = 0; columnIndex < array.Count; columnIndex++)
                {
                    string heading = name;
                    heading += "(" + (columnIndex + 1).ToString() + ")";

                    object arrayElement = array[columnIndex];
                    FlattenValue(heading, units, arrayElement, rowIndex, flattenedColumns);  // recursion
                }
            }
            else
            {
                // A struct or class
                foreach (PropertyInfo property in ReflectionUtilities.GetPropertiesSorted(value.GetType(), BindingFlags.Instance | BindingFlags.Public))
                {
                    object[] attrs     = property.GetCustomAttributes(true);
                    string   propUnits = null;
                    bool     ignore    = false;
                    foreach (object attr in attrs)
                    {
                        if (attr is XmlIgnoreAttribute)
                        {
                            ignore = true;
                            continue;
                        }
                        Core.UnitsAttribute unitsAttr = attr as Core.UnitsAttribute;
                        if (unitsAttr != null)
                        {
                            propUnits = unitsAttr.ToString();
                        }
                    }
                    if (ignore)
                    {
                        continue;
                    }
                    string heading      = name + "." + property.Name;
                    object classElement = property.GetValue(value, null);
                    FlattenValue(heading, propUnits, classElement, rowIndex, flattenedColumns);
                }
            }
        }