don't reinvent the wheel; move attribute validation logic from Oms to AttributeImplementation

This commit is contained in:
Michael Becker 2025-10-26 09:43:38 -04:00
parent 3a96529a21
commit 0e40deb35b
7 changed files with 70 additions and 86 deletions

View File

@ -30,10 +30,13 @@ public abstract class AttributeImplementation<T> : AttributeImplementation
} }
return defaultValue; return defaultValue;
} }
protected override IEnumerable<Type>? ValidDataTypes => [ typeof(T) ];
} }
public abstract class AttributeImplementation : ClassImplementation public abstract class AttributeImplementation : ClassImplementation
{ {
protected virtual IEnumerable<Type>? ValidDataTypes { get; }
protected abstract object? ConvertFromInternal(Oms oms, object? value); protected abstract object? ConvertFromInternal(Oms oms, object? value);
public object? ReadDerivedData(BinaryReader br) public object? ReadDerivedData(BinaryReader br)
@ -53,9 +56,19 @@ public abstract class AttributeImplementation : ClassImplementation
ExecuteBuildElementInternal(oms, targetInstance, elementContent, elementContentInstance, objCell); ExecuteBuildElementInternal(oms, targetInstance, elementContent, elementContentInstance, objCell);
} }
protected abstract bool IsValidValueInternal(object value); protected virtual void ValidateInternal(Oms oms, InstanceHandle attributeInstance, object value)
public bool IsValidValue(object value)
{ {
return IsValidValueInternal(value); // do nothing by default
}
public void Validate(Oms oms, InstanceHandle attributeInstance, object value)
{
if (ValidDataTypes != null)
{
if (value != null && !ValidDataTypes.Contains(value.GetType()))
{
throw new ArgumentException(String.Format("value {0} cannot be converted to attribute type `{1}`", value is string ? "\"" + value.ToString() + "\"" : value, oms.GetInstanceText(attributeInstance)));
}
}
ValidateInternal(oms, attributeInstance, value);
} }
} }

View File

@ -54,9 +54,4 @@ public class BooleanAttributeImplementation : AttributeImplementation<bool>
objCell.Add("value", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance)); objCell.Add("value", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance));
objCell.Add("text", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance) ? "Yes" : "No"); objCell.Add("text", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance) ? "Yes" : "No");
} }
protected override bool IsValidValueInternal(object value)
{
return value is bool;
}
} }

View File

@ -61,9 +61,4 @@ public class DateAttributeImplementation : AttributeImplementation<DateTime>
objCell.Add("text", dt.ToString()); objCell.Add("text", dt.ToString());
objCell.Add("dateTimePrecision", "DAY"); objCell.Add("dateTimePrecision", "DAY");
} }
protected override bool IsValidValueInternal(object value)
{
return value is DateTime;
}
} }

View File

@ -55,9 +55,21 @@ public class NumericAttributeImplementation : AttributeImplementation<decimal>
objCell.Add("precision", 6); objCell.Add("precision", 6);
objCell.Add("format", "#0.######"); objCell.Add("format", "#0.######");
} }
protected override void ValidateInternal(Oms oms, InstanceHandle attributeInstance, object value)
protected override bool IsValidValueInternal(object value)
{ {
return value is decimal; if (oms.TryGetAttributeValue(attributeInstance, oms.GetInstance(KnownAttributeGuids.Numeric.MinimumValue), out decimal minimumValue))
{
if (((decimal)value) < minimumValue)
{
throw new ArgumentOutOfRangeException(String.Format("value for NumericAttribute must be greater than {0}", minimumValue - 1));
}
}
if (oms.TryGetAttributeValue(attributeInstance, oms.GetInstance(KnownAttributeGuids.Numeric.MaximumValue), out decimal maximumValue))
{
if (((decimal)value) > maximumValue)
{
throw new ArgumentOutOfRangeException(String.Format("value for NumericAttribute must be greater than {0}", maximumValue - 1));
}
}
} }
} }

View File

@ -78,8 +78,25 @@ public class TextAttributeImplementation : AttributeImplementation<string>
} }
} }
protected override bool IsValidValueInternal(object value) protected override void ValidateInternal(Oms oms, InstanceHandle attributeInstance, object value)
{ {
return value is string; if (!(value is string))
{
throw new ArgumentException("value for TextAttribute must be System.String");
}
if (oms.TryGetAttributeValue(attributeInstance, oms.GetInstance(KnownAttributeGuids.Numeric.MinimumLength), out decimal minimumLength))
{
if (((string)value).Length < minimumLength)
{
throw new ArgumentOutOfRangeException(String.Format("value for TextAttribute must be greater than {0} characters", minimumLength - 1));
}
}
if (oms.TryGetAttributeValue(attributeInstance, oms.GetInstance(KnownAttributeGuids.Numeric.MaximumLength), out decimal maximumLength))
{
if (((string)value).Length > maximumLength)
{
throw new ArgumentOutOfRangeException(String.Format("value for TextAttribute must be less than {0} characters", maximumLength + 1));
}
}
} }
} }

View File

@ -908,7 +908,11 @@ public abstract class Oms
} }
} }
private void ValidateConstraintsForAttribute(InstanceHandle source, InstanceHandle attribute, object value) public void ValidateConstraintsForAttribute(InstanceHandle attribute, object value)
{
ValidateConstraintsForAttribute(InstanceHandle.Empty, attribute, value);
}
public void ValidateConstraintsForAttribute(InstanceHandle source, InstanceHandle attribute, object value)
{ {
if (!ValidateConstraints) if (!ValidateConstraints)
return; return;
@ -924,11 +928,10 @@ public abstract class Oms
InstanceHandle a_NumericAttribute = GetInstance(KnownInstanceGuids.Classes.NumericAttribute); InstanceHandle a_NumericAttribute = GetInstance(KnownInstanceGuids.Classes.NumericAttribute);
InstanceHandle a_DateAttribute = GetInstance(KnownInstanceGuids.Classes.DateAttribute); InstanceHandle a_DateAttribute = GetInstance(KnownInstanceGuids.Classes.DateAttribute);
InstanceHandle sourceParentClass = GetParentClass(source);
bool Verify_Classes_Contain_Attributes = false; bool Verify_Classes_Contain_Attributes = false;
if (Verify_Classes_Contain_Attributes) if (Verify_Classes_Contain_Attributes && source != InstanceHandle.Empty)
{ {
InstanceHandle sourceParentClass = GetParentClass(source);
if (!RecursiveClassHasAttribute(sourceParentClass, attribute)) if (!RecursiveClassHasAttribute(sourceParentClass, attribute))
{ {
string name = GetAttributeValue<string>(attribute, GetInstance(KnownAttributeGuids.Text.Name)); string name = GetAttributeValue<string>(attribute, GetInstance(KnownAttributeGuids.Text.Name));
@ -937,53 +940,14 @@ public abstract class Oms
} }
} }
if (IsInstanceOf(attribute, a_TextAttribute)) Guid parentClassGuid = GetGlobalIdentifier(GetParentClass(attribute));
IEnumerable<AttributeImplementation> attrs = ClassImplementations.GetAll<AttributeImplementation>();
foreach (AttributeImplementation impl in attrs)
{ {
if (!(value is string)) if (impl.ClassGuid == parentClassGuid)
{ {
throw new ArgumentException("value for TextAttribute must be System.String"); impl.Validate(this, attribute, value);
} // throw new ArgumentException(String.Format("value {0} cannot be converted to a `{1}`", value is string ? "\"" + value + "\"" : value, Oms.GetInstanceText(Oms.GetParentClass(parm))), nameof(value));
if (TryGetAttributeValue(attribute, GetInstance(KnownAttributeGuids.Numeric.MinimumLength), out decimal minimumLength))
{
if (((string)value).Length < minimumLength)
{
throw new ArgumentOutOfRangeException(String.Format("value for TextAttribute must be greater than {0} characters", minimumLength - 1));
}
}
if (TryGetAttributeValue(attribute, GetInstance(KnownAttributeGuids.Numeric.MaximumLength), out decimal maximumLength))
{
if (((string)value).Length > maximumLength)
{
throw new ArgumentOutOfRangeException(String.Format("value for TextAttribute must be less than {0} characters", maximumLength + 1));
}
}
}
else if (IsInstanceOf(attribute, a_BooleanAttribute))
{
if (!(value is bool))
{
throw new ArgumentException("value for BooleanAttribute must be System.Boolean");
}
}
else if (IsInstanceOf(attribute, a_NumericAttribute))
{
if (!(value is decimal))
{
throw new ArgumentException("value for NumericAttribute must be System.Decimal");
}
if (TryGetAttributeValue(attribute, GetInstance(KnownAttributeGuids.Numeric.MinimumValue), out decimal minimumValue))
{
if (((decimal)value) < minimumValue)
{
throw new ArgumentOutOfRangeException(String.Format("value for NumericAttribute must be greater than {0}", minimumValue - 1));
}
}
if (TryGetAttributeValue(attribute, GetInstance(KnownAttributeGuids.Numeric.MaximumValue), out decimal maximumValue))
{
if (((decimal)value) > maximumValue)
{
throw new ArgumentOutOfRangeException(String.Format("value for NumericAttribute must be greater than {0}", maximumValue - 1));
}
} }
} }
} }

View File

@ -190,18 +190,6 @@ public class OmsContext
} }
} }
} }
private void ValidateAttributeConstraints(InstanceHandle parm, object value)
{
Guid parentClassGuid = Oms.GetGlobalIdentifier(Oms.GetParentClass(parm));
IEnumerable<AttributeImplementation> attrs = Oms.ClassImplementations.GetAll<AttributeImplementation>();
foreach (AttributeImplementation impl in attrs)
{
if (impl.ClassGuid == parentClassGuid && !impl.IsValidValue(value))
{
throw new ArgumentException(String.Format("value {0} cannot be converted to a `{1}`", value is string ? "\"" + value + "\"" : value, Oms.GetInstanceText(Oms.GetParentClass(parm))), nameof(value));
}
}
}
public void SetWorkData(IInstanceReference parm, object? value) public void SetWorkData(IInstanceReference parm, object? value)
{ {
@ -236,7 +224,7 @@ public class OmsContext
} }
else else
{ {
ValidateAttributeConstraints(parm, value); Oms.ValidateConstraintsForAttribute(parm, value);
} }
} }
_WorkData[parm] = value; _WorkData[parm] = value;