git_bsmd/nsw/Source/bsmd.database/ValidationCondition.cs
Daniel Schick f9d5c4f6e3 Build 3.7.1:
Weiteres Vorgehen bei der Validierung (Bearbeitungsdialog angefangen (ex dashface))
Speicherung der Validierungsregeln usw.
2017-09-19 07:52:58 +00:00

307 lines
10 KiB
C#

// Copyright (c) 2015-2017 schick Informatik
// Description: Validierungsbedingung, die (als Gruppe) als Validierungsregel serialisiert und
// ausgewertet wird
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using log4net;
namespace bsmd.database
{
public class ValidationCondition : ICloneable
{
private static ILog log = LogManager.GetLogger(typeof(ValidationCondition));
public ValidationCondition() { }
public enum ConditionOperatorEnum
{
EQUAL,
NOT_EQUAL,
GREATER,
LESS
}
#region Properties
public string FieldName { get; set; }
public ConditionOperatorEnum ConditionOperator { get; set; }
public string Value { get; set; }
public string ErrorMessage { get; set; }
#endregion
#region static methods
public static bool? CheckConditions(MessageCore core, List<Message> messages, ConditionGroup cGroup, out string message)
{
bool? result = null;
message = "";
bool conditionResult = false;
try
{
foreach (ValidationCondition condition in cGroup.Conditions)
{
object[] otherargs = null;
// switch case type
string errorMessage = condition.ErrorMessage;
if (otherargs != null)
errorMessage = string.Format(errorMessage, otherargs);
result = ValidationCondition.CombineConditions(result, conditionResult, cGroup.GroupOperator);
// Fehlermeldung hinzufügen falls Bedingung verletzt wurde
if (!conditionResult && ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.AND) || (cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.OR)))
message += string.Format("- {0}{1}", errorMessage, Environment.NewLine);
//if (conditionResult && ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.NAND) || (cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.NOR)))
// message += string.Format("- {0}{1}", errorMessage, Environment.NewLine);
}
// check internal groups recursively
foreach (ConditionGroup subGroup in cGroup.SubGroups)
{
string subMessage = "";
bool? subResult = ValidationCondition.CheckConditions(core, messages, subGroup, out subMessage);
if (!subResult.HasValue) // an error occurred evaluating this element
{
return subResult;
}
else
{
result = ValidationCondition.CombineConditions(result, subResult.Value, cGroup.GroupOperator);
// Fehlermeldung hinzufügen falls Bedingung verletzt wurde
if (!subResult.Value && ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.AND) || (cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.OR)))
message += string.Format("- {0}{1}", subMessage, Environment.NewLine);
//if (subResult.Value && ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.NAND) || (cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.NOR)))
// message += string.Format("- {0}{1}", subMessage, Environment.NewLine);
}
}
// falls in einer "OR" Gruppe eine Bedingung fehlschlägt aber die Condition nach true evaluiert
// wird die Fehlermeldung zwecks Verwirrungsvermeidung gedroppt. Dasselbe natürl. auch für NAND
if ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.OR) && result.Value) message = "";
//if ((cGroup.GroupOperator == ConditionGroup.GroupOperatorEnum.NAND) && !result.Value) message = "";
}
catch (Exception ex)
{
message = string.Format("Validation threw exception: {0}", ex.ToString());
log.Error(message);
return false;
}
return result;
}
public static ConditionGroup LoadFromString(string serializedConditions)
{
if ((serializedConditions == null) ||
(serializedConditions.Trim().Length == 0))
return null;
using (StringReader sr = new StringReader(serializedConditions))
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(ConditionGroup));
ConditionGroup container = serializer.Deserialize(sr) as ConditionGroup;
return container;
}
catch (Exception)
{
return null;
}
}
}
public static string SaveToString(ConditionGroup group)
{
if (group == null) return null;
using (StringWriter sw = new StringWriter())
{
try
{
Type theType = Type.GetType("bsmd.database.ConditionGroup, bsmd.database");
XmlSerializer serializer = new XmlSerializer(theType);
serializer.Serialize(sw, group);
return sw.ToString();
}
catch (Exception)
{
return null;
}
}
}
/// <summary>
/// evaluate logical group operator
/// </summary>
private static bool CombineConditions(bool? c1, bool c2, ConditionGroup.GroupOperatorEnum op)
{
if (!c1.HasValue) return c2;
switch (op)
{
case ConditionGroup.GroupOperatorEnum.AND:
return c1.Value & c2;
case ConditionGroup.GroupOperatorEnum.OR:
return c1.Value | c2;
case ConditionGroup.GroupOperatorEnum.NOT:
return !(c1.Value);
case ConditionGroup.GroupOperatorEnum.XOR:
return (c1.Value ^ c2);
}
return false;
}
private static bool IsConditionTrue(string val1, string val2, ValidationCondition.ConditionOperatorEnum condition)
{
switch (condition)
{
case ValidationCondition.ConditionOperatorEnum.EQUAL:
return val1.Equals(val2);
default:
return !val1.Equals(val2);
}
}
private static bool IsConditionTrue(bool val1, bool val2, ValidationCondition.ConditionOperatorEnum condition)
{
switch (condition)
{
case ValidationCondition.ConditionOperatorEnum.EQUAL:
return val1.Equals(val2);
default:
return !val1.Equals(val2);
}
}
private static bool IsConditionTrue(DateTime val1, DateTime val2, ValidationCondition.ConditionOperatorEnum condition)
{
switch (condition)
{
case ValidationCondition.ConditionOperatorEnum.EQUAL:
return val1 == val2;
case ValidationCondition.ConditionOperatorEnum.GREATER:
return val1 > val2;
case ValidationCondition.ConditionOperatorEnum.LESS:
return val1 < val2;
case ValidationCondition.ConditionOperatorEnum.NOT_EQUAL:
return val1 != val2;
}
return true;
}
private static bool IsConditionTrue(TimeSpan val1, TimeSpan val2, ValidationCondition.ConditionOperatorEnum condition)
{
switch (condition)
{
case ValidationCondition.ConditionOperatorEnum.EQUAL:
return val1 == val2;
case ValidationCondition.ConditionOperatorEnum.GREATER:
return val1 > val2;
case ValidationCondition.ConditionOperatorEnum.LESS:
return val1 < val2;
case ValidationCondition.ConditionOperatorEnum.NOT_EQUAL:
return val1 != val2;
}
return true;
}
private static bool IsConditionTrue(double val1, double val2, ValidationCondition.ConditionOperatorEnum condition)
{
switch (condition)
{
case ValidationCondition.ConditionOperatorEnum.EQUAL:
return val1 == val2;
case ValidationCondition.ConditionOperatorEnum.GREATER:
return val1 > val2;
case ValidationCondition.ConditionOperatorEnum.LESS:
return val1 < val2;
case ValidationCondition.ConditionOperatorEnum.NOT_EQUAL:
return val1 != val2;
}
return true;
}
#endregion
#region ICloneable implementation
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
#region class ConditionGroup
[Serializable]
public class ConditionGroup
{
public enum GroupOperatorEnum
{
AND,
OR,
NOT,
XOR
}
public ConditionGroup() { }
public List<ValidationCondition> Conditions
{
get;
set;
}
public GroupOperatorEnum GroupOperator
{
get;
set;
}
public List<ConditionGroup> SubGroups
{
get;
set;
}
}
#endregion
#region struct KeyValuePairS
[Serializable]
[XmlType(TypeName = "schickKeyValuePair")]
public struct KeyValuePairS<K, V>
{
public K Key { get; set; }
public V Value { get; set; }
}
#endregion
}