//============================================================================== /// <summary> /// Searching for a suitable model class name. /// </summary> /// <param name="xmlParse"></param> /// <param name="modelNode"></param> /// <param name="compDll"></param> /// <returns></returns> //============================================================================== protected String findCompClassName(TXMLParser xmlParse, XmlNode modelNode, String compDll) { XmlNode aNode; String attrVal; String result = ""; if (modelNode != null) { aNode = xmlParse.firstElementChild(modelNode, "Cultivar"); if (aNode != null) { attrVal = xmlParse.getAttrValue(aNode, "name"); result = attrVal; } else { aNode = xmlParse.firstElementChild(modelNode, "crop_type"); if (aNode != null) { result = xmlParse.getText(aNode); } if (result.Length < 1) //if this is a non plant then { result = xmlParse.getAttrValue(modelNode, "name"); //try the model type } if (result.Length < 1) //if this is a non plant and non soil then { result = xmlParse.getAttrValue(xmlParse.rootNode(), "name"); //try the Type } } } return(result); }
//============================================================================== /// <summary> /// In the <![CDATA[<component>]]> section, find the dll name (short name). /// </summary> /// <param name="xmlParse"></param> /// <param name="compNode"></param> /// <param name="metaDllValue"></param> /// <returns></returns> //============================================================================== protected String GetDllPathString(TXMLParser xmlParse, XmlNode compNode, String metaDllValue) { String compDll = ""; XmlNode anode; anode = xmlParse.firstElementChild(compNode, "executable"); if (anode != null) { compDll = xmlParse.getAttrValue(anode, "name"); } else //no <executable > { compDll = xmlParse.getAttrValue(compNode, "executable"); } if (compDll.ToLower() == "[dll]") { compDll = metaDllValue; //replace with the <dll> value } else if (compDll.Length > 0) { compDll = fixDllMacros(compDll); } return(compDll); }
//============================================================================== /// <summary> /// Get the matching <![CDATA[<model>]]> section for the macro found. /// </summary> /// <param name="xmlParse"></param> /// <param name="modelMacro"></param> /// <returns></returns> //============================================================================== protected XmlNode getModelNode(TXMLParser xmlParse, String modelMacro) { int idx_1, idx_2, posStartModelType; String modelType; XmlNode modelNode; String buf; XmlNode result = null; String sModel = "[Model"; idx_1 = modelMacro.IndexOf(sModel); idx_2 = modelMacro.IndexOf("]"); posStartModelType = idx_1 + sModel.Length; modelType = modelMacro.Substring(posStartModelType, idx_2 - posStartModelType).Trim(); //get the <Model> section for the parameters modelNode = xmlParse.firstElementChild(xmlParse.rootNode(), "Model"); if (modelNode != null) { if (modelType.Length > 0) { buf = xmlParse.getAttrValue(modelNode, "name"); while (modelType.ToLower() != buf.ToLower()) { modelNode = xmlParse.nextElementSibling(modelNode, "Model"); buf = xmlParse.getAttrValue(modelNode, "name"); } } result = modelNode; } return(result); }
//======================================================================= /// <summary> /// Construct a component event object using XML description. /// </summary> /// <param name="sXML">XML description that contains the DDML of the type.</param> //======================================================================= public TCompEvent(String sXML) { TXMLParser parser; XmlNode anode; String typeText; parser = new TXMLParser(sXML); sDescr = ""; sFullDescr = ""; //build a DDML type from the values in the event description typeText = "<type>"; anode = parser.firstElementChild(parser.rootNode(), "field"); bIsEmpty = (anode == null); while (anode != null) { typeText = typeText + parser.docToString(anode); anode = parser.nextElementSibling(anode, "field"); } typeText = typeText + "</type>"; initType = new TDDMLValue(typeText, ""); //create as a DDML type Name = parser.getAttrValue(parser.rootNode(), "name"); //set this object's attributes sKind = parser.getAttrValue(parser.rootNode(), "kind"); sDescr = parser.getAttrValue(parser.rootNode(), "descr"); if (sKind.Length < 1) { sKind = "published"; // Default when not specified } order = 0; //init to an invalid value anode = parser.firstElementChild(parser.rootNode(), "description"); if (anode != null) { sFullDescr = parser.getText(anode); } }
//============================================================================== /// <summary> /// Get a list of the dlls from the <code>;ltdll;gt</code> elements. Returns the short name. /// </summary> /// <param name="xmlParse"></param> /// <param name="metaDataNode"></param> /// <param name="dllList"></param> //============================================================================== protected void getDllList(TXMLParser xmlParse, XmlNode metaDataNode, List <String> dllList) { XmlNode anode; String compDll; anode = xmlParse.firstElementChild(metaDataNode, "dll"); while (anode != null) { if (anode != null) { compDll = xmlParse.getText(anode); compDll = fixDllMacros(compDll); dllList.Add(compDll); } anode = xmlParse.nextElementSibling(anode, "dll"); } }
//============================================================================== /// <summary> /// Loop through any <![CDATA[<component>]]> items and find the one that matches the /// dll name chosen. /// </summary> /// <param name="xmlParse"></param> /// <param name="parentNode"></param> /// <param name="metaDllPath"></param> /// <param name="dllPath"></param> /// <returns></returns> //============================================================================== protected XmlNode FindCompNode(TXMLParser xmlParse, XmlNode parentNode, String metaDllPath, String dllPath) { String testDll; XmlNode anode; String compPath; XmlNode result = null; testDll = Path.GetFileName(dllPath).ToLower(); anode = xmlParse.firstElementChild(parentNode, "component"); while ((anode != null) && (result == null)) { compPath = GetDllPathString(xmlParse, anode, metaDllPath); //returns full path of dll found in <component> section if (testDll == Path.GetFileName(compPath).ToLower()) { result = anode; } anode = xmlParse.nextElementSibling(anode, "component"); } return(result); }
//============================================================================== /// <summary> /// Get the context string from the specified context file. This could be a .ctx /// file or an apsim .xml file. /// </summary> /// <param name="strContext"></param> /// <param name="modelConsts"></param> /// <param name="dllPath"></param> /// <param name="expandModel">Expand the Model macro in an APSIM init section</param> //============================================================================== public void getContextFromFile(out String strContext, out String modelConsts, String dllPath, Boolean expandModel) { StreamReader fileStream; String context; TXMLParser xmlParse; XmlNode anode; XmlNode metaDataNode; XmlNode modelNode; XmlNode compNode; XmlNode childNode; String compName; String compDll = ""; string compClass = ""; String model; StringBuilder buf; String xml; int i; List <String> dllList; String nodeName; model = ""; strContext = ""; fileStream = new StreamReader(FContextFile); context = fileStream.ReadToEnd(); if (Path.GetExtension(FContextFile).ToLower() == ".ctx") { strContext = context; XmlDocument doc = new XmlDocument(); doc.LoadXml(strContext); String exe = doc.DocumentElement.GetAttribute("executable"); if ((exe.Length > 0) && !exe.Contains(Path.DirectorySeparatorChar.ToString()) && dllPath.Contains(Path.DirectorySeparatorChar.ToString())) { XmlNode exeAttr = doc.DocumentElement.GetAttributeNode("executable"); if (exeAttr != null) { exeAttr.Value = dllPath; strContext = doc.OuterXml; } } } else //an apsim .xml file { dllList = new List <String>(); xmlParse = new TXMLParser(context); metaDataNode = xmlParse.firstElementChild(xmlParse.rootNode(), "MetaData"); if (metaDataNode != null) { modelNode = null; getDllList(xmlParse, metaDataNode, dllList); anode = xmlParse.firstElementChild(metaDataNode, "ApsimToSim"); if (anode != null) { if (dllList.Count < 1) { throw new Exception("No dll's found in the context file."); } compNode = FindCompNode(xmlParse, anode, dllList[0], dllPath); //find the matching component section for dllPath if (compNode != null) { compDll = dllPath; //we know the full path so use it compClass = xmlParse.getAttrValue(compNode, "class"); FInitList.Clear(); //now expand the sections under <component><initdata> anode = xmlParse.firstElementChild(compNode, "initdata"); if (anode != null) { anode = xmlParse.firstChild(anode); while (anode != null) //while more children under <initdata> { nodeName = anode.Name; if (nodeName == "PerformInstructions") { childNode = xmlParse.firstElementChild(anode, "ConstructModel"); if (childNode != null) { model = StripMacros(xmlParse.InnerXml(childNode)); break; } } xml = anode.OuterXml; if (xml.Length > 0) { if (xml.Contains("[Model")) //if this is a [Model] macro { if (expandModel) { modelNode = getModelNode(xmlParse, xml); //search for the matching <model> section model = xmlParse.InnerXml(modelNode); } else { model = " " + MODELMACRO + CR; } } if (xmlParse.getNodeType(anode) == XmlNodeType.Element) //get all the init names { FInitList.Add(nodeName); } } anode = xmlParse.nextSibling(anode); } } } //endif compNode <> nil } compName = findCompClassName(xmlParse, modelNode, compDll); if (compName == "") { compName = Path.GetFileNameWithoutExtension(compDll); } if (compClass == "") { compClass = Path.GetFileNameWithoutExtension(compDll); } buf = new StringBuilder(); //now build the correct xml for the context file buf.Append("<component name=\"" + compName.Trim() + "\" executable=\"" + compDll + "\"" + " class=\"" + compClass + "\">"); buf.Append(" <initdata>\r\n"); buf.Append(model); if (compClass.ToLower().StartsWith("plant.")) { if (InitNames.IndexOf("uptake_source") < 0) { InitNames.Add("uptake_source"); //ensure it is an init } } for (i = 0; i < FInitList.Count - 1; i++) { if (FInitList[i] == "uptake_source") { buf.Append(" <" + FInitList[i] + ">apsim</" + FInitList[i] + ">\r\n"); } else { buf.Append(" <" + FInitList[i] + "></" + FInitList[i] + ">\r\n"); } } buf.Append(" </initdata>"); buf.Append("</component>"); strContext = buf.ToString(); } } modelConsts = model; }
/// <summary> /// Parses a <parameters> or <set> element in an XML parameter document /// </summary> /// <param name="Parser"></param> /// <param name="aNode"></param> /// <param name="Params"></param> /// <param name="bModify"></param> private void readParamNode(TXMLParser Parser, XmlNode aNode, ref TParameterSet Params, bool bModify) { XmlNode childNode; TParameterSet newParams; string sTag, sValues, sChildName, sLang, sDummy; try { Params.sName = Parser.getAttrValue(aNode, "name"); // Name and version information. The Params.sEnglishName = Params.sName; if (Params.bRootNode()) // version is passed to child sets Params.sVersion = Parser.getAttrValue(aNode, "version"); // during creation childNode = Parser.firstElementChild(aNode, "translate"); // See if tbere's a translation of the name matching our current language setting while (childNode != null) { sLang = Parser.getAttrValue(childNode, "lang"); sDummy = Parser.getText(childNode); Params.addTranslation(sLang, sDummy); childNode = Parser.nextElementSibling(childNode, "translate"); } if (!bModify) // If we are not modifying an existing while (Params.iChildCount() > 0) // parameter set, then clear any old Params.deleteChild(Params.iChildCount() - 1); // child parameter sets sValues = Parser.getAttrValue(aNode, "locales").Trim(); // Populate the locale list Params.setLocaleText(sValues); childNode = Parser.firstElementChild(aNode, "par"); // Parse the <par> elements while (childNode != null) { sTag = Parser.getAttrValue(childNode, "name"); sValues = Parser.getText(childNode); readParamValues(ref Params, sTag, sValues, bModify); childNode = Parser.nextElementSibling(childNode, "par"); } Params.deriveParams(); childNode = Parser.firstElementChild(aNode, "set"); // Create child parameter sets from the while (childNode != null) // <set> elements { if (!bModify) newParams = Params.addChild(); else { // If we are modifying an existing sChildName = Parser.getAttrValue(childNode, "name"); // parameter set, then locate the child newParams = Params.getChild(sChildName); // set that we are about to parse if (newParams == null) newParams = Params.addChild(); } readParamNode(Parser, childNode, ref newParams, bModify); childNode = Parser.nextElementSibling(childNode, "set"); } } catch (Exception e) { throw new Exception(e.Message); } }