From 8692d7fdb0e491d3741df1415ff71cc04dbdc534 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Wed, 27 Jul 2016 13:02:00 +0200
Subject: [PATCH] add the simulation mode to the validation context

certain validations are only done in declaration mode (e.g. gross vehicle weight)
---
 .../Simulation/Impl/SimulatorFactory.cs       |   2 +-
 .../Data/SimulationComponentData.cs           |   8 ++
 .../SimulationComponent/Data/VehicleData.cs   |   7 +-
 VectoCore/VectoCore/Utils/Validation.cs       |  24 +++-
 .../Models/SimulationComponent/GearboxTest.cs |   4 +-
 .../SimulationComponentData/ValidationTest.cs | 132 ++++++++++++++++--
 6 files changed, 161 insertions(+), 16 deletions(-)

diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
index 9e59a781d6..96478896ff 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs
@@ -151,7 +151,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 						throw new ArgumentOutOfRangeException("CycleType unknown:" + data.Cycle.CycleType);
 				}
 
-				var validationErrors = run.Validate();
+				var validationErrors = run.Validate(_mode);
 				if (validationErrors.Any()) {
 					throw new VectoException("Validation of Run-Data Failed: " +
 											"\n".Join(validationErrors.Select(r => r.ErrorMessage)));
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs
index a6dc7f1a4e..558791d936 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/SimulationComponentData.cs
@@ -29,8 +29,10 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
+using System.ComponentModel.DataAnnotations;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 {
@@ -50,5 +52,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 		public string DigestValue { get; internal set; }
 
 		public IntegrityStatus IntegrityStatus { get; internal set; }
+
+		protected static ExecutionMode GetExecutionMode(ValidationContext context)
+		{
+			var modeService = context.GetService(typeof(ExecutionMode)) as ExecutionModeServiceContainer;
+			return modeService == null ? ExecutionMode.Declaration : modeService.Mode;
+		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
index aca8f710a0..0e8d1b5829 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
@@ -140,6 +140,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 
 		public static ValidationResult ValidateVehicleData(VehicleData vehicleData, ValidationContext validationContext)
 		{
+			var mode = SimulationComponentData.GetExecutionMode(validationContext);
+
 			var weightShareSum = vehicleData.AxleData.Sum(axle => axle.AxleWeightShare);
 			if (!weightShareSum.IsEqual(1.0, 1E-10)) {
 				return new ValidationResult(
@@ -147,12 +149,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 						weightShareSum, 1 - weightShareSum));
 			}
 
+			if (mode != ExecutionMode.Declaration) {
+				return ValidationResult.Success;
+			}
+
 			if (vehicleData.TotalVehicleWeight() > vehicleData.GrossVehicleMassRating) {
 				return new ValidationResult(
 					string.Format("Total Vehicle Weight is greater than GrossVehicleMassRating! sum: {0},  GVM: {1}",
 						vehicleData.TotalVehicleWeight(), vehicleData.GrossVehicleMassRating));
 			}
-
 			return ValidationResult.Success;
 		}
 	}
diff --git a/VectoCore/VectoCore/Utils/Validation.cs b/VectoCore/VectoCore/Utils/Validation.cs
index ade2ded943..313f867036 100644
--- a/VectoCore/VectoCore/Utils/Validation.cs
+++ b/VectoCore/VectoCore/Utils/Validation.cs
@@ -36,6 +36,7 @@ using System.ComponentModel.DataAnnotations;
 using System.IO;
 using System.Linq;
 using System.Reflection;
+using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 
 namespace TUGraz.VectoCore.Utils
@@ -50,12 +51,14 @@ namespace TUGraz.VectoCore.Utils
 		/// </summary>
 		/// <typeparam name="T"></typeparam>
 		/// <param name="entity">The entity.</param>
+		/// <param name="mode">validate the entity for the given execution mode</param>
 		/// <returns>Null, if the validation was successfull. Otherwise a list of ValidationResults with the ErrorMessages.</returns>
-		public static IList<ValidationResult> Validate<T>(this T entity)
+		public static IList<ValidationResult> Validate<T>(this T entity, ExecutionMode mode)
 		{
 			var context = new ValidationContext(entity);
+			context.ServiceContainer.AddService(typeof(ExecutionMode), new ExecutionModeServiceContainer(mode));
 			var results = new List<ValidationResult>();
-			Validator.TryValidateObject(entity, new ValidationContext(entity), results, true);
+			Validator.TryValidateObject(entity, context, results, true);
 
 			const BindingFlags flags =
 				BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public |
@@ -129,6 +132,16 @@ namespace TUGraz.VectoCore.Utils
 		}
 	}
 
+	public class ExecutionModeServiceContainer
+	{
+		public ExecutionModeServiceContainer(ExecutionMode mode)
+		{
+			Mode = mode;
+		}
+
+		public ExecutionMode Mode { get; protected set; }
+	}
+
 	/// <summary>
 	/// Determines that the attributed object should be validated recursively.
 	/// </summary>
@@ -148,11 +161,14 @@ namespace TUGraz.VectoCore.Utils
 				return ValidationResult.Success;
 			}
 
+			var modeService = validationContext.GetService(typeof(ExecutionMode)) as ExecutionModeServiceContainer;
+			var mode = modeService != null ? modeService.Mode : ExecutionMode.Declaration;
+
 			var enumerable = value as IEnumerable;
 			if (enumerable != null) {
 				var i = 0;
 				foreach (var element in enumerable) {
-					var results = element.Validate();
+					var results = element.Validate(mode);
 					if (results.Any()) {
 						return new ValidationResult(
 							string.Format("{1}[{0}] in {1} invalid: {2}", i, validationContext.DisplayName,
@@ -161,7 +177,7 @@ namespace TUGraz.VectoCore.Utils
 					i++;
 				}
 			} else {
-				var results = value.Validate();
+				var results = value.Validate(mode);
 				if (!results.Any()) {
 					return ValidationResult.Success;
 				}
diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs
index 2daadd875d..7dadf10e48 100644
--- a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs
+++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs
@@ -136,7 +136,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var vehicle = new VehicleContainer(ExecutionMode.Engineering);
 			var axleGearData = MockSimulationDataFactory.CreateAxleGearDataFromFile(AxleGearValidRangeDataFile);
 			var axleGear = new AxleGear(vehicle, axleGearData);
-			Assert.AreEqual(0, axleGear.Validate().Count);
+			Assert.AreEqual(0, axleGear.Validate(ExecutionMode.Declaration).Count);
 		}
 
 		[TestCase]
@@ -145,7 +145,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var vehicle = new VehicleContainer(ExecutionMode.Engineering);
 			var axleGearData = MockSimulationDataFactory.CreateAxleGearDataFromFile(AxleGearInvalidRangeDataFile);
 			var axleGear = new AxleGear(vehicle, axleGearData);
-			var errors = axleGear.Validate();
+			var errors = axleGear.Validate(ExecutionMode.Declaration);
 			Assert.AreEqual(1, errors.Count);
 		}
 
diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs
index f87c11281f..2b7568cd89 100644
--- a/VectoCore/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs
+++ b/VectoCore/VectoCoreTest/Models/SimulationComponentData/ValidationTest.cs
@@ -29,6 +29,7 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
+using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Data;
 using System.Diagnostics.CodeAnalysis;
@@ -38,6 +39,7 @@ using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.InputData.Reader;
 using TUGraz.VectoCore.InputData.Reader.DataObjectAdaper;
+using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
@@ -53,7 +55,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 	[TestClass]
 	[SuppressMessage("ReSharper", "InconsistentNaming")]
 	[SuppressMessage("ReSharper", "UnusedMember.Local")]
-	public class CombustionEngineDataValidationTestClass
+	public class ValidationTestClass
 	{
 		/// <summary>
 		/// VECTO-107 Check valid range of input parameters
@@ -90,7 +92,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 			};
 			data.FullLoadCurve.EngineData = data;
 
-			var results = data.Validate();
+			var results = data.Validate(ExecutionMode.Declaration);
 			Assert.IsFalse(results.Any(), "Validation Failed: " + "; ".Join(results.Select(r => r.ErrorMessage)));
 			Assert.IsTrue(data.IsValid());
 		}
@@ -125,7 +127,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 
 			var engineData = dao.CreateEngineData(data);
 
-			var results = engineData.Validate();
+			var results = engineData.Validate(ExecutionMode.Declaration);
 			Assert.IsFalse(results.Any(), "Validation failed: " + "; ".Join(results.Select(r => r.ErrorMessage)));
 			Assert.IsTrue(engineData.IsValid());
 		}
@@ -164,11 +166,125 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 
 			var engineData = dao.CreateEngineData(data);
 
-			var results = engineData.Validate();
+			var results = engineData.Validate(ExecutionMode.Declaration);
 			Assert.IsFalse(results.Any(), "Validation failed: " + "; ".Join(results.Select(r => r.ErrorMessage)));
 			Assert.IsTrue(engineData.IsValid());
 		}
 
+		[TestMethod]
+		public void ValidationModeVehicleDataTest()
+		{
+			var vehicleData = new VehicleData() {
+				AxleConfiguration = AxleConfiguration.AxleConfig_4x2,
+				Creator = "Mr. Test",
+				CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection,
+				CrossWindCorrectionCurve =
+					new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(5.SI<SquareMeter>()),
+						CrossWindCorrectionMode.NoCorrection),
+				CurbWeight = 7500.SI<Kilogram>(),
+				DynamicTyreRadius = 0.5.SI<Meter>(),
+				CurbWeigthExtra = 0.SI<Kilogram>(),
+				Loading = 12000.SI<Kilogram>(),
+				GrossVehicleMassRating = 16000.SI<Kilogram>()
+			};
+			vehicleData.AxleData = new List<Axle>() {
+				new Axle() {
+					AxleType = AxleType.VehicleNonDriven,
+					AxleWeightShare = 0.4,
+					Inertia = 0.5.SI<KilogramSquareMeter>(),
+					RollResistanceCoefficient = 0.00555,
+					TyreTestLoad = 33000.SI<Newton>()
+				},
+				new Axle() {
+					AxleType = AxleType.VehicleNonDriven,
+					AxleWeightShare = 0.6,
+					Inertia = 0.5.SI<KilogramSquareMeter>(),
+					RollResistanceCoefficient = 0.00555,
+					TyreTestLoad = 33000.SI<Newton>()
+				},
+			};
+			var result = vehicleData.Validate(ExecutionMode.Engineering);
+			Assert.IsTrue(!result.Any());
+
+			result = vehicleData.Validate(ExecutionMode.Declaration);
+			Assert.IsTrue(result.Any(), "validation should have failed, but succeeded");
+		}
+
+		/// <summary>
+		/// VECTO-107 Check valid range of input parameters
+		/// </summary>
+		[TestMethod]
+		public void ValidationModeVectoRunDataTest()
+		{
+			var container = new VehicleContainer(ExecutionMode.Engineering);
+			var data = new DistanceRun(container);
+			var engineData = new CombustionEngineData
+			{
+				FullLoadCurve = EngineFullLoadCurve.ReadFromFile(@"TestData\Components\12t Delivery Truck.vfld"),
+				IdleSpeed = 560.RPMtoRad()
+			};
+
+			var gearboxData = new GearboxData();
+			gearboxData.Gears[1] = new GearData
+			{
+				LossMap = TransmissionLossMap.ReadFromFile(@"TestData\Components\Direct Gear.vtlm", 1, "1"),
+				Ratio = 1
+			};
+
+			var axleGearData = new AxleGearData
+			{
+				AxleGear = new GearData
+				{
+					Ratio = 1,
+					LossMap = TransmissionLossMap.ReadFromFile(@"TestData\Components\limited.vtlm", 1, "1"),
+				}
+			};
+			var vehicleData = new VehicleData()
+			{
+				AxleConfiguration = AxleConfiguration.AxleConfig_4x2,
+				Creator = "Mr. Test",
+				CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection,
+				CrossWindCorrectionCurve =
+					new CrosswindCorrectionCdxALookup(CrossWindCorrectionCurveReader.GetNoCorrectionCurve(5.SI<SquareMeter>()),
+						CrossWindCorrectionMode.NoCorrection),
+				CurbWeight = 7500.SI<Kilogram>(),
+				DynamicTyreRadius = 0.5.SI<Meter>(),
+				CurbWeigthExtra = 0.SI<Kilogram>(),
+				Loading = 12000.SI<Kilogram>(),
+				GrossVehicleMassRating = 16000.SI<Kilogram>()
+			};
+			vehicleData.AxleData = new List<Axle>() {
+				new Axle() {
+					AxleType = AxleType.VehicleNonDriven,
+					AxleWeightShare = 0.4,
+					Inertia = 0.5.SI<KilogramSquareMeter>(),
+					RollResistanceCoefficient = 0.00555,
+					TyreTestLoad = 33000.SI<Newton>()
+				},
+				new Axle() {
+					AxleType = AxleType.VehicleNonDriven,
+					AxleWeightShare = 0.6,
+					Inertia = 0.5.SI<KilogramSquareMeter>(),
+					RollResistanceCoefficient = 0.00555,
+					TyreTestLoad = 33000.SI<Newton>()
+				},
+			};
+
+			container.RunData = new VectoRunData
+			{
+				VehicleData = vehicleData,
+				GearboxData = gearboxData,
+				EngineData = engineData,
+				AxleGearData = axleGearData
+			};
+
+			var results = data.Validate(ExecutionMode.Declaration);
+			Assert.IsTrue(results.Any(), "Validation should have failed, but succeded.");
+
+			results = vehicleData.Validate(ExecutionMode.Engineering);
+			Assert.IsTrue(!results.Any());
+		}
+
 		/// <summary>
 		/// VECTO-107 Check valid range of input parameters
 		/// </summary>
@@ -201,7 +317,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 				AxleGearData = axleGearData
 			};
 
-			var results = data.Validate();
+			var results = data.Validate(ExecutionMode.Declaration);
 			Assert.IsTrue(results.Any(), "Validation should have failed, but succeded.");
 		}
 
@@ -211,7 +327,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 		[TestMethod]
 		public void Validation_Test()
 		{
-			var results = new DataObject().Validate();
+			var results = new DataObject().Validate(ExecutionMode.Declaration);
 
 			// every field and property should be tested except private parent fields and properties and 
 			// (4*4+1) * 2 = 17*2= 34 - 4 private parent fields (+2 public field and property which are tested twice) = 32
@@ -238,7 +354,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 					VectoCSVFile.ReadStream(
 						InputDataHelper.InputDataAsStream("engine torque,downshift rpm [rpm],upshift rpm [rpm]	", vgbs)));
 
-			var results = shiftPolygon.Validate();
+			var results = shiftPolygon.Validate(ExecutionMode.Declaration);
 			Assert.IsFalse(results.Any());
 
 			shiftPolygon =
@@ -246,7 +362,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 					VectoCSVFile.ReadStream(
 						InputDataHelper.InputDataAsStream("engine torque,upshift rpm [rpm], downshift rpm [rpm]	", vgbs)));
 
-			results = shiftPolygon.Validate();
+			results = shiftPolygon.Validate(ExecutionMode.Declaration);
 			Assert.IsTrue(results.Any());
 		}
 
-- 
GitLab