public void FileFormat_EnsureWriteReadRoundTripWorks() { // Create a simulations object with child model wrappers. ModelWrapper rootNode1 = new ModelWrapper(); ModelWrapper simulations = rootNode1.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); ModelWrapper zone = simulation.Add(new Zone()); // Write the above simulations object to an xml string. FileFormat fileFormat = new FileFormat(); string xml = fileFormat.WriteXML(rootNode1); // Read XML back in. ModelWrapper rootNode2 = fileFormat.ReadXML(xml); // Make sure the two root nodes are the same. Assert.IsTrue(rootNode2.Model is Simulations); Assert.AreEqual(rootNode2.Children.Count, 1); Assert.IsTrue((rootNode2.Children[0] as ModelWrapper).Model is Simulation); Assert.AreEqual((rootNode2.Children[0] as ModelWrapper).Children.Count, 2); }
public void TestGet() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); simulation.Add(new MockSummary()); ModelWrapper zone = simulation.Add(new Zone()); // Check that it is case sensitive. Assert.IsNull(models.Get("simulation.clock.StartDate")); // Fix case this should work. object d = models.Get("Simulation.Clock.StartDate"); DateTime startDate = (DateTime)d; Assert.AreEqual(startDate.Year, 2015); Assert.AreEqual(startDate.Month, 1); Assert.AreEqual(startDate.Day, 1); }
public void Scope_EnsureFindAllWorks() { ModelWithParentLink modelWithParentLink = new UnitTests.ModelWithParentLink(); // Create a simulation ModelWrapper simulation = new ModelWrapper(new Simulation()); simulation.Add(new Clock()); simulation.Add(new MockSummary()); simulation.Add(new Zone() { Name = "zone1" }); simulation.Add(new Zone() { Name = "zone2" }); simulation.Children[2].Add(new Soil()); // added to zone1 simulation.Children[2].Add(new Plant()); // added to zone1 simulation.Children[2].Children[1].Add(new Leaf() { Name = "leaf1" }); // added to plant1 simulation.Children[2].Children[1].Add(new GenericOrgan() { Name = "stem1" }); // added to plant1 simulation.Children[2].Add(new Plant()); // added to zone1 simulation.Children[2].Children[2].Add(new Leaf() { Name = "leaf2" }); // added to plant2 simulation.Children[2].Children[2].Add(new GenericOrgan() { Name = "stem2" }); // added to plant2 simulation.ParentAllModels(); // Ensure correct scoping from leaf1 (remember Plant is a scoping unit) List<IModel> inScopeOfLeaf1 = Apsim.FindAll(simulation.Children[2].Children[1].Children[0].Model as IModel); Assert.AreEqual(inScopeOfLeaf1.Count, 9); Assert.AreEqual(inScopeOfLeaf1[0].Name, "Plant"); Assert.AreEqual(inScopeOfLeaf1[1].Name, "leaf1"); Assert.AreEqual(inScopeOfLeaf1[2].Name, "stem1"); Assert.AreEqual(inScopeOfLeaf1[3].Name, "Soil"); Assert.AreEqual(inScopeOfLeaf1[4].Name, "Plant"); Assert.AreEqual(inScopeOfLeaf1[5].Name, "Clock"); Assert.AreEqual(inScopeOfLeaf1[6].Name, "zone1"); Assert.AreEqual(inScopeOfLeaf1[7].Name, "zone2"); Assert.AreEqual(inScopeOfLeaf1[8].Name, "Simulation"); // Ensure correct scoping from soil List<IModel> inScopeOfSoil = Apsim.FindAll(simulation.Children[2].Children[0].Model as IModel); Assert.AreEqual(inScopeOfSoil.Count, 11); Assert.AreEqual(inScopeOfSoil[0].Name, "zone1"); Assert.AreEqual(inScopeOfSoil[1].Name, "Soil"); Assert.AreEqual(inScopeOfSoil[2].Name, "Plant"); Assert.AreEqual(inScopeOfSoil[3].Name, "leaf1"); Assert.AreEqual(inScopeOfSoil[4].Name, "stem1"); Assert.AreEqual(inScopeOfSoil[5].Name, "Plant"); Assert.AreEqual(inScopeOfSoil[6].Name, "leaf2"); Assert.AreEqual(inScopeOfSoil[7].Name, "stem2"); Assert.AreEqual(inScopeOfSoil[8].Name, "Clock"); Assert.AreEqual(inScopeOfSoil[9].Name, "zone2"); Assert.AreEqual(inScopeOfSoil[10].Name, "Simulation"); }
public void Links_EnsureChildLinkByNameWorks() { ModelWithChildLinkByName modelWithChildLinkByName = new UnitTests.ModelWithChildLinkByName(); // Create a simulation ModelWrapper simulation = new ModelWrapper(new Simulation()); simulation.Add(new Clock()); simulation.Add(new MockSummary()); simulation.Add(modelWithChildLinkByName); simulation.Children[2].Add(new Zone() { Name = "zone1" }); // added to modelWithChildLink simulation.Children[2].Add(new Zone() { Name = "zone2" }); // added to modelWithChildLink Links linksAlgorithm = new Links(); linksAlgorithm.Resolve(simulation); // Should find zone2 as a match as it uses the fields name. Assert.AreEqual(modelWithChildLinkByName.zone2.Name, "zone2"); }
public void Links_EnsureChildLinkWorks() { ModelWithChildLink modelWithChildLink = new UnitTests.ModelWithChildLink(); // Create a simulation ModelWrapper simulation = new ModelWrapper(new Simulation()); simulation.Add(new Clock()); simulation.Add(new MockSummary()); simulation.Add(modelWithChildLink); simulation.Children[2].Add(new Zone() { Name = "zone1" }); // added to modelWithChildLink Links linksAlgorithm = new Links(); linksAlgorithm.Resolve(simulation); // Should find zone1 as a match i.e. not use the zones name when doing a match. Assert.AreEqual(modelWithChildLink.zone2.Name, "zone1"); // If we now add another child, resolve should fail as there are two matches. simulation.Children[2].Add(new Zone() { Name = "zone2" }); // added to modelWithChildLink Assert.Throws<Exception>(() => linksAlgorithm.Resolve(simulation) ); }
public void TestSet() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); simulation.Add(new MockSummary()); ModelWrapper zone = simulation.Add(new Zone()); // Fix case this should work. Assert.IsTrue(models.Set("Simulation.Clock.EndDate", new DateTime(2016, 1, 1))); Assert.AreEqual(clock.EndDate.Year, 2016); Assert.AreEqual(clock.EndDate.Month, 1); Assert.AreEqual(clock.EndDate.Day, 1); }
public void Link() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); MockSummary summary = new MockSummary(); simulation.Add(summary); simulation.Add(new Zone()); simulation.Add(new Zone()); ModelWithLinks links = new ModelWithLinks(); simulation.Add(links); Links.Resolve(simulations); Assert.AreEqual(links.zones.Length, 3); Assert.NotNull(links.zones[0]); Assert.NotNull(links.zones[1]); }
public void EnsureModelNodeLinksCorrectly() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); MockSummary summary = new MockSummary(); simulation.Add(summary); simulation.Add(new Zone()); simulation.Add(new Zone()); ModelWithModelNodeLink modelWithModelNode = new ModelWithModelNodeLink(); simulation.Add(modelWithModelNode); Links.Resolve(simulations); Assert.IsNotNull(modelWithModelNode.model); }
public void EnsureIFunctionLinksCorrectly() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); MockSummary summary = new MockSummary(); simulation.Add(summary); simulation.Add(new Zone()); simulation.Add(new Zone()); ModelWithIFunctions links = new ModelWithIFunctions(); simulation.Add(links); simulation.Add(new IFunctionProxy() { value = 1 }).Name = "model1"; simulation.Add(new IFunctionProxy() { value = 2 }).Name = "model2"; simulation.Add(new IFunctionProxy() { value = 3 }).Name = "model3"; Links.Resolve(simulations); Assert.AreEqual(links.model2.Value, 2); }
/// <summary> /// /// </summary> /// <param name="rootNode"></param> public static void Resolve(ModelWrapper rootNode) { List<ModelWrapper> allModels = rootNode.ChildrenRecursively; foreach (ModelWrapper modelNode in allModels) { List<ModelWrapper> modelsInScope = modelNode.FindModelsInScope(allModels); string errorMsg = string.Empty; // Go looking for [Link]s foreach (FieldInfo field in ReflectionUtilities.GetAllFields( modelNode.Model.GetType(), BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)) { var link = ReflectionUtilities.GetAttribute(field, typeof(LinkAttribute), false) as LinkAttribute; if (link != null) { object linkedObject = null; if (field.FieldType == typeof(ModelWrapper)) linkedObject = modelNode; else if (field.FieldType == typeof(Property)) { PropertyInfo associatedProperty = modelNode.Model.GetType().GetProperty(link.AssociatedProperty); if (associatedProperty == null) throw new Exception("Cannot find the associated property: " + link.AssociatedProperty); linkedObject = rootNode.GetProperty(associatedProperty.GetValue(modelNode.Model, null).ToString()); if (linkedObject == null) throw new Exception("Cannot find the value of associated property: " + link.AssociatedProperty); } else { Type type = field.FieldType; if (type.IsArray) type = type.GetElementType(); List<ModelWrapper> allMatches; if (type.Name == "IFunction") allMatches = modelsInScope.FindAll(m => type.IsAssignableFrom(m.Model.GetType()) && m.Name.Equals(field.Name, StringComparison.InvariantCultureIgnoreCase)); else allMatches = modelsInScope.FindAll(m => type.IsAssignableFrom(m.Model.GetType())); if (field.FieldType.IsArray) { Array array = Array.CreateInstance(type, allMatches.Count); for (int i = 0; i < allMatches.Count; i++) array.SetValue(allMatches[i].Model, i); linkedObject = array; } else if (allMatches.Count == 1) linkedObject = allMatches[0].Model; else { // more that one match so use name to match foreach (ModelWrapper matchingModel in allMatches) { if (matchingModel.Name == field.Name) { linkedObject = matchingModel.Model; break; } } // If the link isn't optional then choose the closest match. if (linkedObject == null && !link.IsOptional && allMatches.Count > 1) { // Return the first (closest) match. linkedObject = allMatches[0].Model; } if ((linkedObject == null) && (!link.IsOptional)) errorMsg = string.Format(": Found {0} matches for {1} {2} !", allMatches.Count, field.FieldType.FullName, field.Name); } } if (linkedObject != null) field.SetValue(modelNode.Model, linkedObject); else if (!link.IsOptional) throw new Exception("Cannot resolve [Link] '" + field.ToString() + errorMsg); } } } }
/// <summary>Convert the specified model to XML</summary> /// <param name="rootNode">The root model to serialise.</param> /// <returns>The XML</returns> public string WriteXML(ModelWrapper rootNode) { StringWriter s = new StringWriter(); APSIMFileWriter writer = new APSIMFileWriter(s); writer.Formatting = Formatting.Indented; XmlUtilities.SerialiseWithOptions(rootNode, false, null, null, writer); return s.ToString(); }
public void Links_EnsureScopedLinkWorks() { ModelWithScopedLink modelWithScopedLink = new UnitTests.ModelWithScopedLink(); // Create a simulation ModelWrapper simulation = new ModelWrapper(new Simulation()); simulation.Add(new Clock()); simulation.Add(new MockSummary()); simulation.Add(new Zone() { Name = "zone1" }); simulation.Add(new Zone() { Name = "zone2" }); simulation.Children[1].Add(modelWithScopedLink); // added to zone1 Links linksAlgorithm = new Links(); linksAlgorithm.Resolve(simulation); // Should find the closest match. Assert.AreEqual(modelWithScopedLink.zone2.Name, "zone1"); }
/// <summary> /// /// </summary> /// <param name="rootNode"></param> public void Resolve(ModelWrapper rootNode) { allModels = rootNode.ChildrenRecursively; foreach (ModelWrapper modelNode in allModels) ResolveInternal(modelNode); }
/// <summary>A method for adding a model.</summary> public ModelWrapper Add(object model) { if (Model == null) { Model = model; Name = model.GetType().Name; depth = 1; return this; } else { ModelWrapper child = new ModelWrapper(model) { Name = model.GetType().Name }; child.depth = depth + 1; Children.Add(child); return child; } }
public void EnsureDynamicPropertyLinksCorrectly() { // Create a tree with a root node for our models. ModelWrapper models = new ModelWrapper(); // Create some models. ModelWrapper simulations = models.Add(new Simulations()); ModelWrapper simulation = simulations.Add(new Simulation()); Clock clock = new Clock(); clock.StartDate = new DateTime(2015, 1, 1); clock.EndDate = new DateTime(2015, 12, 31); simulation.Add(clock); MockSummary summary = new MockSummary(); simulation.Add(summary); simulation.Add(new Zone()); simulation.Add(new Zone()); ModelWithDynamicProperty modelWithDynamicProperty = new ModelWithDynamicProperty(); modelWithDynamicProperty.xname = "Clock.StartDate"; simulation.Add(modelWithDynamicProperty); Links.Resolve(simulation); Assert.IsNotNull(modelWithDynamicProperty); Assert.AreEqual(modelWithDynamicProperty.x.Get(), clock.StartDate); }
/// <summary>Constructor</summary> /// <param name="model">A ModelNode starting node</param> internal Property(ModelWrapper model) { this.model = model; }
/// <summary>A method for adding a model.</summary> public ModelWrapper Add(object model) { if (Model == null) { Model = model; Name = model.GetType().Name; depth = 1; return this; } else { string name; if (model is IModel) name = (model as IModel).Name; else name = model.GetType().Name; ModelWrapper child = new ModelWrapper(model, name ); child.depth = depth + 1; Children.Add(child); return child; } }