improve strongly typed validations for Work Set and other Work Data
This commit is contained in:
parent
79d86a933c
commit
3a96529a21
@ -1 +1 @@
|
||||
Subproject commit 8bea362b3ca08a642ba196b8670e8e44e5e799e3
|
||||
Subproject commit 8638fc4c3a77de9b6fad3a9a17911995300e71c3
|
||||
@ -52,4 +52,10 @@ public abstract class AttributeImplementation : ClassImplementation
|
||||
{
|
||||
ExecuteBuildElementInternal(oms, targetInstance, elementContent, elementContentInstance, objCell);
|
||||
}
|
||||
|
||||
protected abstract bool IsValidValueInternal(object value);
|
||||
public bool IsValidValue(object value)
|
||||
{
|
||||
return IsValidValueInternal(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,4 +54,9 @@ public class BooleanAttributeImplementation : AttributeImplementation<bool>
|
||||
objCell.Add("value", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance));
|
||||
objCell.Add("text", oms.GetAttributeValue<bool>(targetInstance, elementContentInstance) ? "Yes" : "No");
|
||||
}
|
||||
|
||||
protected override bool IsValidValueInternal(object value)
|
||||
{
|
||||
return value is bool;
|
||||
}
|
||||
}
|
||||
@ -61,4 +61,9 @@ public class DateAttributeImplementation : AttributeImplementation<DateTime>
|
||||
objCell.Add("text", dt.ToString());
|
||||
objCell.Add("dateTimePrecision", "DAY");
|
||||
}
|
||||
|
||||
protected override bool IsValidValueInternal(object value)
|
||||
{
|
||||
return value is DateTime;
|
||||
}
|
||||
}
|
||||
@ -55,4 +55,9 @@ public class NumericAttributeImplementation : AttributeImplementation<decimal>
|
||||
objCell.Add("precision", 6);
|
||||
objCell.Add("format", "#0.######");
|
||||
}
|
||||
|
||||
protected override bool IsValidValueInternal(object value)
|
||||
{
|
||||
return value is decimal;
|
||||
}
|
||||
}
|
||||
@ -77,4 +77,9 @@ public class TextAttributeImplementation : AttributeImplementation<string>
|
||||
objCell.Add("value", oms.GetAttributeValue<string>(targetInstance, elementContentInstance));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool IsValidValueInternal(object value)
|
||||
{
|
||||
return value is string;
|
||||
}
|
||||
}
|
||||
@ -68,4 +68,17 @@ public class ClassImplementationRegistry
|
||||
implementation = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll<T>() where T : ClassImplementation
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
foreach (KeyValuePair<Guid, ClassImplementation> kvp in implementations)
|
||||
{
|
||||
if (kvp.Value is T)
|
||||
{
|
||||
list.Add((T)kvp.Value);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@ -66,6 +66,7 @@ namespace Mocha.Core
|
||||
public static Guid ValidateOnlyOnSubmit { get; } = new Guid("{400fcd8e-823b-4f4a-aa38-b444f763259b}");
|
||||
public static Guid UserIsLoggedIn { get; } = new Guid("{8e93d9f3-a897-4c97-935c-b3427f90633b}");
|
||||
public static Guid Derived { get; } = new Guid("{66991ca1-ef08-4f30-846c-4984c2a3139d}");
|
||||
public static Guid IncludeSubclasses { get; } = new Guid("{bc95f90e-d373-48be-b71e-283695afed5a}");
|
||||
}
|
||||
public static class Numeric
|
||||
{
|
||||
@ -87,5 +88,9 @@ namespace Mocha.Core
|
||||
|
||||
public static Guid SecondaryOperandValue { get; } = new Guid("{253a04bb-feb7-474d-b608-43219a753ef8}"); // {e666aa75-6b53-47ea-9afa-369378e17b5d}
|
||||
}
|
||||
public static class Date
|
||||
{
|
||||
public static Guid DateAndTime { get; } = new Guid("{ea71cc92-a5e9-49c1-b487-8ad178b557d2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,6 +137,72 @@ public class OmsContext
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void ValidateSubclassConstraints(InstanceHandle parm, System.Collections.IEnumerable en)
|
||||
{
|
||||
bool singular = false;
|
||||
if (!Oms.TryGetAttributeValue<bool>(parm, Oms.GetInstance(KnownAttributeGuids.Boolean.Singular), out singular))
|
||||
{
|
||||
singular = false;
|
||||
}
|
||||
bool includeSubclasses = false;
|
||||
if (!Oms.TryGetAttributeValue<bool>(parm, Oms.GetInstance(KnownAttributeGuids.Boolean.IncludeSubclasses), out includeSubclasses))
|
||||
{
|
||||
includeSubclasses = false;
|
||||
}
|
||||
|
||||
int ct = 0;
|
||||
foreach (object o in en)
|
||||
{
|
||||
ct++;
|
||||
}
|
||||
|
||||
if (singular && ct > 1)
|
||||
{
|
||||
throw new InvalidOperationException("cannot assign multiple instances to a singular Work Set");
|
||||
}
|
||||
|
||||
foreach (object o in en)
|
||||
{
|
||||
if (o is IInstanceReference ir)
|
||||
{
|
||||
IReadOnlyCollection<InstanceHandle> irs = Oms.GetRelatedInstances(parm, Oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
|
||||
if (irs.Count > 0)
|
||||
{
|
||||
if (includeSubclasses)
|
||||
{
|
||||
foreach (InstanceHandle possibleParentClass in irs)
|
||||
{
|
||||
if (!Oms.IsInstanceOf(ir, possibleParentClass))
|
||||
{
|
||||
throw new ArgumentException("instance reference must be an instance of appropriate class");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InstanceHandle parentClass = Oms.GetParentClass(ir);
|
||||
if (!irs.Contains(parentClass))
|
||||
{
|
||||
throw new ArgumentException("instance reference must be an instance of appropriate class");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
SetWorkData(parm.GetHandle(), value);
|
||||
@ -147,75 +213,31 @@ public class OmsContext
|
||||
{
|
||||
if (Oms.IsInstanceOf(parm, Oms.GetInstance(KnownInstanceGuids.Classes.WorkSet)))
|
||||
{
|
||||
bool singular = false;
|
||||
if (!Oms.TryGetAttributeValue<bool>(parm, Oms.GetInstance(KnownAttributeGuids.Boolean.Singular), out singular))
|
||||
{
|
||||
singular = false;
|
||||
}
|
||||
|
||||
if (value is IInstanceReference)
|
||||
{
|
||||
IReadOnlyCollection<InstanceHandle> irs = Oms.GetRelatedInstances(parm, Oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
|
||||
if (irs.Count > 0)
|
||||
{
|
||||
InstanceHandle ir = ((IInstanceReference)value).GetHandle();
|
||||
InstanceHandle parentClass = Oms.GetParentClass(ir);
|
||||
if (!irs.Contains(parentClass))
|
||||
{
|
||||
throw new ArgumentException("instance reference must be an instance of appropriate class");
|
||||
}
|
||||
}
|
||||
ValidateSubclassConstraints(parm, new IInstanceReference[] { (IInstanceReference)value });
|
||||
}
|
||||
else if (value is IEnumerable<InstanceHandle>)
|
||||
{
|
||||
IEnumerable<InstanceHandle> insts = (IEnumerable<InstanceHandle>)value;
|
||||
if (singular && insts.Count() > 1)
|
||||
{
|
||||
throw new InvalidOperationException("Singular Work Set must only contain a single InstanceReference or be an array of InstanceReference that contains exactly zero or one item.");
|
||||
}
|
||||
IEnumerable<InstanceHandle> irs = Oms.GetRelatedInstances(parm, Oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
|
||||
if (irs.Count() > 0)
|
||||
{
|
||||
foreach (InstanceHandle ir in insts)
|
||||
{
|
||||
InstanceHandle parentClass = Oms.GetParentClass(ir);
|
||||
if (!irs.Contains(parentClass))
|
||||
{
|
||||
throw new ArgumentException("instance reference must be an instance of appropriate class");
|
||||
}
|
||||
}
|
||||
}
|
||||
// value = ((IEnumerable<InstanceHandle>)value).FirstOrDefault();
|
||||
ValidateSubclassConstraints(parm, (IEnumerable<InstanceHandle>)value);
|
||||
}
|
||||
else if (value is IEnumerable<InstanceWrapper>)
|
||||
{
|
||||
IEnumerable<InstanceWrapper> insts = (IEnumerable<InstanceWrapper>)value;
|
||||
if (singular && insts.Count() > 1)
|
||||
{
|
||||
throw new InvalidOperationException("Singular Work Set must only contain a single InstanceReference or be an array of InstanceReference that contains exactly zero or one item.");
|
||||
}
|
||||
IEnumerable<InstanceHandle> irs = Oms.GetRelatedInstances(parm, Oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
|
||||
if (irs != null)
|
||||
{
|
||||
if (irs.Count() > 0)
|
||||
{
|
||||
foreach (InstanceWrapper iw in insts)
|
||||
{
|
||||
InstanceHandle ir = iw.GetHandle();
|
||||
InstanceHandle parentClass = Oms.GetParentClass(ir);
|
||||
if (!irs.Contains(parentClass))
|
||||
{
|
||||
throw new ArgumentException("instance reference must be an instance of appropriate class");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ValidateSubclassConstraints(parm, (IEnumerable<InstanceWrapper>)value);
|
||||
}
|
||||
else if (value is IEnumerable<IInstanceReference>)
|
||||
{
|
||||
ValidateSubclassConstraints(parm, (IEnumerable<IInstanceReference>)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(String.Format("cannot assign literal data '{0}' to a Work Set", value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidateAttributeConstraints(parm, value);
|
||||
}
|
||||
}
|
||||
_WorkData[parm] = value;
|
||||
}
|
||||
|
||||
@ -59,6 +59,28 @@ public class WorkSetTests : OmsTestsBase
|
||||
}, Throws.ArgumentException);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingleValidClassConstraintWithInheritance()
|
||||
{
|
||||
// we should be able to put a `Text Attribute` instance into this Work Set if its valid class is `Attribute`
|
||||
InstanceHandle c_Attribute = Oms.GetInstance(KnownInstanceGuids.Classes.Attribute);
|
||||
InstanceHandle c_TextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
|
||||
|
||||
WorkSet workSet = Oms.CreateWorkSet("Dummy Work Set", true, new InstanceHandle[]
|
||||
{
|
||||
c_Attribute
|
||||
});
|
||||
Oms.SetAttributeValue(workSet, Oms.GetInstance(KnownAttributeGuids.Boolean.IncludeSubclasses), true);
|
||||
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
|
||||
|
||||
OmsContext context = Oms.CreateContext();
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
context.SetWorkData(workSet, a_Name);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MultipleValidClassConstraintSingular()
|
||||
{
|
||||
@ -151,4 +173,64 @@ public class WorkSetTests : OmsTestsBase
|
||||
context.SetWorkData(workSet, true);
|
||||
}, Throws.ArgumentException);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextAttributeWorkData()
|
||||
{
|
||||
OmsContext context = Oms.CreateContext();
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign boolean to Text Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
|
||||
context.SetWorkData(a_Name, true);
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign DateTime to Text Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
|
||||
context.SetWorkData(a_Name, DateTime.Now);
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign decimal to Text Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
|
||||
context.SetWorkData(a_Name, 5.3M);
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// can assign string to Text Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
|
||||
context.SetWorkData(a_Name, "hello world");
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DateAttributeWorkData()
|
||||
{
|
||||
OmsContext context = Oms.CreateContext();
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign boolean to Date Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Date.DateAndTime);
|
||||
context.SetWorkData(a_Name, true);
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign decimal to Date Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Date.DateAndTime);
|
||||
context.SetWorkData(a_Name, 5.3M);
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// cannot assign string to Date Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Date.DateAndTime);
|
||||
context.SetWorkData(a_Name, "hello world");
|
||||
}, Throws.ArgumentException);
|
||||
Assert.That(delegate ()
|
||||
{
|
||||
// can assign DateTime to Date Attribute
|
||||
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Date.DateAndTime);
|
||||
context.SetWorkData(a_Name, DateTime.Now);
|
||||
}, Throws.Nothing);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user