예제 #1
0

        
예제 #2
0
파일: Apsim.cs 프로젝트: ver078/ApsimX
 /// <summary>Deletes the specified model.</summary>
 /// <param name="model">The model.</param>
 public static bool Delete(IModel model)
 {
     Locator(model.Parent).Clear();
     Apsim.ClearCaches(model);
     return(model.Parent.Children.Remove(model as Model));
 }
예제 #3
0
 /// <summary>Add the specified model to the parent.</summary>
 /// <param name="parent">The parent model</param>
 /// <param name="modelToAdd">The child model.</param>
 public static void Add(IModel parent, IModel modelToAdd)
 {
     modelToAdd.Parent = parent;
     Apsim.ParentAllChildren(modelToAdd);
     parent.Children.Add(modelToAdd as Model);
 }
예제 #4
0
 /// <summary>Gets a model in scope of the specified type</summary>
 /// <param name="typeToMatch">The type of the model to return</param>
 /// <returns>The found model or null if not found</returns>
 public IModel Get(Type typeToMatch)
 {
     return(Apsim.Find(relativeToModel, typeToMatch));
 }
예제 #5
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</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>
        private IVariable GetInternal(string namePath, bool ignoreCase = true)
        {
            IModel           relativeTo  = relativeToModel;
            string           cacheKey    = namePath;
            StringComparison compareType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = null;

            if (cache.ContainsKey(cacheKey))
            {
                value = cache[cacheKey];
            }
            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
                      | (namePath.IndexOfAny("(".ToCharArray()) >= 0 && namePath.Substring(0, (namePath.IndexOf('(') >= 0? namePath.IndexOf('(') : 0)).IndexOfAny("[.".ToCharArray()) == -1)))
            {
                // expression - need a better way of detecting an expression
                returnVariable = new VariableExpression(namePath, relativeTo as Model);
            }
            else
            {
                namePath = namePath.Replace("Value()", "Value().");
                // 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 = Apsim.Find(relativeTo, 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 = Apsim.Find(relativeTo, modelTypes[0]) as Model;
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeTo = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    IModel root = relativeTo;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeTo = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // 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);
                int      i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeTo.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType) && m.Enabled);
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeTo = localModel as Model;
                    }
                }

                // At this point there are only 2 possibilities. We have encountered a
                // PropertyInfo/MethodInfo 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 = relativeTo;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeTo));
                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);
                    }

                    // Check property info
                    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 not property info
                    // Check method info
                    MethodInfo    methodInfo    = null;
                    List <object> argumentsList = null;
                    if (propertyInfo == null)
                    {
                        if (namePathBits[j].IndexOf('(') > 0)
                        {
                            relativeToObject.GetType().GetMethod(namePathBits[j].Substring(0, namePathBits[j].IndexOf('(')));
                            if (methodInfo == null && ignoreCase) // If not found, try using a case-insensitive search
                            {
                                methodInfo = relativeToObject.GetType().GetMethod(namePathBits[j].Substring(0, namePathBits[j].IndexOf('(')), BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase);
                            }
                        }
                        if (methodInfo != null)
                        {
                            // get arguments and store in VariableMethod
                            string args = namePathBits[j].Substring(namePathBits[j].IndexOf('('));
                            args = args.Substring(0, args.IndexOf(')'));
                            args = args.Replace("(", "").Replace(")", "");
                            if (args.Length > 0)
                            {
                                argumentsList = new List <object>();
                                args          = args.Trim('(').Trim(')');
                                var argList = args.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                // get arguments
                                ParameterInfo[] pars = methodInfo.GetParameters();

                                for (int argid = 0; argid < argList.Length; argid++)
                                {
                                    var cleanArg = argList[argid].Trim(' ').Trim(new char[] { '(', ')' }).Trim(' ').Trim('"');
                                    switch (Type.GetTypeCode(pars[argid].ParameterType))
                                    {
                                    case TypeCode.Double:
                                        argumentsList.Add(Convert.ToDouble(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    case TypeCode.Int32:
                                        argumentsList.Add(Convert.ToInt32(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    case TypeCode.String:
                                        argumentsList.Add(cleanArg);
                                        break;

                                    case TypeCode.Boolean:
                                        argumentsList.Add(Convert.ToBoolean(cleanArg, CultureInfo.InvariantCulture));
                                        break;

                                    default:
                                        throw new ApsimXException(relativeToModel, "The type of argument (" + Type.GetTypeCode(pars[argid].ParameterType) + ") is not currently supported in Report methods");
                                    }
                                }
                            }
                        }
                    }

                    //if (relativeToObject is IFunction && namePathBits[j] == "Value()")
                    //{
                    //    MethodInfo method = relativeTo.GetType().GetMethod("Value");
                    //    properties.Add(new VariableMethod(relativeTo, method));
                    //}
                    //                    else if (propertyInfo == null && methodInfo == null && relativeToObject is Model)

                    if (propertyInfo == null && methodInfo == null && relativeToObject is Model)
                    {
                        // Not a property, may be an unchecked method or a child model.
                        localModel = (relativeToObject as IModel).Children.FirstOrDefault(m => m.Name.Equals(namePathBits[j], compareType));
                        if (localModel == null)
                        {
                            // Not a model
                            return(null);
                        }
                        else
                        {
                            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 (methodInfo != null)
                    {
                        VariableMethod method = null;
                        if (argumentsList != null)
                        {
                            method = new VariableMethod(relativeToObject, methodInfo, argumentsList.ToArray <object>());
                        }
                        else
                        {
                            method = new VariableMethod(relativeToObject, methodInfo, null);
                        }
                        //                        VariableProperty property = new VariableProperty(relativeToObject, propertyInfo, arraySpecifier);
                        properties.Add(method);
                        relativeToObject = method.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]);
                        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.
            cache.Add(cacheKey, returnVariable);

            return(returnVariable);
        }
예제 #6
0
        /// <summary>Documents the specified model.</summary>
        /// <param name="modelNameToDocument">The model name to document.</param>
        /// <param name="tags">The auto doc tags.</param>
        /// <param name="headingLevel">The starting heading level.</param>
        public void DocumentModel(string modelNameToDocument, List <AutoDocumentation.ITag> tags, int headingLevel)
        {
            Simulation simulation = Apsim.Find(this, typeof(Simulation)) as Simulation;

            if (simulation != null)
            {
                // Find the model of the right name.
                IModel modelToDocument = Apsim.Find(simulation, modelNameToDocument);

                // If not found then find a model of the specified type.
                if (modelToDocument == null)
                {
                    modelToDocument = Apsim.Get(simulation, "[" + modelNameToDocument + "]") as IModel;
                }

                // If the simulation has the same name as the model we want to document, dig a bit deeper
                if (modelToDocument == simulation)
                {
                    modelToDocument = Apsim.ChildrenRecursivelyVisible(simulation).FirstOrDefault(m => m.Name.Equals(modelNameToDocument, StringComparison.OrdinalIgnoreCase));
                }

                // If still not found throw an error.
                if (modelToDocument != null)
                {
                    // Get the path of the model (relative to parentSimulation) to document so that
                    // when replacements happen below we will point to the replacement model not the
                    // one passed into this method.
                    string pathOfSimulation      = Apsim.FullPath(simulation) + ".";
                    string pathOfModelToDocument = Apsim.FullPath(modelToDocument).Replace(pathOfSimulation, "");

                    // Clone the simulation
                    Simulation clonedSimulation = Apsim.Clone(simulation) as Simulation;

                    // Make any substitutions.
                    MakeSubstitutions(clonedSimulation);

                    // Now use the path to get the model we want to document.
                    modelToDocument = Apsim.Get(clonedSimulation, pathOfModelToDocument) as IModel;

                    if (modelToDocument == null)
                    {
                        throw new Exception("Cannot find model to document: " + modelNameToDocument);
                    }

                    // resolve all links in cloned simulation.
                    Links.Resolve(clonedSimulation);

                    modelToDocument.IncludeInDocumentation = true;
                    foreach (IModel child in Apsim.ChildrenRecursively(modelToDocument))
                    {
                        child.IncludeInDocumentation = true;
                    }

                    // Document the model.
                    modelToDocument.Document(tags, headingLevel, 0);

                    // Unresolve links.
                    Links.Unresolve(clonedSimulation);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Get the value of a variable or model.
        /// </summary>
        /// <param name="namePath">The name of the object to return</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>
        private IVariable GetInternal(string namePath, bool ignoreCase = true)
        {
            IModel           relativeTo  = relativeToModel;
            string           cacheKey    = namePath;
            StringComparison compareType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;

            // Look in cache first.
            object value = null;

            if (cache.ContainsKey(cacheKey))
            {
                value = cache[cacheKey];
            }
            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, relativeTo as Model);
            }
            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 = Apsim.Find(relativeTo, 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 = Apsim.Find(relativeTo, modelTypes[0]) as Model;
                        }
                    }
                    if (foundModel == null)
                    {
                        return(null);
                    }
                    else
                    {
                        relativeTo = foundModel;
                    }
                }
                else if (namePath.StartsWith("."))
                {
                    // Absolute path
                    IModel root = relativeTo;
                    while (root.Parent != null)
                    {
                        root = root.Parent as Model;
                    }
                    relativeTo = root;

                    int posPeriod = namePath.IndexOf('.', 1);
                    if (posPeriod == -1)
                    {
                        posPeriod = namePath.Length;
                    }

                    namePath = namePath.Remove(0, posPeriod);
                    if (namePath.StartsWith("."))
                    {
                        namePath.Remove(1);
                    }
                }

                // 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);
                int      i;
                for (i = 0; i < namePathBits.Length; i++)
                {
                    IModel localModel = relativeTo.Children.FirstOrDefault(m => m.Name.Equals(namePathBits[i], compareType));
                    if (localModel == null)
                    {
                        break;
                    }
                    else
                    {
                        relativeTo = 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 = relativeTo;
                List <IVariable> properties       = new List <IVariable>();
                properties.Add(new VariableObject(relativeTo));
                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 = relativeTo.GetType().GetMethod("Value");
                        properties.Add(new VariableMethod(relativeTo, 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[j], 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]);
                        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.
            cache.Add(cacheKey, returnVariable);

            return(returnVariable);
        }