Weiteres Vorgehen bei der Validierung (Bearbeitungsdialog angefangen (ex dashface)) Speicherung der Validierungsregeln usw.
307 lines
10 KiB
C#
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
|
|
|
|
}
|