massive update to mocha .NET Core
This commit is contained in:
parent
07f920194e
commit
3169ff076d
@ -1 +1 @@
|
||||
Subproject commit 7c4b71e091c26ca0526801a4d08cf1be4d5b32b6
|
||||
Subproject commit 604901d6735f1a3d694d8b874389ea696dc0233b
|
||||
@ -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}
|
||||
|
||||
104
mocha-dotnet/src/app/Mocha.ServerApplication/AssetWebHandler.cs
Normal file
104
mocha-dotnet/src/app/Mocha.ServerApplication/AssetWebHandler.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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>
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
22
mocha-dotnet/src/app/Mocha.ServerApplication/Program.cs
Normal file
22
mocha-dotnet/src/app/Mocha.ServerApplication/Program.cs
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
13
mocha-dotnet/src/lib/Mocha.Core/AttributeValue.cs
Normal file
13
mocha-dotnet/src/lib/Mocha.Core/AttributeValue.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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}");
|
||||
|
||||
|
||||
@ -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}");
|
||||
|
||||
|
||||
6
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsClass.cs
Normal file
6
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsClass.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsClass
|
||||
{
|
||||
|
||||
}
|
||||
115
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsDatabase.cs
Normal file
115
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsDatabase.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsGlobalIdentifierAttribute : Attribute
|
||||
{
|
||||
public Guid GlobalIdentifier { get; }
|
||||
|
||||
public OmsGlobalIdentifierAttribute(string globalIdentifier)
|
||||
{
|
||||
GlobalIdentifier = new Guid(globalIdentifier);
|
||||
}
|
||||
}
|
||||
13
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsNameAttribute.cs
Normal file
13
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsNameAttribute.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsNameAttribute : Attribute
|
||||
{
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public OmsNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsRelationship<TSource, TDestination> where TSource : OmsClass where TDestination : OmsClass
|
||||
{
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsRelationshipTargetAttribute : OmsNativeRelationship
|
||||
{
|
||||
public OmsRelationshipTargetAttribute(string targetClassGlobalIdentifier) : base(KnownRelationshipGuids.Relationship__has_destination__Class, targetClassGlobalIdentifier) { }
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsRelationshipTypeAttribute : OmsNativeAttribute
|
||||
{
|
||||
public OmsRelationshipTypeAttribute(string relationshipType) : base(KnownAttributeGuids.Text.RelationshipType, relationshipType)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
9
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsSIngular.cs
Normal file
9
mocha-dotnet/src/lib/Mocha.Core/Modeling/OmsSIngular.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Mocha.Core.Modeling;
|
||||
|
||||
public class OmsSingularAttribute : OmsNativeAttribute
|
||||
{
|
||||
public OmsSingularAttribute(bool singular) : base(KnownAttributeGuids.Boolean.Singular, singular)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
631
mocha-dotnet/src/lib/Mocha.Core/Oms.cs
Normal file
631
mocha-dotnet/src/lib/Mocha.Core/Oms.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
73
mocha-dotnet/src/lib/Mocha.Core/OmsContext.cs
Normal file
73
mocha-dotnet/src/lib/Mocha.Core/OmsContext.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
306
mocha-dotnet/src/lib/Mocha.Core/OmsImplementations/MemoryOms.cs
Normal file
306
mocha-dotnet/src/lib/Mocha.Core/OmsImplementations/MemoryOms.cs
Normal 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
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
62
mocha-dotnet/src/lib/Mocha.Core/OmsMethodBuilder.cs
Normal file
62
mocha-dotnet/src/lib/Mocha.Core/OmsMethodBuilder.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
13
mocha-dotnet/src/lib/Mocha.Core/RelationshipValue.cs
Normal file
13
mocha-dotnet/src/lib/Mocha.Core/RelationshipValue.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
122
mocha-dotnet/tests/Mocha.Core.Tests/BasicTests.cs
Normal file
122
mocha-dotnet/tests/Mocha.Core.Tests/BasicTests.cs
Normal 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.");
|
||||
}
|
||||
}
|
||||
1
mocha-dotnet/tests/Mocha.Core.Tests/GlobalUsings.cs
Normal file
1
mocha-dotnet/tests/Mocha.Core.Tests/GlobalUsings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
||||
94
mocha-dotnet/tests/Mocha.Core.Tests/MethodTests.cs
Normal file
94
mocha-dotnet/tests/Mocha.Core.Tests/MethodTests.cs
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
25
mocha-dotnet/tests/Mocha.Core.Tests/Mocha.Core.Tests.csproj
Normal file
25
mocha-dotnet/tests/Mocha.Core.Tests/Mocha.Core.Tests.csproj
Normal 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>
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
124
mocha-dotnet/tests/Mocha.Core.Tests/OmsTestsBase.cs
Normal file
124
mocha-dotnet/tests/Mocha.Core.Tests/OmsTestsBase.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
75
mocha-dotnet/tests/Mocha.Core.Tests/RelationshipTests.cs
Normal file
75
mocha-dotnet/tests/Mocha.Core.Tests/RelationshipTests.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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}"));
|
||||
}
|
||||
}
|
||||
142
mocha-dotnet/tests/Mocha.Core.Tests/WorkSetTests.cs
Normal file
142
mocha-dotnet/tests/Mocha.Core.Tests/WorkSetTests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user