//========================================================================= /// <summary> /// /// </summary> /// <param name="context"></param> /// <returns></returns> //========================================================================= public override string description(string context) { StringBuilder str = new StringBuilder(""); try { if (context.Length < 1) { str.Append(base.description("")); } else { XmlDocument Doc = new XmlDocument(); Doc.LoadXml(context); if (Doc != null) { String ExecutableFileName = XmlHelper.Attribute(Doc.DocumentElement, "executable"); FType = XmlHelper.Attribute(Doc.DocumentElement, "class"); Assembly Assemb = Assembly.LoadFile(ExecutableFileName); // Load the assembly. ApsimComponent Comp = new ApsimComponent(Assemb, 0, this); XmlNode InitData = XmlHelper.Find(Doc.DocumentElement, "initdata"); str.Append(Comp.GetDescription(InitData)); } } } catch (Exception err) { Console.WriteLine(err.Message); } return(str.ToString()); }
//---------------------------------------------------------------------- /// <summary> /// Create a DotNetProxy class to represent an Apsim component. /// <param name="TypeToFind">The type to find. [Type.]ProxyClass.</param> /// <param name="FQN"></param> /// <param name="Comp"></param> /// </summary> //---------------------------------------------------------------------- protected static Object CreateDotNetProxy(String TypeToFind, String FQN, ApsimComponent Comp) { Type ProxyType; if (TypeToFind == "ProtocolManager") { TypeToFind = "Paddock"; } if (TypeToFind == "Paddock" || TypeToFind == "Component" || TypeToFind == "Simulation" || TypeToFind == "SystemComponent") { ProxyType = Assembly.GetExecutingAssembly().GetType("ModelFramework." + TypeToFind); } else { ProxyType = ProbeInfo.GetType("ModelFramework." + TypeToFind); } if (ProxyType == null) { throw new Exception("Cannot find proxy reference: " + TypeToFind); } Object[] Parameters = new Object[2]; Parameters[0] = FQN; Parameters[1] = Comp; return(Activator.CreateInstance(ProxyType, Parameters)); }
// -------------------------------------------------------------------- /// <summary> /// /// </summary> /// <param name="Nam"></param> /// <param name="Paren"></param> /// <param name="HostComponent"></param> // -------------------------------------------------------------------- public void Initialise(String Nam, Instance Paren, ApsimComponent ParentComponent) { Name = Nam; Parent = Paren; Component = ParentComponent; Children.ParentName = MyFQN(); Initialising(); }
// -------------------------------------------------------------------- /// <summary> /// Constructor /// </summary> /// <param name="_FullName">Name of the actual component</param> /// <param name="CompClass">The component class name. eg. Report.Ouputfile</param> /// <param name="component">The apsim component that hosts this object</param> // -------------------------------------------------------------------- public Component(String _FullName, String CompClass, object component) { InitClass(_FullName); HostComponent = component as ApsimComponent; //set the type for this component FTypeName = CompClass; }
public LinkField(Instance _In, PropertyInfo _Field, Link _LinkAttr) { In = _In; Field = new ReflectedProperty(_Field, In.Model); LinkAttr = _LinkAttr; Comp = In.ParentComponent(); ProbeInfo = null; }
// -------------------------------------------------------------------- /// <summary> /// Create instances (and populate their fields and properies of all /// classes as specified by the Xml passed in. The newly created root /// instance can be retrieved by the 'Root' property. /// </summary> /// <param name="Xml"></param> /// <param name="AssemblyWithTypes"></param> /// <param name="HostComponent"></param> // -------------------------------------------------------------------- public void Create(String Xml, Assembly AssemblyWithTypes, ApsimComponent ParentComponent) { CallingAssembly = AssemblyWithTypes; XmlDocument Doc = new XmlDocument(); Doc.LoadXml(Xml); RemoveShortCuts(Doc.DocumentElement); _Root = CreateInstance(Doc.DocumentElement, null, null, ParentComponent); }
// -------------------------------------------------------------------- /// <summary> /// Constructor /// </summary> /// <param name="In">Instance of a root/leaf/shoot/phenology</param> // -------------------------------------------------------------------- internal Component(Instance _In) { In = _In; //use the name of the owner component of the Instance (e.g. Plant2) InitClass(In.ParentComponent().GetName()); //e.g. Paddock //get the name of the host component for the calling object HostComponent = In.ParentComponent(); //e.g. Plant2 FTypeName = HostComponent.CompClass; //type of Plant2 }
//========================================================================= /// <summary> /// Create an instance of a component here /// </summary> /// <param name="compID"></param> /// <param name="parentCompID"></param> /// <param name="messageCallback"></param> //========================================================================= public TAPSIMHost(uint compID, uint parentCompID, MessageFromLogic messageCallback, String _STYPE, String _SVERSION, String _SAUTHOR) : base(compID, parentCompID, messageCallback, _STYPE, _SVERSION, _SAUTHOR) { //create an APSIM component here Assembly Assemb = Assembly.GetCallingAssembly(); //get the cmp component that uses this library Comp = new ApsimComponent(Assemb, (int)compID, this); Comp.CompClass = _STYPE; Comp.createInstance(Assemb.Location, compID, parentCompID); FModuleName = getModulePath(); entityInfoList = new Dictionary <string, List <TIDSpec> >(); compInfoList = new Dictionary <string, List <TComp> >(); }
// -------------------------------------------------------------------- /// <summary> /// Constructor /// </summary> /// <param name="_FullName">Name of the actual component</param> /// <param name="component">The apsim component that hosts this object</param> // -------------------------------------------------------------------- public Component(String _FullName, object component) { InitClass(_FullName); HostComponent = component as ApsimComponent; //get the type for this component List <TComp> comps = new List <TComp>(); HostComponent.Host.queryCompInfo(FQN, TypeSpec.KIND_COMPONENT, ref comps); if (comps.Count > 0) { FTypeName = comps[0].CompClass; } else { FTypeName = this.GetType().Name; } }
// -------------------------------------------------------------------- /// <summary> /// Create an instance of a the 'Instance' class based on the /// Node type passed in information. Then populate the instance based /// on the child XML nodes. /// </summary> /// <param name="Node"></param> /// <param name="Parent"></param> /// <param name="ParentInstance"></param> /// <param name="HostComponent"></param> /// <returns></returns> // -------------------------------------------------------------------- private Instance CreateInstance(XmlNode Node, XmlNode Parent, Instance ParentInstance, ApsimComponent ParentComponent) { Type ClassType = GetTypeOfChild(Node, ParentInstance); if (ClassType == null) { throw new Exception("Cannot find a class called: " + Node.Name); } object Model = Activator.CreateInstance(ClassType); Instance CreatedInstance; if (Model.GetType().IsSubclassOf(typeof(Instance))) { CreatedInstance = (Instance)Model; } else { CreatedInstance = new Instance(Model); } //if (CreatedInstance.GetType().IsSubclassOf(typeof(DerivedInstance))) //{ // ((DerivedInstance)CreatedInstance).Initialise(Node, ParentInstance, ParentComponent); //} if (CreatedInstance != null) { CreatedInstance.Initialise(XmlHelper.Name(Node), ParentInstance, ParentComponent); GetAllProperties(CreatedInstance, Parent); GetAllEventHandlers(CreatedInstance); GetAllEvents(CreatedInstance); PopulateParams(CreatedInstance, Node, ParentComponent); } else { throw new Exception("Class " + Node.Name + " must be derived from the \"Instance\" class"); } return(CreatedInstance); }
// -------------------------------------------------------------------- /// <summary> /// /// </summary> /// <param name="In">Instance of a root/leaf/shoot/phenology</param> // -------------------------------------------------------------------- internal SystemComponent(Instance In) : base(In) { //NamePrefix = ""; HostComponent = In.ParentComponent(); }
// -------------------------------------------------------------------- /// <summary> /// Encapsulates an APSIM paddock in a simulation. /// When the component Class is known. /// </summary> /// <param name="Nam">Name of the paddock or system</param> /// <param name="CompClass"></param> /// <param name="component">The hosting component</param> public SystemComponent(String Nam, String CompClass, object component) : base(Nam, CompClass, component) { //NamePrefix = ""; HostComponent = component as ApsimComponent; }
//---------------------------------------------------------------------- /// <summary> /// Go find a component with the specified name. NameToFind can be either /// a relative or absolute address. /// </summary> //---------------------------------------------------------------------- protected static Object GetSpecificApsimComponent(String NameToFind, string TypeToFind, ApsimComponent Comp) { Object comp = CreateDotNetProxy(TypeToFind, NameToFind, Comp); // absolute reference. if (comp == null) { // relative reference. String OurName = Comp.GetName(); String ParentName = ""; int PosLastPeriod = OurName.LastIndexOf('.'); if (PosLastPeriod == -1) { throw new Exception("Invalid component name found: " + OurName); } ParentName = OurName.Substring(0, PosLastPeriod); comp = CreateDotNetProxy(NameToFind, ParentName + "." + NameToFind, Comp); } return(comp); }
//---------------------------------------------------------------------- /// <summary> /// Go find an Apsim component IN SCOPE that matches the specified name and type. /// IN SCOPE means a component that is a sibling (or in the system above ?????) /// </summary> /// <param name="NameToFind">Name of the component.</param> /// <param name="TypeToFind">The type to find. [Type.]ProxyClass</param> /// <param name="SystemName"></param> /// <param name="Comp"></param> //---------------------------------------------------------------------- internal static Object FindApsimComponent(String NameToFind, String TypeToFind, string SystemName, ApsimComponent Comp) { if ((TypeToFind == "Simulation") && (NameToFind == null) && (SystemName.Length == 0)) //if the parent is the simulation { return(CreateDotNetProxy(TypeToFind, SystemName, Comp)); } if ((TypeToFind == "Paddock") && (NameToFind == null) && (SystemName.Length > 0)) //if the parent is a paddock/system { return(CreateDotNetProxy(TypeToFind, SystemName, Comp)); } if ((TypeToFind == "SystemComponent") && (NameToFind == null)) //if the parent is a systemcomponent { return(CreateDotNetProxy(TypeToFind, SystemName, Comp)); } if (TypeToFind == "Component" && NameToFind == null) { return(CreateDotNetProxy(TypeToFind, Comp.Name, Comp)); } //Get a list of siblings. String sSearchName = "*"; if (SystemName.Length > 0) { sSearchName = SystemName + ".*"; //search parent.* } if (NameToFind != null && NameToFind.Contains("*")) { sSearchName = NameToFind; } List <TComp> comps = new List <TComp>(); Comp.Host.queryCompInfo(sSearchName, TypeSpec.KIND_COMPONENT, ref comps); //using sibling components find the one to create. String SiblingShortName = ""; // The TypeToFind passed in as [Type.]DotNetProxy . We need to convert this to a Component Type // e.g. TypeToFind = Plant2.Lucerne2, Component Type = Plant2, ProxyClass = Lucerne2 // Query DotNetProxies for metadata about the TypeToFind class. Find [ComponentType()] attribute String compClass = ""; if (TypeToFind != null) { Type ProxyType; ProxyType = ProbeInfo.GetType("ModelFramework." + unQualifiedName(TypeToFind)); if (ProxyType != null) { Attribute[] attribs = Attribute.GetCustomAttributes(ProxyType); foreach (Attribute attrib in attribs) { if (attrib.GetType() == typeof(ComponentTypeAttribute)) { compClass = ((ComponentTypeAttribute)attrib).ComponentClass; } if (compClass.ToLower() != unQualifiedName(TypeToFind).ToLower()) { compClass += "." + unQualifiedName(TypeToFind); //e.g Plant2.Lucerne2 } } } else { //this TypeToFind may have been Plant2 which means we search through the components //to get the full Type.DotNetProxy type foreach (TComp pair in comps) { int firstPeriod = pair.CompClass.IndexOf('.'); if (firstPeriod == -1) { firstPeriod = pair.CompClass.Length; } String SiblingType = pair.CompClass.Substring(0, firstPeriod); if (SiblingType.ToLower() == TypeToFind.ToLower()) { return(CreateDotNetProxy(unQualifiedName(pair.CompClass), pair.name, Comp)); } } } //for each sibling of this component foreach (TComp pair in comps) { String SiblingType = pair.CompClass; if (SiblingType.ToLower() == compClass.ToLower() || unQualifiedName(SiblingType).ToLower() == compClass.ToLower()) { SiblingShortName = unQualifiedName(pair.name).ToLower(); if (NameToFind == null || NameToFind.Contains("*") || NameToFind.ToLower() == SiblingShortName) { return(CreateDotNetProxy(unQualifiedName(TypeToFind), pair.name, Comp)); } } } } else { //TypeToFind==null but the name is used. So then we can use the compClass //that was found for the component using queryInfo before. string ShortNameToFind = unQualifiedName(NameToFind); foreach (TComp pair in comps) //for each sibling of this component { SiblingShortName = unQualifiedName(pair.name).ToLower(); if (ShortNameToFind.ToLower() == SiblingShortName) { compClass = unQualifiedName(pair.CompClass); if (compClass.Length > 0) { //find the proxytype for this component class return(CreateDotNetProxy(compClass, pair.name, Comp)); } } } } // If we get this far then we didn't find the APSIM component. Try our parent system. string ParentSystem = ""; int lastDot = SystemName.LastIndexOf("."); if (lastDot >= 0) { ParentSystem = SystemName.Substring(0, lastDot); } if (!((ParentSystem == "") && (SystemName == ""))) { return(FindApsimComponent(NameToFind, TypeToFind, ParentSystem, Comp)); } else { return(null); } }
/// <summary> /// Constructor /// </summary> /// <param name="component"></param> /// <param name="VariableName">FQN of the variable</param> public Variable(object component, String VariableName) { Component = component as ApsimComponent; Name = VariableName; }
//------------------------------------------------------------------------- /// <summary> /// Return a object that matches the specified type and name. /// <param name="TypeToFind">The type to find. [Type.]ProxyClass. Would be the paddock type when /// when the NameToFind is expected to be a child of the paddock.</param> /// <param name="NameToFind">Name of the component. Can be null. </param> /// <param name="SystemName"></param> /// <param name="Comp"></param> /// </summary> //------------------------------------------------------------------------- public static Object FindApsimObject(String TypeToFind, String NameToFind, string SystemName, ApsimComponent Comp) { Object ReferencedObject; if (TypeToFind != null && NameToFind != null && NameToFind.Contains(".") && !NameToFind.Contains("*")) { ReferencedObject = GetSpecificApsimComponent(NameToFind, TypeToFind, Comp); } else { ReferencedObject = FindApsimComponent(NameToFind, TypeToFind, SystemName, Comp); } return(ReferencedObject); }
// -------------------------------------------------------------------- /// <summary> /// Check for parameters in the model that haven't been given a value and throw if any /// are found. Also do range checking, if applicable. /// </summary> // -------------------------------------------------------------------- public void CheckParameters(ApsimComponent ModelInstance) { String Errors = ""; String RangeMsgs = ""; for (int i = 0; i != RegisteredProperties.Count; i++) { FactoryProperty Property = RegisteredProperties[i]; if (Property.IsParam) { if (!Property.HasAsValue && !Property.OptionalParam) { if (Errors != "") { Errors += ", "; } Errors += Property.FQN; } // Is there a tidier way to do this? if (Property.HasAsValue && (!Double.IsNaN(Property.ParamMinVal) || !Double.IsNaN(Property.ParamMaxVal))) { if (Property.TypeName == "Double" || Property.TypeName == "Single" || Property.TypeName == "Int32") { double val = Convert.ToDouble(Property.Get.ToString()); if (!Double.IsNaN(Property.ParamMinVal) && val < Property.ParamMinVal) { RangeMsgs += "The value provided for parameter " + Property.FQN + " is less than its allowed minimum (" + Property.Get.ToString() + " vs. " + Property.ParamMinVal + ")\n"; } if (!Double.IsNaN(Property.ParamMaxVal) && val > Property.ParamMaxVal) { RangeMsgs += "The value provided for parameter " + Property.FQN + " is greater than its allowed maximum (" + Property.Get.ToString() + " vs. " + Property.ParamMaxVal + ")\n"; } } else if (Property.TypeName == "Double[]") { CheckArray <double>(Property, RangeMsgs); } else if (Property.TypeName == "Single[]") { CheckArray <float>(Property, RangeMsgs); } else if (Property.TypeName == "Int32[]") { CheckArray <int>(Property, RangeMsgs); } } } } if (Errors != "") { throw new Exception("The following parameters haven't been initialised: " + Errors); } if (RangeMsgs != "") { string rangeMessage = "In " + Root.InstanceName + ", the following parameters are outside their allowable ranges:\n" + RangeMsgs; if (ModelInstance != null) { ModelInstance.Warning(rangeMessage); } else { throw new Exception(rangeMessage); } } }
// -------------------------------------------------------------------- /// <summary> /// Go through all child XML nodes for the node passed in and set /// the corresponding property values in the Obj instance passed in. /// </summary> /// <param name="Obj"></param> /// <param name="Node"></param> /// <param name="HostComponent"></param> // -------------------------------------------------------------------- private void PopulateParams(Instance Obj, XmlNode Node, ApsimComponent ParentComponent) { // Look for an XmlNode param. If found then given it our current 'Node'. bool HavePassedXMLToObj = false; foreach (FactoryProperty Property in RegisteredProperties) { if ((String.Compare(Property.TypeName, "XmlNode", StringComparison.Ordinal) == 0) && (Property.OutputName.Contains(Node.Name))) { Property.SetObject(Node); HavePassedXMLToObj = true; } } // Go through all child XML nodes for the node passed in and set // the corresponding property values in the Obj instance passed in. if (!HavePassedXMLToObj) { foreach (XmlNode Child in Node.ChildNodes) { if (Child.GetType() != typeof(XmlComment)) { Type t = GetTypeOfChild(Child, Obj); if ((t != null) && (t.IsSubclassOf(typeof(Instance)) || t.IsClass)) { // Create a child instance - indirect recursion. Instance ChildInstance = CreateInstance(Child, Child, Obj, ParentComponent); Obj.Add(ChildInstance); FactoryProperty Parameter = FindProperty(Child); if (XmlHelper.Name(Child).Contains("[")) { String ArrayName = XmlHelper.Name(Child); StringManip.SplitOffBracketedValue(ref ArrayName, '[', ']'); XmlHelper.SetName(Child, ArrayName); Parameter = FindProperty(Child); if (Parameter != null) { Parameter.AddToList(ChildInstance); } else { // Parameter must be an array link to child nodes e.g. // [Link] LeafCohort[] InitialLeaves; } } else if ((Parameter != null) && (Parameter.IsParam && !Parameter.TypeName.Contains("System::"))) { Parameter.SetObject(ChildInstance.Model); } } else if (Child.Name == "Memo") { // Ignore memo fields. } else { FactoryProperty Parameter = FindProperty(Child); if (Parameter != null) { Parameter.Name = XmlHelper.Name(Child); Parameter.Set(Child); } } } } } }