massive update to mocha .NET Core

This commit is contained in:
Michael Becker 2024-07-20 23:44:32 -04:00
parent 07f920194e
commit 3169ff076d
42 changed files with 2648 additions and 17 deletions

@ -1 +1 @@
Subproject commit 7c4b71e091c26ca0526801a4d08cf1be4d5b32b6
Subproject commit 604901d6735f1a3d694d8b874389ea696dc0233b

View File

@ -21,6 +21,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{7D0A3F8A-502
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Core", "framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj", "{91F156ED-2825-4EE2-A051-2A46DB6B0CAD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{11486802-8136-4958-8B32-FC34630B0306}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.ServerApplication", "mocha-dotnet\src\app\Mocha.ServerApplication\Mocha.ServerApplication.csproj", "{15AB12BC-5E65-45F1-9C26-D905EA65FB0F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web-framework-dotnet", "web-framework-dotnet", "{FFAB66C1-ADDB-4A51-B63C-40D8CD96DB8A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6C253683-40D4-4612-B300-0089A6F932F1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{D67F792A-95F6-44EC-80A8-C17A0D0B0644}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Web", "web-framework-dotnet\src\lib\MBS.Web\MBS.Web.csproj", "{1345068A-1AF8-4FAA-A336-457E73ED23A7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{27C300F5-5172-4225-A6F7-3503B9007DD8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Core.Tests", "mocha-dotnet\tests\Mocha.Core.Tests\Mocha.Core.Tests.csproj", "{20B7D199-322C-4942-85FE-46B90C75E92A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -35,6 +51,18 @@ Global
{91F156ED-2825-4EE2-A051-2A46DB6B0CAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91F156ED-2825-4EE2-A051-2A46DB6B0CAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91F156ED-2825-4EE2-A051-2A46DB6B0CAD}.Release|Any CPU.Build.0 = Release|Any CPU
{15AB12BC-5E65-45F1-9C26-D905EA65FB0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15AB12BC-5E65-45F1-9C26-D905EA65FB0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15AB12BC-5E65-45F1-9C26-D905EA65FB0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15AB12BC-5E65-45F1-9C26-D905EA65FB0F}.Release|Any CPU.Build.0 = Release|Any CPU
{1345068A-1AF8-4FAA-A336-457E73ED23A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1345068A-1AF8-4FAA-A336-457E73ED23A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1345068A-1AF8-4FAA-A336-457E73ED23A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1345068A-1AF8-4FAA-A336-457E73ED23A7}.Release|Any CPU.Build.0 = Release|Any CPU
{20B7D199-322C-4942-85FE-46B90C75E92A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20B7D199-322C-4942-85FE-46B90C75E92A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20B7D199-322C-4942-85FE-46B90C75E92A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20B7D199-322C-4942-85FE-46B90C75E92A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -47,6 +75,13 @@ Global
{5D15CF7D-69F7-4F78-AD47-93B332F65982} = {D014ADBA-7B4D-4AA2-8223-C49F7052E6A6}
{7D0A3F8A-502F-469E-BB79-DB4D5212E395} = {5D15CF7D-69F7-4F78-AD47-93B332F65982}
{91F156ED-2825-4EE2-A051-2A46DB6B0CAD} = {7D0A3F8A-502F-469E-BB79-DB4D5212E395}
{11486802-8136-4958-8B32-FC34630B0306} = {66EB3261-A473-41C7-8D40-E1B4DC8ED4B3}
{15AB12BC-5E65-45F1-9C26-D905EA65FB0F} = {11486802-8136-4958-8B32-FC34630B0306}
{6C253683-40D4-4612-B300-0089A6F932F1} = {FFAB66C1-ADDB-4A51-B63C-40D8CD96DB8A}
{D67F792A-95F6-44EC-80A8-C17A0D0B0644} = {6C253683-40D4-4612-B300-0089A6F932F1}
{1345068A-1AF8-4FAA-A336-457E73ED23A7} = {D67F792A-95F6-44EC-80A8-C17A0D0B0644}
{27C300F5-5172-4225-A6F7-3503B9007DD8} = {2A2B84F1-FA6B-4D67-ACB8-E277D50C98F2}
{20B7D199-322C-4942-85FE-46B90C75E92A} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D28A9CF8-0235-4F8F-865F-C460BDCAE16D}

View File

@ -0,0 +1,104 @@
using System.Buffers.Text;
using System.Data.SqlTypes;
using System.Runtime.Intrinsics.X86;
using System.Text;
using MBS.Web;
namespace Mocha.ServerApplication;
public class AssetWebHandler : WebHandler
{
private static string Q3Colorize(string input)
{
string output = input;
output = output.Replace("^1", "\u001b[1;31m");
output = output.Replace("^2", "\u001b[1;32m");
output = output.Replace("^3", "\u001b[1;33m");
output = output.Replace("^4", "\u001b[1;34m");
output = output.Replace("^6", "\u001b[1;35m");
output = output.Replace("^5", "\u001b[1;36m");
return output;
}
protected override void ProcessRequestInternal(WebContext context)
{
string assetName = context.Request.PathVariables["name"];
string assetVersion = context.Request.PathVariables["version"];
string assetPathRaw = context.Request.PathVariables["path"];
string[] pq = assetPathRaw.Split(new char[] { '?' }, 2);
string assetPath = pq[0];
string sha256sum_base64 = String.Empty;
List<KeyValuePair<string, string>> queryValues = new List<KeyValuePair<string, string>>();
if (pq.Length > 1)
{
string[] query = pq[1].Split(new char[] { '&' });
foreach (string q in query)
{
string[] p = q.Split(new char[] { '=' }, 2);
string key = Uri.UnescapeDataString(p[0]), value = "";
if (p.Length > 1)
{
value = Uri.UnescapeDataString(p[1]);
}
if (key.StartsWith("sha256-"))
{
sha256sum_base64 = key.Substring("sha256-".Length);
}
queryValues.Add(new KeyValuePair<string, string>(key, value));
}
}
string sha256sum_txt = String.Empty;
if (!String.IsNullOrEmpty(sha256sum_base64))
{
try
{
byte[] sha256sum_bytes = Convert.FromBase64String(sha256sum_base64);
sha256sum_txt = Convert.ToHexString(sha256sum_bytes);
}
catch (Exception ex)
{
// do nothing, silent failure is acceptable (but maybe we should log it?)
}
}
string basepath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
string filename = basepath + "/assets/" + assetName + "-" + assetVersion + "/" + assetPath;
byte[] data = new byte[0];
if (System.IO.File.Exists(filename))
{
data = System.IO.File.ReadAllBytes(filename);
Console.WriteLine(Q3Colorize(String.Format("^5AssetWebHandler: ^2asset found: {0}@{1}://{2} = {3}", assetName, assetVersion, assetPath, filename)));
}
else
{
Console.WriteLine(Q3Colorize(String.Format("^5AssetWebHandler: ^1asset not found: {0}@{1}://{2} = {3}", assetName, assetVersion, assetPath, filename)));
}
context.Response.ContentType = "text/css";
context.Response.ResponseCode = 200;
context.Response.ResponseText = "OK";
context.Response.Stream.Write(data, 0, data.Length);
return;
byte[] sha256sum2_bytes = System.Security.Cryptography.SHA256.Create().ComputeHash(data);
string sha256sum2_base64 = Convert.ToBase64String(sha256sum2_bytes);
string sha256sum2_txt = Convert.ToHexString(sha256sum2_bytes);
StreamWriter sw = new StreamWriter(context.Response.Stream);
sw.WriteLine("<h1>Asset Load</h1>");
sw.WriteLine("<p>Asset Name: " + assetName + "</p>");
sw.WriteLine("<p>Version: " + assetVersion + "</p>");
sw.WriteLine("<p>Relative Path: " + assetPath + "</p>");
sw.WriteLine("<p>Physical Path: " + filename + "</p>");
sw.WriteLine("<p>SHA256 supplied: " + sha256sum_txt + "</p>");
sw.WriteLine("<p>SHA256 actual: " + sha256sum2_txt + "</p>");
sw.WriteLine("<p>SHA256 passed?: " + (sha256sum_txt.Equals(sha256sum2_txt) ? "YES" : "NO") + "</p>");
sw.Flush();
}
}

View File

@ -0,0 +1,34 @@
using MBS.Core;
using MBS.Web;
using Mocha.Core;
namespace Mocha.ServerApplication;
public class AttachmentWebHandler : WebHandler
{
protected override void ProcessRequestInternal(WebContext context)
{
string tenantName = context.Request.PathVariables["tenant"];
string instanceKeyStr = context.Request.PathVariables["iid"];
InstanceKey instanceKey = InstanceKey.Parse(instanceKeyStr);
string accessKey = context.Request.PathVariables["accesskey"];
MochaWebApplication app = ((MochaWebApplication)Application.Instance);
string oldtenantName = app.Oms.TenantName;
app.Oms.TenantName = tenantName;
InstanceHandle ir = app.Oms.GetInstance(instanceKey);
string contentType = app.Oms.GetAttributeValue<string>(ir, app.Oms.GetInstance(KnownAttributeGuids.Text.ContentType));
string val = app.Oms.GetAttributeValue<string>(ir, app.Oms.GetInstance(KnownAttributeGuids.Text.Value));
byte[] data = Convert.FromBase64String(val);
context.Response.Headers["Content-Type"] = contentType;
context.Response.Stream.Write(data, 0, data.Length);
app.Oms.TenantName = oldtenantName;
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
<ProjectReference Include="..\..\..\..\web-framework-dotnet\src\lib\MBS.Web\MBS.Web.csproj" />
<ProjectReference Include="..\..\lib\Mocha.Core\Mocha.Core.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,164 @@
using System.Net;
using MBS.Core;
using MBS.Web;
using MBS.Web.UI;
using MBS.Web.UI.WebControls;
using Mocha.Core;
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.ServerApplication;
public abstract class MochaWebApplication : WebApplication
{
/// <summary>
/// Gets the <see cref="Mocha.Core.Oms" /> responsible for hosting data on the Mocha advanced database infrastructure.
/// </summary>
/// <value></value>
public Oms Oms { get; }
/// <summary>
/// Gets or sets the name of the tenant which should be navigated to
/// if no tenant is specified in the request.
/// </summary>
/// <value></value>
public string DefaultTenantName { get; set; } = "super";
public MochaWebApplication()
{
Oms = new MiniOms();
Oms.Initialize();
Oms.BasePath = VirtualBasePath;
Oms.TenantName = "super";
}
class LoginWebPage : WebPage
{
protected override void InitializeInternal()
{
base.InitializeInternal();
MochaWebApplication app = ((MochaWebApplication)Application.Instance);
InstanceHandle loginHeaderImage = app.Oms.GetInstance(new Guid("{c4f31b1a-aede-4e91-9fa0-511537f098a5}"));
StyleSheets.Add(WebStyleSheet.FromContent("text/css", @"
table.uwt-formview td.uwt-formview-item-label { padding-top: 10px; }
table.uwt-formview td.uwt-formview-item-content { padding-bottom: 8px; }
body > form > div.uwt-panel
{
margin-right: auto;
margin-left: auto;
width: 600px;
margin-top: 64px;
}
body > form > div.uwt-panel > div.uwt-content > div:first-child
{
background-image: url('" + app.Oms.GetAttachmentUrl(loginHeaderImage) + @"');
background-repeat: no-repeat;
background-size: cover;
height: 256px;
width: 256px;
margin-left: auto;
margin-right: auto;
margin-top: 32px;
margin-bottom: 32px;
}
"));
}
protected override void CreateChildControls()
{
base.CreateChildControls();
Panel panel = new Panel();
panel.ContentControls.Add(new Container());
panel.ContentControls.Add(new FormView(new FormView.FormViewItem[]
{
new FormView.FormViewItem("User _name", new TextBox() { Name = "username" }),
new FormView.FormViewItem("_Password", new TextBox(TextBoxType.Password) { Name = "password" } )
}));
panel.FooterControls.Add(new Button("_Log In"));
Controls.Add(panel);
}
}
protected override void OnProcessRequest(WebServerProcessRequestEventArgs e)
{
base.OnProcessRequest(e);
MochaWebApplication app = ((MochaWebApplication)Application.Instance);
Console.WriteLine("request: {0} {1} {2}", e.Context.Request.Method, e.Context.Request.Path, e.Context.Request.Version);
string[] parts = e.Context.Request.Path.Split(new char[] { '/' });
if (e.Context.Request.Path == "/")
{
// default route
e.Context.Response.Redirect(String.Format("~/{0}", DefaultTenantName));
e.Handled = true;
return;
}
if (parts.Length >= 2)
{
string tenantName = "super";
if (parts[1] != "madi")
{
tenantName = parts[1];
}
else
{
if (parts[2] == "authgwy")
{
tenantName = parts[3];
}
}
TenantHandle tenant = app.Oms.GetTenantByName(tenantName);
if (tenant == TenantHandle.Empty)
{
StreamWriter sw = new StreamWriter(e.Context.Response.Stream);
sw.WriteLine("<h1>Not Found</h1>");
sw.WriteLine("<p>The requested URL was not found on this server.</p>");
sw.WriteLine("<p>Please contact your Mocha applications administrator for further assistance.</p>");
sw.Flush();
e.Handled = true;
return;
}
else
{
app.Oms.SelectTenant(tenant);
}
}
if (parts.Length == 2)
{
e.Context.Response.Redirect("~/" + parts[1] + "/d/home.htmld");
e.Handled = true;
}
}
protected override void OnServerCreated(WebServerCreatedEventArgs e)
{
base.OnServerCreated(e);
e.Server.UserAgent = "Mocha User Interface Service";
// set up the routes
// e.Server.Routes.Add(new WebRoute("/{tenant}", new RedirectWebHandler("~/{tenant}/d/home.htmld")));
e.Server.Routes.Add(new WebRoute("/{tenant}/d/home.htmld", new WebHandler(delegate(WebContext ctx)
{
Console.WriteLine("req app path: " + ctx.Request.Path);
ctx.Response.Redirect("~/" + ctx.Request.PathVariables["tenant"] + "/d/login.htmld");
})));
e.Server.Routes.Add(new WebRoute("/{tenant}/d/login.htmld", new RedirectWebHandler("~/madi/authgwy/{tenant}/login.htmld")));
e.Server.Routes.Add(new WebRoute("/madi/authgwy/{tenant}/login.htmld", new LoginWebPage()));
e.Server.Routes.Add(new WebRoute("/madi/asset/{name}/{version}/{path}", new AssetWebHandler()));
e.Server.Routes.Add(new WebRoute("/{tenant}/attachment/{iid}/{accesskey}", new AttachmentWebHandler()));
}
}

View File

@ -0,0 +1,22 @@
using System.Net;
using MBS.Core;
using MBS.Web;
namespace Mocha.ServerApplication;
public class Program : MochaWebApplication
{
protected override int DefaultPort => 10020;
public Program()
{
ShortName = "mocha-server";
}
public static int Main(string[] args)
{
return (new Program()).Start();
}
}

View File

@ -0,0 +1,13 @@
namespace Mocha.Core;
public struct AttributeValue
{
public readonly DateTime EffectiveDate;
public readonly object? Value;
public AttributeValue(DateTime effectiveDate, object? value)
{
EffectiveDate = effectiveDate;
Value = value;
}
}

View File

@ -19,19 +19,22 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Diagnostics.CodeAnalysis;
using MBS.Core;
namespace Mocha.Core
{
public struct InstanceReference : IEquatable<InstanceReference>
/// <summary>
/// Represents an opaque handle to an instance in a Mocha object management system (OMS).
/// </summary>
public struct InstanceHandle : IEquatable<InstanceHandle>
{
private NanoId _ID;
private bool isNotEmpty;
public static InstanceReference Create()
public static InstanceHandle Create()
{
InstanceReference handle = new InstanceReference();
InstanceHandle handle = new InstanceHandle();
handle._ID = NanoId.Generate();
handle.isNotEmpty = true;
return handle;
@ -42,23 +45,31 @@ namespace Mocha.Core
return System.Text.Encoding.ASCII.GetBytes(_ID.ToString());
}
public static readonly InstanceReference Empty = new InstanceReference();
public static readonly InstanceHandle Empty = new InstanceHandle();
public bool IsEmpty { get { return !isNotEmpty; } }
public bool Equals(InstanceReference other)
public bool Equals(InstanceHandle other)
{
if (IsEmpty && other.IsEmpty)
return true;
return _ID == other._ID && !IsEmpty;
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
if (obj is InstanceHandle)
{
return this.Equals(((InstanceHandle)obj));
}
return base.Equals(obj);
}
public static bool operator ==(InstanceReference left, InstanceReference right)
public static bool operator ==(InstanceHandle left, InstanceHandle right)
{
return left.Equals(right);
}
public static bool operator !=(InstanceReference left, InstanceReference right)
public static bool operator !=(InstanceHandle left, InstanceHandle right)
{
return !left.Equals(right);
}

View File

@ -45,6 +45,12 @@ namespace Mocha.Core
public static Guid Level { get; } = new Guid("{8C528FB0-4063-47B0-BC56-85E387A41BD2}");
public static Guid DebugDefinitionLineNumber { get; } = new Guid("{822be9b7-531d-4aa1-818a-6e4de1609057}");
public static Guid DebugDefinitionColumnNumber { get; } = new Guid("{0f75c750-e738-4410-9b4e-deb422efc7aa}");
public static Guid MinimumLength { get; } = new Guid("{8590e809-3947-418a-a32d-fdbfc0776a55}");
public static Guid MaximumLength { get; } = new Guid("{6d69fee2-f220-4aad-ab89-01bfa491dae1}");
public static Guid MinimumValue { get; } = new Guid("{bc90ffdf-9b6e-444a-a484-f9d06d7f3c31}");
public static Guid MaximumValue { get; } = new Guid("{b9353b1c-2597-4097-96eb-449a6fafcdab}");
}
}
}

View File

@ -23,6 +23,8 @@ namespace Mocha.Core
public static Guid Element { get; } = new Guid("{91929595-3dbd-4eae-8add-6120a49797c7}");
public static Guid ElementContent { get; } = new Guid("{f85d4f5e-c69f-4498-9913-7a8554e233a4}");
public static Guid File { get; } = new Guid("{5D081079-E136-406A-A728-7472937A6E5E}");
public static Guid Translation { get; } = new Guid("{04A53CC8-3206-4A97-99C5-464DB8CAA6E6}");
public static Guid TranslationValue { get; } = new Guid("{6D38E757-EC18-43AD-9C35-D15BB446C0E1}");

View File

@ -85,8 +85,8 @@ namespace Mocha.Core
public static Guid Instance_Prompt_Value__has__Instance { get; } = new Guid("{512B518E-A892-44AB-AC35-4E9DBCABFF0B}");
public static Guid Method__has__Method_Binding { get; } = new Guid("{D52500F1-1421-4B73-9987-223163BC9C04}");
public static Guid Method_Binding__for__Method { get; } = new Guid("{B782A592-8AF5-4228-8296-E3D0B24C70A8}");
public static Guid Method__executed_by__Method_Binding { get; } = new Guid("{D52500F1-1421-4B73-9987-223163BC9C04}");
public static Guid Method_Binding__executes__Method { get; } = new Guid("{B782A592-8AF5-4228-8296-E3D0B24C70A8}");
public static Guid Method__has_return_type__Class { get; } = new Guid("{1241c599-e55d-4dcf-9200-d0e48c217ef8}");
@ -114,7 +114,8 @@ namespace Mocha.Core
public static Guid Validation__has_failure_message__Translation { get; } = new Guid("{E15A97DD-2A1D-4DC0-BD6B-A957B63D9802}");
public static Guid Translation__failure_message_for__Validation { get; } = new Guid("{46a7dfcb-8848-47d5-9ad3-d27fbd8b423f}");
public static Guid Get_Attribute_Method__has__Attribute { get; } = new Guid("{5eca9b3f-be75-4f6e-8495-781480774833}");
public static Guid Get_Attribute_Method__returns__Attribute { get; } = new Guid("{5eca9b3f-be75-4f6e-8495-781480774833}");
public static Guid Attribute__returned_by__Get_Attribute_Method { get; } = new Guid("{e82ace2e-84b7-4912-89ed-7b8efd63bb5d}");
public static Guid Get_Referenced_Instance_Set_Method__loop_on__Instance_Set { get; } = new Guid("{2978238f-7cb0-4ba3-8c6f-473df782cfef}");
public static Guid Get_Referenced_Instance_Set_Method__has_relationship__Method { get; } = new Guid("{6a65819e-c8cb-4575-9af8-ee221364049b}");
@ -122,8 +123,6 @@ namespace Mocha.Core
public static Guid Get_Referenced_Attribute_Method__has__Attribute { get; } = new Guid("{87f90fe9-5ec6-4b09-8f51-b8a4d1544cae}");
public static Guid Get_Referenced_Attribute_Method__loop_on__Instance_Set { get; } = new Guid("{c7ecd498-6d05-4e07-b1bc-f7127d0d6666}");
public static Guid Get_Specific_Instances_Method__has__Instance { get; } = new Guid("{dea1aa0b-2bef-4bac-b4f9-0ce8cf7006fc}");
public static Guid Evaluate_Boolean_Expression_Method__has_source_attribute__Method { get; } = new Guid("{45d76d56-01ed-4641-9f68-cfe0c7d0d265}");
public static Guid Evaluate_Boolean_Expression_Method__equal_to_attribute__Method { get; } = new Guid("{0646df91-7e3e-4d59-be71-b978a22ced8e}");
@ -271,6 +270,11 @@ namespace Mocha.Core
public static Guid Work_Set__has_valid__Class { get; } = new Guid("{08087462-41a5-4271-84bc-a9bcd31a2c21}");
public static Guid Class__valid_for__Work_Set { get; } = new Guid("{73c65dcf-7810-47d4-98c0-898ca1b17a68}");
public static Guid Get_Specified_Instances_Method__returns__Work_Set { get; } = new Guid("{27796f3d-0cbd-42c5-a840-791d3af6c16d}");
public static Guid Work_Set__returned_by__Get_Specified_Instances_Method { get; } = new Guid("{3a0080c7-7061-42a4-9814-cd3f6efaaa16}");
public static Guid Get_Specified_Instances_Method__uses__Instance { get; } = new Guid("{dea1aa0b-2bef-4bac-b4f9-0ce8cf7006fc}");
public static Guid Instance__used_by__Get_Specified_Instances_Method { get; } = new Guid("{13978b33-dd35-4d96-9414-4cb929b549e9}");
public static Guid Conditional_Select_Attribute_Case__invokes__Executable_returning_Attribute { get; } = new Guid("{dbd97430-9c55-430d-815c-77fce9887ba7}");
public static Guid Executable_returning_Attribute__invoked_by__Conditional_Select_Attribute_Case { get; } = new Guid("{f4b04072-abe8-452a-b8f8-e0369dde24d4}");

View File

@ -0,0 +1,6 @@
namespace Mocha.Core.Modeling;
public class OmsClass
{
}

View File

@ -0,0 +1,115 @@
using System.Globalization;
using System.Reflection;
namespace Mocha.Core.Modeling;
public class OmsDatabase
{
public Oms Oms { get; private set; }
private Type _Type = null;
public void Initialize(Oms oms)
{
Oms = oms;
_Type = this.GetType();
Type[] nestedTypes = null;
try
{
nestedTypes = _Type.GetNestedTypes();
}
catch (ReflectionTypeLoadException ex)
{
nestedTypes = ex.Types;
}
foreach (Type t in nestedTypes)
{
if (t == null) continue;
if (t.IsAbstract) continue;
if (!t.IsSubclassOf(typeof(OmsClass)))
continue;
CreateClass(t);
}
}
private void CreateClass(Type t)
{
string className = t.Name;
Guid globalIdentifier = Guid.Empty;
object[] classAttrs = t.GetCustomAttributes(false);
foreach (object attr in classAttrs)
{
if (attr is OmsNameAttribute)
{
className = ((OmsNameAttribute)attr).Name;
}
if (attr is OmsGlobalIdentifierAttribute)
{
globalIdentifier = ((OmsGlobalIdentifierAttribute)attr).GlobalIdentifier;
}
}
PropertyInfo[] properties = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo property in properties)
{
SetupClassProperty(t, property);
}
if (globalIdentifier == Guid.Empty)
{
globalIdentifier = Guid.NewGuid();
}
Console.WriteLine("OmsDatabase: got type {0} (class `{1}` {2})", t.Name, className, globalIdentifier.ToString("B"));
Oms.CreateClass(className, globalIdentifier);
}
private void SetupClassProperty(Type t, PropertyInfo pi)
{
object[] propertyAttrs = pi.GetCustomAttributes(false);
Guid globalIdentifier = Guid.Empty;
foreach (object attr in propertyAttrs)
{
if (attr is OmsGlobalIdentifierAttribute gaAttr)
{
globalIdentifier = gaAttr.GlobalIdentifier;
}
}
if (globalIdentifier == Guid.Empty)
{
globalIdentifier = Guid.NewGuid();
}
InstanceHandle relationshipInstance = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.Relationship), globalIdentifier);
ApplyNativeAttributes(relationshipInstance, propertyAttrs);
}
private void ApplyNativeAttributes(InstanceHandle inst, object[] propertyAttrs)
{
foreach (object attr in propertyAttrs)
{
if (attr is OmsNativeAttribute nativeAttr)
{
InstanceHandle attributeInstance = Oms.GetInstance(nativeAttr.AttributeGlobalIdentifier);
Oms.SetAttributeValue(inst, attributeInstance, nativeAttr.Value);
}
else if (attr is OmsNativeRelationship nativeRel)
{
InstanceHandle relationshipInstance = Oms.GetInstance(nativeRel.RelationshipGlobalIdentifier);
List<InstanceHandle> list = new List<InstanceHandle>();
foreach (Guid guid in nativeRel.TargetInstances)
{
InstanceHandle relinst = Oms.GetInstance(guid);
list.Add(relinst);
}
Oms.AssignRelationship(inst, relationshipInstance, list.ToArray());
}
}
}
}

View File

@ -0,0 +1,11 @@
namespace Mocha.Core.Modeling;
public class OmsGlobalIdentifierAttribute : Attribute
{
public Guid GlobalIdentifier { get; }
public OmsGlobalIdentifierAttribute(string globalIdentifier)
{
GlobalIdentifier = new Guid(globalIdentifier);
}
}

View File

@ -0,0 +1,13 @@
namespace Mocha.Core.Modeling;
public class OmsNameAttribute : Attribute
{
public string Name { get; }
public OmsNameAttribute(string name)
{
Name = name;
}
}

View File

@ -0,0 +1,13 @@
namespace Mocha.Core.Modeling;
public abstract class OmsNativeAttribute : Attribute
{
public Guid AttributeGlobalIdentifier { get; }
public object Value { get; }
public OmsNativeAttribute(Guid attributeGuid, object value)
{
AttributeGlobalIdentifier = attributeGuid;
Value = value;
}
}

View File

@ -0,0 +1,21 @@
namespace Mocha.Core.Modeling;
public abstract class OmsNativeRelationship : Attribute
{
public Guid RelationshipGlobalIdentifier { get; }
public Guid[] TargetInstances { get; }
public OmsNativeRelationship(Guid relationshipGuid, string targetInstances)
{
RelationshipGlobalIdentifier = relationshipGuid;
string[] targetInstancesStr = targetInstances.Split(new char[] { ',' });
List<Guid> list = new List<Guid>();
foreach (string targetInstanceStr in targetInstancesStr)
{
list.Add(new Guid(targetInstanceStr));
}
TargetInstances = list.ToArray();
}
}

View File

@ -0,0 +1,6 @@
namespace Mocha.Core.Modeling;
public class OmsRelationship<TSource, TDestination> where TSource : OmsClass where TDestination : OmsClass
{
}

View File

@ -0,0 +1,6 @@
namespace Mocha.Core.Modeling;
public class OmsRelationshipTargetAttribute : OmsNativeRelationship
{
public OmsRelationshipTargetAttribute(string targetClassGlobalIdentifier) : base(KnownRelationshipGuids.Relationship__has_destination__Class, targetClassGlobalIdentifier) { }
}

View File

@ -0,0 +1,9 @@
namespace Mocha.Core.Modeling;
public class OmsRelationshipTypeAttribute : OmsNativeAttribute
{
public OmsRelationshipTypeAttribute(string relationshipType) : base(KnownAttributeGuids.Text.RelationshipType, relationshipType)
{
}
}

View File

@ -0,0 +1,9 @@
namespace Mocha.Core.Modeling;
public class OmsSingularAttribute : OmsNativeAttribute
{
public OmsSingularAttribute(bool singular) : base(KnownAttributeGuids.Boolean.Singular, singular)
{
}
}

View File

@ -0,0 +1,631 @@
namespace Mocha.Core;
using System.Collections.Frozen;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Numerics;
using System.Runtime.CompilerServices;
using MBS.Core;
public abstract class Oms
{
/// <summary>
/// Gets or sets the base path to which URLs are made relative.
/// </summary>
/// <value></value>
public string BasePath { get; set; } = String.Empty;
public string TenantName { get; set; } = String.Empty;
protected bool ValidateConstraints { get; set; } = true;
protected virtual void InitializeInternal()
{
}
public void Initialize()
{
InitializeInternal();
}
private Dictionary<string, TenantHandle> _tenantsByName = new Dictionary<string, TenantHandle>();
protected void RegisterTenant(string tenantName, TenantHandle handle)
{
_tenantsByName[tenantName] = handle;
}
protected abstract TenantHandle CreateTenantInternal(string tenantName);
public TenantHandle CreateTenant(string tenantName)
{
return CreateTenantInternal(tenantName);
}
public TenantHandle GetTenantByName(string tenantName)
{
if (_tenantsByName.ContainsKey(tenantName))
{
return _tenantsByName[tenantName];
}
return TenantHandle.Empty;
}
protected abstract void SelectTenantInternal(TenantHandle tenant);
public void SelectTenant(TenantHandle tenant)
{
SelectTenantInternal(tenant);
}
protected abstract void ReleaseTenantInternal();
public void ReleaseTenant()
{
ReleaseTenantInternal();
}
protected abstract InstanceKey GetInstanceKeyInternal(InstanceHandle instance);
public InstanceKey GetInstanceKey(InstanceHandle instance)
{
if (instance.Equals(GetInstance(KnownInstanceGuids.Classes.Class)))
{
return new InstanceKey(1, 1);
}
return GetInstanceKeyInternal(instance);
}
protected abstract Guid GetGlobalIdentifierInternal(InstanceHandle instance);
public Guid GetGlobalIdentifier(InstanceHandle instance)
{
return GetGlobalIdentifierInternal(instance);
}
protected abstract void AssignRelationshipInternal(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets, DateTime effectiveDate);
public void AssignRelationship(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets, DateTime effectiveDate)
{
ValidateConstraintsForRelationship(source, relationship, targets);
AssignRelationshipInternal(source, relationship, targets, effectiveDate);
}
public void AssignRelationship(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets)
{
AssignRelationship(source, relationship, targets, DateTime.Now);
}
public void AssignRelationship(InstanceHandle source, InstanceHandle relationship, InstanceHandle target, DateTime effectiveDate)
{
AssignRelationship(source, relationship, new InstanceHandle[] { target }, effectiveDate);
}
public void AssignRelationship(InstanceHandle source, InstanceHandle relationship, InstanceHandle target)
{
AssignRelationship(source, relationship, new InstanceHandle[] { target }, DateTime.Now);
}
private void ValidateConstraintsForRelationship(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets)
{
if (!ValidateConstraints)
return;
if (TryGetAttributeValue<bool>(relationship, GetInstance(KnownAttributeGuids.Boolean.Singular), out bool value))
{
if (value)
{
// enforce singular relationship constraint
if (targets.Count() > 1)
{
throw new InvalidOperationException("Relationship is Singular; must specify no more than one target instance");
}
}
}
InstanceHandle siblingRelationship = GetRelatedInstance(relationship, GetInstance(KnownRelationshipGuids.Relationship__has_sibling__Relationship));
if (siblingRelationship != InstanceHandle.Empty)
{
DateTime dt = DateTime.Now;
foreach (InstanceHandle target in targets)
{
//* we use AssignRelationshipInternal here because calling the top-level function
//* would result in an infinite loop of sibling assignments
AssignRelationshipInternal(target, siblingRelationship, new InstanceHandle[] { source }, dt);
}
}
}
protected abstract void ClearRelationshipInternal(InstanceHandle source, InstanceHandle relationship);
public void ClearRelationship(InstanceHandle source, InstanceHandle relationship)
{
ClearRelationshipInternal(source, relationship);
}
protected abstract InstanceHandle GetInstanceInternal(Guid globalIdentifier);
protected abstract InstanceHandle GetInstanceInternal(InstanceKey ik);
public InstanceHandle GetInstance(Guid globalIdentifier)
{
return GetInstanceInternal(globalIdentifier);
}
public InstanceHandle GetInstance(InstanceKey ik)
{
return GetInstanceInternal(ik);
}
protected abstract IReadOnlyCollection<InstanceHandle> GetRelatedInstancesInternal(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate);
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate)
{
return GetRelatedInstancesInternal(source, relationship, effectiveDate);
}
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship)
{
return GetRelatedInstances(source, relationship, DateTime.Now);
}
protected abstract InstanceHandle CreateInstanceInternal(Guid globalIdentifier);
protected InstanceHandle CreateInstance(Guid globalIdentifier)
{
return CreateInstanceInternal(globalIdentifier);
}
public InstanceHandle CreateInstanceOf(InstanceHandle ir_class)
{
return CreateInstanceOf(ir_class, Guid.NewGuid());
}
public InstanceHandle CreateInstanceOf(InstanceHandle ir_class, Guid guid)
{
if (GetParentClass(ir_class) != GetInstance(KnownInstanceGuids.Classes.Class))
{
throw new InvalidOperationException("cannot create instance of something that is not a Class");
}
InstanceHandle ir = CreateInstance(guid);
SetParentClass(ir, ir_class);
return ir;
}
public InstanceHandle CreateFile(string name, string contentType, Stream stream)
{
return CreateFile(name, contentType, stream, Guid.NewGuid());
}
public InstanceHandle CreateFile(string name, string contentType, Stream stream, Guid globalIdentifier)
{
InstanceHandle c_File = GetInstance(KnownInstanceGuids.Classes.File);
if (c_File == InstanceHandle.Empty)
{
throw new InvalidOperationException(String.Format("The class `File` {0} has not been defined.", KnownInstanceGuids.Classes.File.ToString("x")));
}
InstanceHandle ir = CreateInstanceOf(c_File, globalIdentifier);
SetAttributeValue(ir, GetInstance(KnownAttributeGuids.Text.Name), name);
SetAttributeValue(ir, GetInstance(KnownAttributeGuids.Text.ContentType), contentType);
byte[] data = stream.ReadToEnd();
string dataBase64 = Convert.ToBase64String(data);
SetAttributeValue(ir, GetInstance(KnownAttributeGuids.Text.Value), dataBase64);
return ir;
}
protected abstract void SetInstanceKeyInternal(InstanceHandle target, InstanceKey instanceKey);
protected void SetInstanceKey(InstanceHandle target, InstanceKey instanceKey)
{
SetInstanceKeyInternal(target, instanceKey);
}
protected void SetParentClass(InstanceHandle ir, InstanceHandle ir_parent)
{
ClearRelationship(ir, GetInstance(KnownRelationshipGuids.Instance__for__Class));
AssignRelationship(ir, GetInstance(KnownRelationshipGuids.Instance__for__Class), ir_parent);
AssignRelationship(ir_parent, GetInstance(KnownRelationshipGuids.Class__has__Instance), ir);
int ct = CountInstances(ir_parent);
SetInstanceKey(ir, new InstanceKey(GetInstanceKey(ir_parent).InstanceIndex, ct));
}
public int CountInstances(InstanceHandle ir_parent)
{
IEnumerable<InstanceHandle> irs = GetRelatedInstances(ir_parent, GetInstance(KnownRelationshipGuids.Class__has__Instance));
return irs.Count();
}
public InstanceHandle GetParentClass(InstanceHandle ir)
{
IEnumerable<InstanceHandle> irs = GetRelatedInstances(ir, GetInstance(KnownRelationshipGuids.Instance__for__Class));
if (irs.Count() > 0)
{
return irs.First();
}
return InstanceHandle.Empty;
}
protected abstract bool HasAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate);
public bool HasAttributeValue(InstanceHandle source, InstanceHandle attribute, DateTime? effectiveDate = null)
{
return HasAttributeValueInternal(source, attribute, effectiveDate.GetValueOrDefault(DateTime.Now));
}
protected abstract object? GetAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate);
protected object? UnsafeGetAttributeValue(InstanceHandle source, InstanceHandle attribute, DateTime? effectiveDate = null)
{
object? val = GetAttributeValueInternal(source, attribute, effectiveDate.GetValueOrDefault(DateTime.Now));
return val;
}
public bool TryGetAttributeValue<T>(InstanceHandle source, InstanceHandle attribute, out T value)
{
return TryGetAttributeValue<T>(source, attribute, null, out value);
}
public bool TryGetAttributeValue<T>(InstanceHandle source, InstanceHandle attribute, DateTime? effectiveDate, out T value)
{
DateTime dt = DateTime.Now;
if (HasAttributeValueInternal(source, attribute, effectiveDate.GetValueOrDefault(dt)))
{
object? val = GetAttributeValueInternal(source, attribute, effectiveDate.GetValueOrDefault(dt));
if (val is T)
{
value = (T)val;
return true;
}
}
value = default(T);
return false;
}
public T GetAttributeValue<T>(InstanceHandle source, InstanceHandle attribute, T defaultValue = default(T), DateTime? effectiveDate = null)
{
if (TryGetAttributeValue(source, attribute, effectiveDate, out T value))
{
return value;
}
return defaultValue;
}
protected abstract void SetAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, object value, DateTime effectiveDate);
public void SetAttributeValue(InstanceHandle source, InstanceHandle attribute, object value, DateTime? effectiveDate = null)
{
ValidateConstraintsForAttribute(source, attribute, value);
SetAttributeValueInternal(source, attribute, value, effectiveDate.GetValueOrDefault(DateTime.Now));
}
private void ValidateConstraintsForAttribute(InstanceHandle source, InstanceHandle attribute, object value)
{
InstanceHandle a_TextAttribute = GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle a_BooleanAttribute = GetInstance(KnownInstanceGuids.Classes.BooleanAttribute);
InstanceHandle a_NumericAttribute = GetInstance(KnownInstanceGuids.Classes.NumericAttribute);
InstanceHandle a_DateAttribute = GetInstance(KnownInstanceGuids.Classes.DateAttribute);
if (ValidateConstraints)
{
InstanceHandle sourceParentClass = GetParentClass(source);
if (!RecursiveClassHasAttribute(sourceParentClass, attribute))
{
throw new ArgumentException("The specified attribute is not defined for the given instance.");
}
}
if (IsInstanceOf(attribute, a_TextAttribute))
{
if (!(value is string))
{
throw new ArgumentException("value for TextAttribute must be System.String");
}
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));
}
}
}
}
private bool RecursiveClassHasAttribute(InstanceHandle sourceParentClass, InstanceHandle attribute)
{
// walk through the inheritance hierarchy and check if we have the attribute
IReadOnlyCollection<InstanceHandle> attrs = GetRelatedInstances(sourceParentClass, GetInstance(KnownRelationshipGuids.Class__has__Attribute));
if (attrs != null && attrs.Contains(attribute))
{
return true;
}
else
{
IReadOnlyCollection<InstanceHandle> superclasses = GetRelatedInstances(sourceParentClass, GetInstance(KnownRelationshipGuids.Class__has_super__Class));
if (superclasses != null)
{
foreach (InstanceHandle ir in superclasses)
{
if (RecursiveClassHasAttribute(ir, attribute))
{
return true;
}
}
}
}
return false;
}
public bool IsInstanceOf(InstanceHandle instance, InstanceHandle parentClass)
{
InstanceHandle parentClass1 = GetParentClass(instance);
return Object.Equals(parentClass1, parentClass);
}
public string GetAttachmentUrl(InstanceHandle fileInstance)
{
string entropy = "";
string accessKey = BuildAccessKeyForOmsAttachment(fileInstance, entropy);
return BasePath + TenantName + "/attachment/" + GetInstanceKey(fileInstance).ToString() + "/" + accessKey;
}
private string BuildAccessKeyForOmsAttachment(InstanceHandle fileInstance, string entropy)
{
/*
if (!entropy.ContainsKey(this.GetInstanceKey(inst)))
{
byte[] entropyData = new byte[256];
random.NextBytes(entropyData);
entropy[this.GetInstanceKey(inst)] = entropyData;
}
string entropy_co = Convert.ToBase64String(entropy[this.GetInstanceKey(inst)]);
string guid = inst.GlobalIdentifier.ToString();
long timestamp = DateTime.Now.Ticks;
string originalFileName = this.GetAttributeValue<string>(inst, KnownAttributeGuids.Text.Name);
string ft_co = String.Format("{0}?oms-attachments/{1}?{2}??{3}", entropy_co, guid, timestamp, originalFileName);
string base64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(ft_co));
string safeBase64 = MBS.Framework.Conversion.Base64ToUrlSafeBase64(base64);
return safeBase64;
*/
string entropy_co = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("lalalala"));
//$timestamp = (new \DateTime())->
string timestamp = DateTime.Now.Ticks.ToString();
string originalFileName = "lalala.png";
string ft_co = entropy_co + "?oms-attachments/" + GetGlobalIdentifier(fileInstance) + "?" + timestamp + "??" + originalFileName;
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(ft_co));
}
public InstanceHandle CreateRelationship(InstanceHandle sourceClass, string relationshipName, InstanceHandle destinationClass, Guid relationshipGuid, bool singular)
{
return CreateRelationship(sourceClass, relationshipName, destinationClass, relationshipGuid, singular, null, Guid.Empty);
}
public InstanceHandle CreateRelationship(InstanceHandle sourceClass, string relationshipName, InstanceHandle destinationClass, Guid relationshipGuid, bool singular, string siblingRelationshipName, Guid siblingRelationshipGuid)
{
InstanceHandle c_Relationship = GetInstance(KnownInstanceGuids.Classes.Relationship);
if (c_Relationship == InstanceHandle.Empty)
{
throw new InvalidOperationException("Class `Relationship` is not defined");
}
InstanceHandle r_Relationship__has_source__Class = GetInstance(KnownRelationshipGuids.Relationship__has_source__Class);
if (r_Relationship__has_source__Class == InstanceHandle.Empty)
{
throw new InvalidOperationException("Relationship `Relationship.has source Class` is not defined");
}
InstanceHandle r_Relationship__has_sibling__Relationship = GetInstance(KnownRelationshipGuids.Relationship__has_sibling__Relationship);
if (r_Relationship__has_sibling__Relationship == InstanceHandle.Empty)
{
throw new InvalidOperationException("Relationship `Relationship.has sibling Relationship` is not defined");
}
InstanceHandle a_RelationshipType = GetInstance(KnownAttributeGuids.Text.RelationshipType);
if (a_RelationshipType == InstanceHandle.Empty)
{
throw new InvalidOperationException("Attribute `Relationship Type` is not defined");
}
InstanceHandle a_Singular = GetInstance(KnownAttributeGuids.Boolean.Singular);
if (a_Singular == InstanceHandle.Empty)
{
throw new InvalidOperationException("Attribute `Singular` is not defined");
}
InstanceHandle r_Relationship__has_destination__Class = GetInstance(KnownRelationshipGuids.Relationship__has_destination__Class);
if (r_Relationship__has_destination__Class == InstanceHandle.Empty)
{
throw new InvalidOperationException("Relationship `Relationship.has destination Class` is not defined");
}
InstanceHandle irRelationship = CreateInstanceOf(c_Relationship, relationshipGuid);
AssignRelationship(irRelationship, r_Relationship__has_source__Class, sourceClass);
SetAttributeValue(irRelationship, a_RelationshipType, relationshipName);
SetAttributeValue(irRelationship, a_Singular, singular);
AssignRelationship(irRelationship, r_Relationship__has_destination__Class, destinationClass);
if (siblingRelationshipName != null)
{
if (siblingRelationshipGuid == Guid.Empty)
{
siblingRelationshipGuid = Guid.NewGuid();
}
InstanceHandle irSiblingRelationship = CreateInstanceOf(c_Relationship, siblingRelationshipGuid);
AssignRelationship(irSiblingRelationship, r_Relationship__has_source__Class, destinationClass);
SetAttributeValue(irSiblingRelationship, a_RelationshipType, siblingRelationshipName);
AssignRelationship(irSiblingRelationship, r_Relationship__has_destination__Class, sourceClass);
AssignRelationship(irRelationship, r_Relationship__has_sibling__Relationship, irSiblingRelationship);
AssignRelationship(irSiblingRelationship, r_Relationship__has_sibling__Relationship, irRelationship);
}
return irRelationship;
}
public InstanceHandle GetRelatedInstance(InstanceHandle source, InstanceHandle relationship)
{
IEnumerable<InstanceHandle> irs = GetRelatedInstances(source, relationship);
if (irs == null) return InstanceHandle.Empty;
if (irs.Count() == 0) return InstanceHandle.Empty;
return irs.First();
}
/// <summary>
/// Creates a new Class with the specified name and a randomly-generated global identifier.
/// </summary>
/// <param name="name">The name of the new Class.</param>
/// <returns></returns>
public InstanceHandle CreateClass(string name)
{
return CreateClass(name, Guid.NewGuid());
}
/// <summary>
/// Creates a new Class with the specified name and global identifier.
/// </summary>
/// <param name="name">The name of the new Class.</param>
/// <param name="globalIdentifier">The global identifier to assign the newly-created Class instance.</param>
/// <returns></returns>
public InstanceHandle CreateClass(string name, Guid globalIdentifier)
{
InstanceHandle c_Class = GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle c_new = CreateInstanceOf(c_Class, globalIdentifier);
SetAttributeValue(c_new, GetInstance(KnownAttributeGuids.Text.Name), name);
return c_new;
}
public InstanceHandle ExecuteInstanceMethod(OmsContext context, InstanceHandle instance, InstanceHandle methodBinding)
{
InstanceHandle method = GetRelatedInstance(methodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
InstanceHandle forClass = GetRelatedInstance(method, GetInstance(KnownRelationshipGuids.Method__for__Class));
context.SetWorkData(forClass, instance);
return Execute(context, methodBinding);
}
public object? ExecuteInstanceMethodReturningAttribute(OmsContext context, InstanceHandle instance, InstanceHandle methodBinding)
{
InstanceHandle workSet = ExecuteInstanceMethod(context, instance, methodBinding);
object? value = context.GetWorkData(workSet);
return value;
}
public InstanceHandle Execute(OmsContext context, InstanceHandle methodOrMethodBinding)
{
if (IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.Classes.ReturnAttributeMethodBinding))
|| IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.Classes.ReturnInstanceSetMethodBinding)))
{
return ExecuteMethodBinding(context, methodOrMethodBinding);
}
else
{
if (IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.MethodClasses.GetAttributeMethod)))
{
InstanceHandle irForClass = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle returnsAttribute = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Get_Attribute_Method__returns__Attribute));
if (returnsAttribute == InstanceHandle.Empty)
{
throw new InvalidOperationException("no Work Set specified for method");
}
InstanceHandle forInstance = (InstanceHandle) context.GetWorkData(irForClass);
object? value = UnsafeGetAttributeValue(forInstance, returnsAttribute);
context.SetWorkData(returnsAttribute, value);
return returnsAttribute;
}
else if (IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.MethodClasses.GetSpecifiedInstancesMethod)))
{
InstanceHandle irForClass = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Method__for__Class));
InstanceHandle returnsWorkSet = GetRelatedInstance(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Get_Specified_Instances_Method__returns__Work_Set));
IReadOnlyCollection<InstanceHandle> irUsesInstance = GetRelatedInstances(methodOrMethodBinding, GetInstance(KnownRelationshipGuids.Get_Specified_Instances_Method__uses__Instance));
if (returnsWorkSet == InstanceHandle.Empty)
{
throw new InvalidOperationException("no Work Set specified for method");
}
context.SetWorkData(returnsWorkSet, irUsesInstance);
return returnsWorkSet;
}
}
throw new NotImplementedException();
}
private InstanceHandle ExecuteMethodBinding(OmsContext context, InstanceHandle methodBinding)
{
InstanceHandle method = GetRelatedInstance(methodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
return Execute(context, method);
}
public OmsContext CreateContext()
{
return new OmsContext(this);
}
public IReadOnlyCollection<InstanceHandle> ExecuteStaticMethodReturningInstanceSet(OmsContext context, InstanceHandle methodBinding)
{
InstanceHandle method = GetRelatedInstance(methodBinding, GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method));
if (TryGetAttributeValue<bool>(method, GetInstance(KnownAttributeGuids.Boolean.Static), out bool is_static))
{
if (is_static)
{
InstanceHandle result = Execute(context, methodBinding);
object? value = context.GetWorkData(result);
if (value is IReadOnlyCollection<InstanceHandle> res)
{
return res;
}
}
}
throw new InvalidOperationException("cannot call a non-static Method in a static context");
}
public InstanceHandle CreateWorkSet(string name)
{
return CreateWorkSet(name, false, new InstanceHandle[0]);
}
public InstanceHandle CreateWorkSet(string name, bool singular, ICollection<InstanceHandle> validClasses)
{
InstanceHandle workSet = CreateInstanceOf(GetInstance(KnownInstanceGuids.Classes.WorkSet));
SetAttributeValue(workSet, GetInstance(KnownAttributeGuids.Text.Name), name);
SetAttributeValue(workSet, GetInstance(KnownAttributeGuids.Boolean.Singular), singular);
if (validClasses.Count > 0)
{
AssignRelationship(workSet, GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class), validClasses);
}
return workSet;
}
public void AddAttribute(InstanceHandle targetInstance, InstanceHandle attributeInstance)
{
AssignRelationship(targetInstance, GetInstance(KnownRelationshipGuids.Class__has__Attribute), attributeInstance);
//!FIXME: remove when we have sibling relationships
AssignRelationship(attributeInstance, GetInstance(KnownRelationshipGuids.Attribute__for__Class), targetInstance);
}
public void AddSuperClass(InstanceHandle classInstance, InstanceHandle inheritsFrom)
{
AssignRelationship(classInstance, GetInstance(KnownRelationshipGuids.Class__has_super__Class), inheritsFrom);
//!FIXME: remove when we have sibling relationships
AssignRelationship(inheritsFrom, GetInstance(KnownRelationshipGuids.Class__has_sub__Class), classInstance);
}
}

View File

@ -0,0 +1,73 @@
using System.Linq.Expressions;
namespace Mocha.Core;
public class OmsContext
{
private Oms oms;
internal OmsContext(Oms oms)
{
this.oms = oms;
}
private Dictionary<InstanceHandle, object?> _WorkData = new Dictionary<InstanceHandle, object?>();
public object? GetWorkData(InstanceHandle parm)
{
if (_WorkData.ContainsKey(parm))
return _WorkData[parm];
Console.Error.WriteLine("work data not found for parm {0}", oms.GetGlobalIdentifier(parm));
return null;
}
public void SetWorkData(InstanceHandle parm, object? value)
{
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 InstanceHandle)
{
IReadOnlyCollection<InstanceHandle> irs = oms.GetRelatedInstances(parm, oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
if (irs != null)
{
InstanceHandle ir = (InstanceHandle)value;
InstanceHandle parentClass = oms.GetParentClass(ir);
if (!irs.Contains(parentClass))
{
throw new ArgumentException("instance reference must be an instance of appropriate class");
}
}
}
else if (value is IReadOnlyCollection<InstanceHandle>)
{
IReadOnlyCollection<InstanceHandle> insts = (IReadOnlyCollection<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.");
}
IReadOnlyCollection<InstanceHandle> irs = oms.GetRelatedInstances(parm, oms.GetInstance(KnownRelationshipGuids.Work_Set__has_valid__Class));
if (irs != null)
{
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");
}
}
}
}
else
{
throw new ArgumentException("cannot assign literal data to a Work Set");
}
}
_WorkData[parm] = value;
}
}

View File

@ -0,0 +1,306 @@

using System.Data;
namespace Mocha.Core.OmsImplementations;
public class MemoryOms : Oms
{
private class _Tenant
{
private Dictionary<Guid, InstanceHandle> _instancesByGuid = new Dictionary<Guid, InstanceHandle>();
private Dictionary<InstanceHandle, Guid> _guidsByInstance = new Dictionary<InstanceHandle, Guid>();
private Dictionary<InstanceKey, InstanceHandle> _instancesByKey = new Dictionary<InstanceKey, InstanceHandle>();
private Dictionary<InstanceHandle, InstanceKey> _keysByInstance = new Dictionary<InstanceHandle, InstanceKey>();
private Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<AttributeValue>>> _Attributes = new Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<AttributeValue>>>();
private Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<RelationshipValue>>> _Relationships = new Dictionary<InstanceHandle, Dictionary<InstanceHandle, List<RelationshipValue>>>();
public Guid GetGlobalIdentifier(InstanceHandle instance)
{
return _guidsByInstance[instance];
}
public InstanceKey GetInstanceKey(InstanceHandle instance)
{
if (_keysByInstance.ContainsKey(instance))
{
return _keysByInstance[instance];
}
return InstanceKey.Empty;
}
public InstanceHandle GetInstance(Guid globalIdentifier)
{
return _instancesByGuid[globalIdentifier];
}
public InstanceHandle GetInstance(InstanceKey ik)
{
return _instancesByKey[ik];
}
public void SetInstanceKey(InstanceHandle c_File, InstanceKey instanceKey)
{
_instancesByKey[instanceKey] = c_File;
_keysByInstance[c_File] = instanceKey;
}
public InstanceHandle CreateInstance(Guid guid)
{
InstanceHandle ir = InstanceHandle.Create();
_instancesByGuid[guid] = ir;
_guidsByInstance[ir] = guid;
return ir;
}
public void ClearRelationship(InstanceHandle source, InstanceHandle relationship)
{
if (_Relationships.ContainsKey(source))
{
if (_Relationships[source].ContainsKey(relationship))
{
_Relationships[source][relationship].Clear();
}
}
}
public void AssignRelationship(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets, DateTime effectiveDate)
{
if (!_Relationships.ContainsKey(source))
{
_Relationships.Add(source, new Dictionary<InstanceHandle, List<RelationshipValue>>());
}
List<RelationshipValue> list;
if (_Relationships[source].ContainsKey(relationship))
{
list = _Relationships[source][relationship];
}
else
{
list = new List<RelationshipValue>();
_Relationships[source].Add(relationship, list);
}
InstanceHandle[] targetsArray = targets.ToArray();
list.Add(new RelationshipValue(effectiveDate, targetsArray));
}
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate)
{
if (_Relationships.ContainsKey(source))
{
if (_Relationships[source].ContainsKey(relationship))
{
List<InstanceHandle> list2 = new List<InstanceHandle>();
List<RelationshipValue> list = _Relationships[source][relationship];
foreach (RelationshipValue val in list)
{
if (val.EffectiveDate <= effectiveDate)
{
list2.AddRange(val.TargetInstances);
}
}
return list2.ToArray();
}
}
return new InstanceHandle[0];
}
public bool HasAttributeValue(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate)
{
if (_Attributes.ContainsKey(source))
{
if (_Attributes[source].ContainsKey(attribute))
{
List<AttributeValue> list = _Attributes[source][attribute];
foreach (AttributeValue val in list)
{
if (val.EffectiveDate <= effectiveDate)
{
return true;
}
}
}
}
return false;
}
public object GetAttributeValue(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate)
{
if (_Attributes.ContainsKey(source))
{
if (_Attributes[source].ContainsKey(attribute))
{
List<AttributeValue> list = _Attributes[source][attribute];
foreach (AttributeValue val in list)
{
if (val.EffectiveDate <= effectiveDate)
{
return val.Value;
}
}
}
}
return null;
}
public void SetAttributeValue(InstanceHandle source, InstanceHandle attribute, object value, DateTime effectiveDate)
{
if (!_Attributes.ContainsKey(source))
{
_Attributes[source] = new Dictionary<InstanceHandle, List<AttributeValue>>();
}
List<AttributeValue> list;
if (!_Attributes[source].ContainsKey(attribute))
{
list = new List<AttributeValue>();
_Attributes[source][attribute] = list;
}
else
{
list = _Attributes[source][attribute];
}
list.Add(new AttributeValue(effectiveDate, value));
}
}
private Dictionary<TenantHandle, _Tenant> _tenantData = new Dictionary<TenantHandle, _Tenant>();
private _Tenant _CurrentTenant = null;
protected override TenantHandle CreateTenantInternal(string tenantName)
{
TenantHandle th = TenantHandle.Create();
_tenantData[th] = new _Tenant();
RegisterTenant(tenantName, th);
return th;
}
protected override void SelectTenantInternal(TenantHandle tenant)
{
_CurrentTenant = _tenantData[tenant];
}
protected override void ReleaseTenantInternal()
{
_CurrentTenant = null;
}
protected override Guid GetGlobalIdentifierInternal(InstanceHandle instance)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.GetGlobalIdentifier(instance);
}
protected override InstanceKey GetInstanceKeyInternal(InstanceHandle instance)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
InstanceKey ik = _CurrentTenant.GetInstanceKey(instance);
if (ik == InstanceKey.Empty)
{
// create a new instance key for this instance
InstanceHandle parent = GetParentClass(instance);
if (parent == null)
{
// hack?
parent = GetInstance(KnownInstanceGuids.Classes.Class);
}
IEnumerable<InstanceHandle> insts = GetRelatedInstances(parent, GetInstance(KnownRelationshipGuids.Class__has__Instance));
int i = 0;
foreach (InstanceHandle ir in insts)
{
i++;
if (ir.Equals(instance))
{
break;
}
}
InstanceKey ikParentInst = GetInstanceKey(parent);
ik = new InstanceKey(ikParentInst.InstanceIndex, i);
_CurrentTenant.SetInstanceKey(instance, ik);
}
return ik;
}
protected override InstanceHandle GetInstanceInternal(Guid globalIdentifier)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.GetInstance(globalIdentifier);
}
protected override InstanceHandle GetInstanceInternal(InstanceKey ik)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.GetInstance(ik);
}
protected override void SetInstanceKeyInternal(InstanceHandle source, InstanceKey instanceKey)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
_CurrentTenant.SetInstanceKey(source, instanceKey);
}
protected override InstanceHandle CreateInstanceInternal(Guid guid)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
InstanceHandle ir = _CurrentTenant.CreateInstance(guid);
return ir;
}
protected override void ClearRelationshipInternal(InstanceHandle source, InstanceHandle relationship)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
_CurrentTenant.ClearRelationship(source, relationship);
}
protected override void AssignRelationshipInternal(InstanceHandle source, InstanceHandle relationship, IEnumerable<InstanceHandle> targets, DateTime effectiveDate)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
_CurrentTenant.AssignRelationship(source, relationship, targets, effectiveDate);
}
protected override IReadOnlyCollection<InstanceHandle> GetRelatedInstancesInternal(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.GetRelatedInstances(source, relationship, effectiveDate);
}
protected override bool HasAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.HasAttributeValue(source, attribute, effectiveDate);
}
protected override object? GetAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
return _CurrentTenant.GetAttributeValue(source, attribute, effectiveDate);
}
protected override void SetAttributeValueInternal(InstanceHandle source, InstanceHandle attribute, object value, DateTime effectiveDate)
{
if (_CurrentTenant == null)
throw new InvalidOperationException("Please select a tenant first.");
_CurrentTenant.SetAttributeValue(source, attribute, value, effectiveDate);
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
namespace Mocha.Core.OmsImplementations.Mini;
public abstract class MiniOmsModule
{
protected InstanceHandle c_Class, c_Attribute, c_TextAttribute, c_BooleanAttribute, c_NumericAttribute, c_DateAttribute, c_WorkSet, c_Instance;
protected abstract void BuildInternal(Oms oms);
public void Build(Oms oms)
{
c_Class = oms.GetInstance(KnownInstanceGuids.Classes.Class);
c_Attribute = oms.GetInstance(KnownInstanceGuids.Classes.Attribute);
c_TextAttribute = oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
c_BooleanAttribute = oms.GetInstance(KnownInstanceGuids.Classes.BooleanAttribute);
c_NumericAttribute = oms.GetInstance(KnownInstanceGuids.Classes.NumericAttribute);
c_DateAttribute = oms.GetInstance(KnownInstanceGuids.Classes.DateAttribute);
c_Instance = oms.GetInstance(KnownInstanceGuids.Classes.Instance);
c_WorkSet = oms.GetInstance(KnownInstanceGuids.Classes.WorkSet);
BuildInternal(oms);
}
}

View File

@ -0,0 +1,44 @@
namespace Mocha.Core.OmsImplementations.Mini;
using System;
using MBS.Core;
/// <summary>
/// Builds additional support for Executables and Methods. These must be defined in order to call
/// Oms.Execute(...).
/// </summary>
public class MethodsModule : MiniOmsModule
{
private InstanceHandle c_Method, c_MethodBinding;
private InstanceHandle a_Name, a_Verb, a_Static;
private InstanceHandle c_ReturnAttributeMethodBinding, c_ReturnInstanceSetMethodBinding;
private InstanceHandle c_GetAttributeMethod, c_GetSpecifiedInstancesMethod;
protected override void BuildInternal(Oms oms)
{
c_Method = oms.CreateInstanceOf(c_Class, KnownInstanceGuids.Classes.Method);
c_MethodBinding = oms.CreateClass("Method Binding", KnownInstanceGuids.Classes.MethodBinding);
c_ReturnAttributeMethodBinding = oms.CreateClass("Return Attribute Method Binding", KnownInstanceGuids.Classes.ReturnAttributeMethodBinding);
c_ReturnInstanceSetMethodBinding = oms.CreateClass("Return Instance Set Method Binding", KnownInstanceGuids.Classes.ReturnInstanceSetMethodBinding);
a_Name = oms.GetInstance(KnownAttributeGuids.Text.Name);
a_Verb = oms.CreateInstanceOf(c_TextAttribute, KnownAttributeGuids.Text.Verb);
a_Static = oms.CreateInstanceOf(c_BooleanAttribute, KnownAttributeGuids.Boolean.Static);
oms.CreateRelationship(c_Class, "has", c_Method, KnownRelationshipGuids.Class__has__Method, false, "for", KnownRelationshipGuids.Method__for__Class);
oms.CreateRelationship(c_MethodBinding, "executes", c_Method, KnownRelationshipGuids.Method_Binding__executes__Method, true, "executed by", KnownRelationshipGuids.Method__executed_by__Method_Binding);
c_GetAttributeMethod = oms.CreateClass("GA - Get Attribute Method", KnownInstanceGuids.MethodClasses.GetAttributeMethod);
oms.CreateRelationship(c_GetAttributeMethod, "returns", c_Attribute, KnownRelationshipGuids.Get_Attribute_Method__returns__Attribute, true, "returned by", KnownRelationshipGuids.Attribute__returned_by__Get_Attribute_Method);
oms.AddSuperClass(c_GetAttributeMethod, c_Method);
c_GetSpecifiedInstancesMethod = oms.CreateClass("GSI - Get Specified Instances Method", KnownInstanceGuids.MethodClasses.GetSpecifiedInstancesMethod);
oms.CreateRelationship(c_GetSpecifiedInstancesMethod, "returns", c_WorkSet, KnownRelationshipGuids.Get_Specified_Instances_Method__returns__Work_Set, true, "returned by", KnownRelationshipGuids.Work_Set__returned_by__Get_Specified_Instances_Method);
oms.CreateRelationship(c_GetSpecifiedInstancesMethod, "uses", c_Instance, KnownRelationshipGuids.Get_Specified_Instances_Method__uses__Instance, false, "used by", KnownRelationshipGuids.Instance__used_by__Get_Specified_Instances_Method);
oms.AddSuperClass(c_GetSpecifiedInstancesMethod, c_Method);
oms.AddAttribute(c_Method, a_Name);
oms.AddAttribute(c_Method, a_Verb);
oms.AddAttribute(c_Method, a_Static);
}
}

View File

@ -0,0 +1,15 @@
namespace Mocha.Core.OmsImplementations.Mini.Modules;
public class SecurityModule : MiniOmsModule
{
private InstanceHandle c_User, c_UserLogin, c_Role;
private InstanceHandle r_User__has__Role;
protected override void BuildInternal(Oms oms)
{
c_User = oms.CreateClass("User", KnownInstanceGuids.Classes.User);
c_UserLogin = oms.CreateClass("User Login", KnownInstanceGuids.Classes.UserLogin);
// c_Role = oms.CreateClass("Role", KnownInstanceGuids.Classes.Role);
}
}

View File

@ -0,0 +1,62 @@
namespace Mocha.Core;
public class OmsMethodBuilder
{
private InstanceHandle c_ReturnAttributeMethodBinding, c_ReturnInstanceSetMethodBinding;
public Oms Oms { get; }
public OmsMethodBuilder(Oms oms)
{
Oms = oms;
c_ReturnAttributeMethodBinding = Oms.GetInstance(KnownInstanceGuids.Classes.ReturnAttributeMethodBinding);
c_ReturnInstanceSetMethodBinding = Oms.GetInstance(KnownInstanceGuids.Classes.ReturnInstanceSetMethodBinding);
}
public InstanceHandle CreateReturnAttributeMethodBinding(InstanceHandle method)
{
InstanceHandle methodBinding = Oms.CreateInstanceOf(c_ReturnAttributeMethodBinding);
Oms.AssignRelationship(methodBinding, Oms.GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method), method);
return methodBinding;
}
public InstanceHandle CreateReturnInstanceSetMethodBinding(InstanceHandle method)
{
InstanceHandle methodBinding = Oms.CreateInstanceOf(c_ReturnInstanceSetMethodBinding);
Oms.AssignRelationship(methodBinding, Oms.GetInstance(KnownRelationshipGuids.Method_Binding__executes__Method), method);
return methodBinding;
}
public InstanceHandle CreateGetAttributeMethod(InstanceHandle forClassInstance, string verb, string name, InstanceHandle attributeInstance)
{
return CreateGetAttributeMethod(forClassInstance, verb, name, null, false, attributeInstance);
}
public InstanceHandle CreateGetAttributeMethod(InstanceHandle forClassInstance, string verb, string name, object accessModifier, bool isStatic, InstanceHandle attributeInstance)
{
InstanceHandle method = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.MethodClasses.GetAttributeMethod));
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Method__for__Class), forClassInstance);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Text.Verb), verb);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Text.Name), name);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Boolean.Static), isStatic);
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Get_Attribute_Method__returns__Attribute), attributeInstance);
return method;
}
public InstanceHandle CreateGetSpecifiedInstancesMethod(InstanceHandle forClassInstance, string verb, string name, InstanceHandle returnsWorkSet, InstanceHandle[] specifiedInstances)
{
return CreateGetSpecifiedInstancesMethod(forClassInstance, verb, name, null, false, returnsWorkSet, specifiedInstances);
}
public InstanceHandle CreateGetSpecifiedInstancesMethod(InstanceHandle forClassInstance, string verb, string name, object accessModifier, bool isStatic, InstanceHandle returnsWorkSet, InstanceHandle[] specifiedInstances)
{
InstanceHandle method = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.MethodClasses.GetSpecifiedInstancesMethod));
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Method__for__Class), forClassInstance);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Text.Verb), verb);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Text.Name), name);
Oms.SetAttributeValue(method, Oms.GetInstance(KnownAttributeGuids.Boolean.Static), isStatic);
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Get_Specified_Instances_Method__returns__Work_Set), returnsWorkSet);
Oms.AssignRelationship(method, Oms.GetInstance(KnownRelationshipGuids.Get_Specified_Instances_Method__uses__Instance), specifiedInstances);
return method;
}
}

View File

@ -5,13 +5,13 @@ namespace Mocha.Core
{
public class Relationship
{
public Relationship(InstanceReference sourceInstance, InstanceReference relationshipInstance)
public Relationship(InstanceHandle sourceInstance, InstanceHandle relationshipInstance)
{
SourceInstance = sourceInstance;
RelationshipInstance = relationshipInstance;
}
public InstanceReference SourceInstance { get; }
public InstanceReference RelationshipInstance { get; }
public InstanceHandle SourceInstance { get; }
public InstanceHandle RelationshipInstance { get; }
}
}

View File

@ -0,0 +1,13 @@
namespace Mocha.Core;
public struct RelationshipValue
{
public readonly DateTime EffectiveDate;
public readonly InstanceHandle[] TargetInstances;
public RelationshipValue(DateTime effectiveDate, InstanceHandle[] targets)
{
EffectiveDate = effectiveDate;
TargetInstances = targets;
}
}

View File

@ -0,0 +1,122 @@
using System.Runtime.CompilerServices;
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
[TestFixture]
public class BasicTests : OmsTestsBase
{
protected override Oms CreateOms()
{
return new MiniOms();
}
[Test]
public void PrerequisitesDefined()
{
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
Assert.That(c_Class, Is.Not.EqualTo(InstanceHandle.Empty));
}
[Test]
public void CreateInstanceTest()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass);
Assert.That(irTestClassInstance, Is.Not.EqualTo(InstanceHandle.Empty));
}
[Test]
public void SetAttributeValueTest()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute), TEST_ATTR_GUID);
Assert.That(irTestAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestAttribute);
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass, TEST_CLASS_INST_GUID);
string testAttributeValue = Oms.GetAttributeValue<string>(irTestClassInstance, irTestAttribute);
Assert.That(testAttributeValue, Is.Null);
Oms.SetAttributeValue(irTestClassInstance, irTestAttribute, TEST_ATTR_VALUE);
testAttributeValue = Oms.GetAttributeValue<string>(irTestClassInstance, irTestAttribute);
Assert.That(testAttributeValue, Is.EqualTo(TEST_ATTR_VALUE));
}
[Test]
public void AssignRelationshipTest()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClass2 = Oms.GetInstance(TEST_CLASS2_GUID);
Assert.That(irTestClass2, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestRelationship = Oms.GetInstance(TEST_REL_GUID);
Assert.That(irTestRelationship, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AssignRelationship(irTestClass, irTestRelationship, irTestClass2);
InstanceHandle irRelated = Oms.GetRelatedInstance(irTestClass, irTestRelationship);
Assert.That(irRelated, Is.EqualTo(irTestClass2));
}
[Test]
public void AssignStringToBooleanAttributeFails()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass, TEST_CLASS_INST_GUID);
Assert.That(irTestClassInstance, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestBooleanAttribute = Oms.GetInstance(TEST_ATTR_BOOL_GUID);
Assert.That(irTestBooleanAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestBooleanAttribute);
Assert.That(delegate ()
{
Oms.SetAttributeValue(irTestClassInstance, irTestBooleanAttribute, false);
}, Throws.Nothing, "Assigning a System.Boolean value to a Boolean Attribute MUST NOT throw an exception.");
Assert.That(delegate ()
{
Oms.SetAttributeValue(irTestClassInstance, irTestBooleanAttribute, "The quick brown fox jumps over the lazy dog.");
}, Throws.ArgumentException, "Assigning something other than a System.Boolean value to a Boolean Attribute MUST throw an ArgumentException.");
}
[Test]
public void AssignObjectToTextAttributeFails()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass, TEST_CLASS_INST_GUID);
Assert.That(irTestClassInstance, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestTextAttribute = Oms.GetInstance(TEST_ATTR_GUID);
Assert.That(irTestTextAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestTextAttribute);
Assert.That(delegate ()
{
Oms.SetAttributeValue(irTestClassInstance, irTestTextAttribute, "Teh quick brown fox");
}, Throws.Nothing, "Assigning a System.String value to a Text Attribute MUST NOT throw an exception.");
Assert.That(delegate ()
{
Oms.SetAttributeValue(irTestClassInstance, irTestTextAttribute, irTestClass);
}, Throws.ArgumentException, "Assigning something other than a System.String value to a Text Attribute MUST throw an ArgumentException.");
}
}

View File

@ -0,0 +1 @@
global using NUnit.Framework;

View File

@ -0,0 +1,94 @@
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
public class MethodTests : OmsTestsBase
{
protected override Oms CreateOms()
{
return new MiniOms(new MiniOmsModule[] { new MethodsModule() });
}
[Test]
public void GetAttributeMethodTest()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass);
Assert.That(irTestClassInstance, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute), TEST_ATTR_GUID);
Assert.That(irTestAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.AddAttribute(irTestClass, irTestAttribute);
Oms.SetAttributeValue(irTestClassInstance, irTestAttribute, TEST_ATTR_VALUE);
string testAttributeValue = Oms.GetAttributeValue<string>(irTestClassInstance, irTestAttribute);
Assert.That(testAttributeValue, Is.EqualTo(TEST_ATTR_VALUE));
// here, the test attribute has a particular value.
// let's make sure that calling a GA- Get Attribute method on TestClass returns the same
OmsMethodBuilder methodBuilder = new OmsMethodBuilder(Oms);
InstanceHandle gaMethod = methodBuilder.CreateGetAttributeMethod(irTestClass, "get", "Test Attribute", irTestAttribute);
// Method is: `Test Class@get Test Attribute(GA)`
InstanceHandle gaMethodRamb = methodBuilder.CreateReturnAttributeMethodBinding(gaMethod);
OmsContext context = Oms.CreateContext();
object? testAttributeValue2 = Oms.ExecuteInstanceMethodReturningAttribute(context, irTestClassInstance, gaMethodRamb);
Assert.That(testAttributeValue2, Is.TypeOf<String>());
Assert.That(testAttributeValue2, Is.EqualTo(testAttributeValue));
}
[Test]
public void NonStaticMethodInStaticContext()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
// create a Work Set to hold our data
InstanceHandle ws = Oms.CreateWorkSet("Test Work Set");
OmsMethodBuilder methodBuilder = new OmsMethodBuilder(Oms);
InstanceHandle dummyMethod = methodBuilder.CreateGetSpecifiedInstancesMethod(irTestClass, "get", "Empty Set", null, false, ws, new InstanceHandle[0]);
InstanceHandle dummyMethodRsmb = methodBuilder.CreateReturnInstanceSetMethodBinding(dummyMethod);
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
IReadOnlyCollection<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, dummyMethodRsmb);
}, Throws.InvalidOperationException);
}
[Test]
public void GetSpecifiedInstancesMethodTest()
{
InstanceHandle irTestClass = Oms.GetInstance(TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestClassInstance = Oms.CreateInstanceOf(irTestClass);
Assert.That(irTestClassInstance, Is.Not.EqualTo(InstanceHandle.Empty));
OmsMethodBuilder methodBuilder = new OmsMethodBuilder(Oms);
// create a Work Set to hold our data
InstanceHandle ws = Oms.CreateWorkSet("Test Work Set", true, new InstanceHandle[] { irTestClass });
InstanceHandle gsiMethod = methodBuilder.CreateGetSpecifiedInstancesMethod(irTestClass, "get", "Test Class Instance", null, true, ws, new InstanceHandle[] { irTestClassInstance });
// Method is: `Test Class@get Test Class Instance(GSI)*S`
InstanceHandle gsiMethodRsmb = methodBuilder.CreateReturnInstanceSetMethodBinding(gsiMethod);
OmsContext context = Oms.CreateContext();
IReadOnlyCollection<InstanceHandle> specifiedInstances = Oms.ExecuteStaticMethodReturningInstanceSet(context, gsiMethodRsmb);
Assert.That(specifiedInstances, Contains.Item(irTestClassInstance));
}
}

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\lib\Mocha.Core\Mocha.Core.csproj" />
<ProjectReference Include="..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,17 @@
using Mocha.Core.Modeling;
namespace Mocha.Core.Tests.Modeling;
public abstract class OmsModelingTestsBase : OmsTestsBase
{
protected abstract OmsDatabase GetDatabase();
protected override void AfterSetup()
{
base.AfterSetup();
OmsDatabase db = GetDatabase();
db.Initialize(Oms);
}
}

View File

@ -0,0 +1,124 @@
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
public abstract class OmsTestsBase
{
public Oms Oms { get; private set; }
protected virtual Oms CreateOms() { return new MiniOms(); }
protected readonly Guid TEST_CLASS_GUID = new Guid("{5821fc28-6411-4339-a7d2-56dc05591501}");
protected readonly Guid TEST_CLASS2_GUID = new Guid("{6351ecb7-da5d-4029-ba3a-196a6dc980e9}");
protected readonly Guid TEST_CLASS_INST_GUID = new Guid("{12b4bd54-dabd-4074-be50-ffd78115a85a}");
protected readonly Guid TEST_ATTR_GUID = new Guid("{e4f314a4-f4b1-4cf1-95d8-7a927fb7c8a0}");
protected readonly Guid TEST_ATTR_BOOL_GUID = new Guid("{b8dc887c-9964-4a66-94b1-6dcd00b196dc}");
protected readonly Guid TEST_ATTR_NUM_GUID = new Guid("{62d633df-47ef-43b7-a108-b0b47f5212f6}");
protected readonly Guid TEST_REL_GUID = new Guid("{969d98bc-95e0-45a9-92e5-d70c62980c0e}");
protected readonly Guid TEST_REL2_GUID = new Guid("{235f025a-90a6-43a6-9be1-0b32716eb95a}");
protected readonly string TEST_ATTR_VALUE = "The quick brown fox jumps over the lazy dog.";
[SetUp]
public void Setup()
{
Oms = CreateOms();
Oms.Initialize();
// create the Test Class
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle irTestClass = Oms.CreateInstanceOf(c_Class, TEST_CLASS_GUID);
Assert.That(irTestClass, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
Oms.SetAttributeValue(irTestClass, a_Name, "Test Class");
InstanceHandle irTestClass2 = Oms.CreateInstanceOf(c_Class, TEST_CLASS2_GUID);
Assert.That(irTestClass2, Is.Not.EqualTo(InstanceHandle.Empty));
Oms.SetAttributeValue(irTestClass2, Oms.GetInstance(KnownAttributeGuids.Text.Name), "Test Class 2");
InstanceHandle irTestAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute), TEST_ATTR_GUID);
Assert.That(irTestAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestBooleanAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.BooleanAttribute), TEST_ATTR_BOOL_GUID);
Assert.That(irTestBooleanAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestNumericAttribute = Oms.CreateInstanceOf(Oms.GetInstance(KnownInstanceGuids.Classes.NumericAttribute), TEST_ATTR_NUM_GUID);
Assert.That(irTestNumericAttribute, Is.Not.EqualTo(InstanceHandle.Empty));
InstanceHandle irTestRelationship = Oms.CreateRelationship(irTestClass, "has", irTestClass2, TEST_REL_GUID, true, "for", TEST_REL2_GUID);
Assert.That(irTestRelationship, Is.Not.EqualTo(InstanceHandle.Empty));
AfterSetup();
}
protected virtual void AfterSetup()
{
}
public void CheckInstanceExists(Guid globalIdentifier)
{
CheckInstanceExists(globalIdentifier, out InstanceHandle c);
}
public void CheckInstanceExists(Guid globalIdentifier, out InstanceHandle c)
{
c = Oms.GetInstance(globalIdentifier);
Assert.That(c, Is.Not.EqualTo(InstanceHandle.Empty));
}
/// <summary>
/// Checks that the class with the given Global Identifier exists and, optionally,
/// that it is named the given Name.
/// </summary>
/// <param name="globalIdentifier">The Global Identifier of the class to check.</param>
/// <param name="name">The name to verify (optional)</param>
public void CheckClassExists(Guid globalIdentifier, string name = null)
{
CheckInstanceExists(globalIdentifier, out InstanceHandle c);
InstanceHandle cParent = Oms.GetParentClass(c);
Assert.That(cParent, Is.EqualTo(Oms.GetInstance(KnownInstanceGuids.Classes.Class)));
if (name != null)
{
InstanceHandle a_Name = Oms.GetInstance(KnownAttributeGuids.Text.Name);
Assert.That(Oms.GetAttributeValue<string>(c, a_Name), Is.EqualTo(name));
}
}
public void CheckRelationshipExists(Guid globalIdentifier, out InstanceHandle c)
{
CheckInstanceExists(globalIdentifier, out c);
InstanceHandle cParent = Oms.GetParentClass(c);
Assert.That(cParent, Is.EqualTo(Oms.GetInstance(KnownInstanceGuids.Classes.Relationship)));
}
public void CheckRelationshipExists(Guid globalIdentifier, Guid sourceClassId, string relationshipType, Guid destinationClassId)
{
CheckRelationshipExists(globalIdentifier, out InstanceHandle r);
InstanceHandle r_Relationship__has_source__Class = Oms.GetInstance(KnownRelationshipGuids.Relationship__has_source__Class);
InstanceHandle r_Relationship__has_destination__Class = Oms.GetInstance(KnownRelationshipGuids.Relationship__has_destination__Class);
InstanceHandle sourceClass = Oms.GetRelatedInstance(r, r_Relationship__has_source__Class);
InstanceHandle expectedSourceClass = Oms.GetInstance(sourceClassId);
Assert.That(sourceClass, Is.EqualTo(expectedSourceClass));
if (relationshipType != null)
{
if (Oms.TryGetAttributeValue<string>(r, Oms.GetInstance(KnownAttributeGuids.Text.RelationshipType), out string actualRelationshipType))
{
Assert.That(actualRelationshipType, Is.EqualTo(relationshipType));
}
else
{
Assert.Fail(String.Format("`RelationshipType` attribute not defined for class {0}", globalIdentifier.ToString("b")));
}
}
InstanceHandle destinationClass = Oms.GetRelatedInstance(r, r_Relationship__has_destination__Class);
InstanceHandle expectedDestinationClass = Oms.GetInstance(destinationClassId);
Assert.That(destinationClass, Is.EqualTo(expectedDestinationClass));
}
}

View File

@ -0,0 +1,75 @@
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
public class RelationshipTests : OmsTestsBase
{
protected override Oms CreateOms()
{
return new MiniOms();
}
protected readonly Guid TEST_REL3_GUID = new Guid("{e1cacab7-c8a9-480d-b2b6-5b25c6c549e0}");
protected readonly Guid TEST_REL4_GUID = new Guid("{82b8f531-fe32-4c36-ad3a-9e0f79bc95b4}");
protected readonly Guid TEST_REL5_GUID = new Guid("{b80995cf-6a2d-44c2-9c93-ebb80c9be802}");
protected readonly Guid TEST_REL6_GUID = new Guid("{f5f53839-b47c-42e4-944e-e8fa0bfa9779}");
private InstanceHandle c_TestClass, c_TestClass2;
private InstanceHandle c_TestClassInstance;
private InstanceHandle c_TestClass2Instance1, c_TestClass2Instance2;
private InstanceHandle r_Test_Class__has_single__Test_Class_2, r_Test_Class__has_multiple__Test_Class_2, r_Test_Class_2__single_for__Test_Class;
[SetUp]
public void SetUp()
{
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
c_TestClass = Oms.CreateClass("Test Class", TEST_CLASS_GUID);
c_TestClass2 = Oms.CreateClass("Test Class 2", TEST_CLASS2_GUID);
c_TestClassInstance = Oms.CreateInstanceOf(c_TestClass);
c_TestClass2Instance1 = Oms.CreateInstanceOf(c_TestClass2);
c_TestClass2Instance2 = Oms.CreateInstanceOf(c_TestClass2);
r_Test_Class__has_single__Test_Class_2 = Oms.CreateRelationship(c_TestClass, "has single", c_TestClass2, TEST_REL3_GUID, true, "single for", TEST_REL4_GUID);
r_Test_Class_2__single_for__Test_Class = Oms.GetInstance(TEST_REL4_GUID);
r_Test_Class__has_multiple__Test_Class_2 = Oms.CreateRelationship(c_TestClass, "has multiple", c_TestClass2, TEST_REL5_GUID, false, "multiple for", TEST_REL6_GUID);
}
[Test]
public void MultipleInstanceCannotAssignToSingularRelationship()
{
Assert.That(delegate ()
{
Oms.AssignRelationship(c_TestClassInstance, r_Test_Class__has_single__Test_Class_2, new InstanceHandle[] { c_TestClass2Instance1, c_TestClass2Instance2 });
}, Throws.InvalidOperationException);
}
[Test]
public void SingleInstanceAssignsToSingularRelationship()
{
Assert.That(delegate ()
{
Oms.AssignRelationship(c_TestClassInstance, r_Test_Class__has_single__Test_Class_2, new InstanceHandle[] { c_TestClass2Instance1 });
}, Throws.Nothing);
}
[Test]
public void MultipleInstanceAssignsToNonsingularRelationship()
{
Assert.That(delegate ()
{
Oms.AssignRelationship(c_TestClassInstance, r_Test_Class__has_multiple__Test_Class_2, new InstanceHandle[] { c_TestClass2Instance1, c_TestClass2Instance2 });
}, Throws.Nothing);
}
[Test]
public void SiblingRelationshipAssignsAutomatically()
{
Oms.AssignRelationship(c_TestClassInstance, r_Test_Class__has_single__Test_Class_2, c_TestClass2Instance1);
InstanceHandle ir = Oms.GetRelatedInstance(c_TestClass2Instance1, r_Test_Class_2__single_for__Test_Class);
Assert.That(ir, Is.EqualTo(c_TestClassInstance));
}
}

View File

@ -0,0 +1,26 @@
namespace Mocha.Core.Tests.SampleDatabases;
public class MovieRentalTests : OmsTestsBase
{
private InstanceHandle c_MovieRental, c_Movie, c_MovieRating;
private InstanceHandle r_Movie_Rental__has__Movie, r_Movie__has__Movie_Rating;
private Guid g_c_Movie = new Guid("{da1cf074-d7be-44a2-95fc-4a31621a85d2}");
private Guid g_c_MovieRating = new Guid("{1f84afec-a9fb-42ff-a66e-7ba231c3fee3}");
private Guid g_r_Movie_Rental__has__Movie = new Guid("{dc0732d9-b47a-4a40-bf3e-0da2b3e0966a}");
private Guid g_r_Movie__has__Movie_Rating = new Guid("{9c8c47bd-6edd-4a76-a240-62ad80374092}");
private Guid g_r_Movie_Rating__for__Movie = new Guid("{e25a4fe9-dfa6-4948-b93b-2bfd94484780}");
protected override void AfterSetup()
{
base.AfterSetup();
c_Movie = Oms.CreateClass("Movie", g_c_Movie);
c_MovieRating = Oms.CreateClass("Movie Rating", g_c_MovieRating);
r_Movie_Rental__has__Movie = Oms.CreateRelationship(c_MovieRental, "has", c_Movie, g_r_Movie_Rental__has__Movie, false);
r_Movie__has__Movie_Rating = Oms.CreateRelationship(c_Movie, "has", c_MovieRating, g_r_Movie__has__Movie_Rating, true, "for", g_r_Movie_Rating__for__Movie);
}
}

View File

@ -0,0 +1,68 @@
using Mocha.Core.Modeling;
using Mocha.Core.Tests.Modeling;
namespace Mocha.Core.Tests.SampleDatabases;
public class VehicleForHireDB : OmsDatabase
{
[OmsName("Business"), OmsGlobalIdentifier("{c4e1d676-726c-42f4-9edb-a0ca0ee0e612}")]
public class Business : OmsClass
{
/// <summary>
/// Business.has Driver
/// </summary>
/// <value></value>
[OmsRelationshipType("has"), OmsGlobalIdentifier("{63e5ab3a-4009-4af9-8171-5b23472c1c8c}")]
public OmsRelationship<Business, Driver> Drivers { get; }
/// <summary>
/// Business.has Vehicle
/// </summary>
/// <value></value>
[OmsRelationshipType("has"), OmsGlobalIdentifier("{c54125f6-c3b0-40b2-99f9-e0ed20a75bfa}")]
public OmsRelationship<Business, Driver> Vehicles { get; }
}
[OmsName("Driver"), OmsGlobalIdentifier("{10c51c07-c757-4b00-b406-d54c99460f32}")]
public class Driver : OmsClass
{
}
[OmsName("Vehicle"), OmsGlobalIdentifier("{4b6f186c-babe-4c42-840b-3840373f68c2}")]
public class Vehicle : OmsClass
{
[OmsRelationshipType("has"), OmsGlobalIdentifier("{867126b9-294e-454f-b9c5-88df44353014}"), OmsRelationshipTarget("{38a492b9-901f-4074-af45-642e812b51f5}")]
public VehiclePermit Permit { get; set; }
[OmsRelationshipType("has multiple"), OmsGlobalIdentifier("{2b3111a2-d520-4897-bd3d-00b2e9a49f8b}"), OmsRelationshipTarget("{38a492b9-901f-4074-af45-642e812b51f5}")]
public IList<VehiclePermit> Permits { get; }
}
[OmsName("Vehicle Permit"), OmsGlobalIdentifier("{38a492b9-901f-4074-af45-642e812b51f5}")]
public class VehiclePermit : OmsClass
{
}
}
public class VehicleForHireTests : OmsModelingTestsBase
{
protected override OmsDatabase GetDatabase() => new VehicleForHireDB();
[Test]
public void ClassesCreated()
{
CheckClassExists(new Guid("{c4e1d676-726c-42f4-9edb-a0ca0ee0e612}"), "Business");
CheckClassExists(new Guid("{10c51c07-c757-4b00-b406-d54c99460f32}"), "Driver");
CheckClassExists(new Guid("{4b6f186c-babe-4c42-840b-3840373f68c2}"), "Vehicle");
CheckClassExists(new Guid("{38a492b9-901f-4074-af45-642e812b51f5}"), "Vehicle Permit");
}
[Test]
public void RelationshipsCreated()
{
CheckRelationshipExists(new Guid("{867126b9-294e-454f-b9c5-88df44353014}"), new Guid("{4b6f186c-babe-4c42-840b-3840373f68c2}"), "has", new Guid("{38a492b9-901f-4074-af45-642e812b51f5}"));
}
}

View File

@ -0,0 +1,142 @@
using System.Xml.Serialization;
using Mocha.Core.OmsImplementations.Mini;
namespace Mocha.Core.Tests;
public class WorkSetTests : OmsTestsBase
{
protected override Oms CreateOms()
{
return new MiniOms();
}
[Test]
public void NoValidClassConstraints()
{
// no valid class constraints - we should be able to put anything in here
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle c_Attribute = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle workSet = Oms.CreateWorkSet("Dummy Work Set");
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
context.SetWorkData(workSet, c_Class);
}, Throws.Nothing);
}
[Test]
public void SingleValidClassConstraint()
{
// no valid class constraints - we should be able to put anything in here
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle c_TextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle workSet = Oms.CreateWorkSet("Dummy Work Set", true, new InstanceHandle[]
{
c_TextAttribute
});
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
context.SetWorkData(workSet, c_Class);
}, Throws.ArgumentException);
}
[Test]
public void MultipleValidClassConstraintSingular()
{
// no valid class constraints - we should be able to put anything in here
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle c_TextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle c_BooleanAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.BooleanAttribute);
InstanceHandle a_Value = Oms.GetInstance(KnownAttributeGuids.Text.Value);
InstanceHandle a_Singular = Oms.GetInstance(KnownAttributeGuids.Boolean.Singular);
InstanceHandle workSet = Oms.CreateWorkSet("Dummy Work Set", true, new InstanceHandle[]
{
c_TextAttribute,
c_BooleanAttribute
});
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
context.SetWorkData(workSet, c_Class);
}, Throws.ArgumentException);
Assert.That(delegate ()
{
context.SetWorkData(workSet, a_Value);
}, Throws.Nothing);
Assert.That(delegate ()
{
context.SetWorkData(workSet, a_Singular);
}, Throws.Nothing);
Assert.That(delegate ()
{
context.SetWorkData(workSet, new InstanceHandle[] { a_Value, a_Singular });
}, Throws.InvalidOperationException);
}
[Test]
public void MultipleValidClassConstraintNonsingular()
{
// no valid class constraints - we should be able to put anything in here
InstanceHandle c_Class = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
InstanceHandle c_TextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.TextAttribute);
InstanceHandle c_BooleanAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.BooleanAttribute);
InstanceHandle a_Value = Oms.GetInstance(KnownAttributeGuids.Text.Value);
InstanceHandle a_Singular = Oms.GetInstance(KnownAttributeGuids.Boolean.Singular);
InstanceHandle workSet = Oms.CreateWorkSet("Dummy Work Set", false, new InstanceHandle[]
{
c_TextAttribute,
c_BooleanAttribute
});
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
context.SetWorkData(workSet, c_Class);
}, Throws.ArgumentException);
Assert.That(delegate ()
{
context.SetWorkData(workSet, a_Value);
}, Throws.Nothing);
Assert.That(delegate ()
{
context.SetWorkData(workSet, a_Singular);
}, Throws.Nothing);
Assert.That(delegate ()
{
context.SetWorkData(workSet, new InstanceHandle[] { a_Singular, a_Value });
}, Throws.Nothing);
}
[Test]
public void LiteralValueAssignedToWorkSet()
{
// no valid class constraints - we should be able to put anything in here
InstanceHandle workSet = Oms.CreateWorkSet("Dummy Work Set");
OmsContext context = Oms.CreateContext();
Assert.That(delegate ()
{
// cannot assign literal data to a work set
context.SetWorkData(workSet, true);
}, Throws.ArgumentException);
}
}