update examples and fix major bug in library loader
This commit is contained in:
parent
e322c5a01b
commit
52b1012fd1
@ -1 +1 @@
|
||||
Subproject commit a40a8b3685a377ab183eb0c906acf8c806b4e215
|
||||
Subproject commit 8a989742ca32c5ef46dbee115675f8605fd033c1
|
||||
@ -16,7 +16,6 @@ ln -s $MOCHA_MOCHA_LIBRARIES_PATH system
|
||||
|
||||
# since we cannot 'dotnet add reference', do it manually - it still works
|
||||
FILE=*.csproj
|
||||
|
||||
ROOT_NAMESPACE=MochaTest1
|
||||
|
||||
echo """
|
||||
@ -46,21 +45,15 @@ echo """
|
||||
</Project>
|
||||
""" > $FILE
|
||||
|
||||
FILE=Program.cs
|
||||
MOCHA_SHARE=/usr/share/mocha
|
||||
cp $MOCHA_SHARE/examples/mocha-dotnet-new/Program.cs Program.cs
|
||||
|
||||
echo """
|
||||
// See https://get.mochapowered.com/mocha-dotnet-new for more information
|
||||
|
||||
Mocha.Core.OmsImplementations.EmbeddedMiniOms oms = new Mocha.Core.OmsImplementations.EmbeddedMiniOms();
|
||||
oms.SystemLibraryResourceName = null; // \"mocha_test.resources.net.alcetech.Mocha.System.mcl\";
|
||||
|
||||
oms.Initialize();
|
||||
|
||||
Mocha.Core.LibraryHandle lh = oms.LoadLibrary(\"system/net.alcetech.Mocha.System.mcl\");
|
||||
oms.AddLibraryReference(lh);
|
||||
|
||||
Mocha.Core.InstanceHandle ih = oms.GetInstance(Mocha.Core.KnownInstanceGuids.Classes.Class);
|
||||
|
||||
Console.WriteLine(\"Hello, World! The \`Class\` GID is {0}\", oms.GetGlobalIdentifier(ih));
|
||||
""" > $FILE
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo ""
|
||||
|
||||
echo "1. Edit the Program.cs file to make changes, or open the folder in"
|
||||
echo " your favorite IDE."
|
||||
echo ""
|
||||
echo "2. Type 'dotnet run' to see the program in action."
|
||||
echo ""
|
||||
|
||||
@ -41,6 +41,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{B024
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Plugins.Libraries.McxMini", "mocha-dotnet\src\plugins\Mocha.Plugins.Libraries.McxMini\Mocha.Plugins.Libraries.McxMini.csproj", "{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Oms.Server", "mocha-dotnet\src\app\Mocha.Oms.Server\Mocha.Oms.Server.csproj", "{07828A24-B888-4464-A158-F77AB61F6AD9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -71,6 +73,10 @@ Global
|
||||
{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{07828A24-B888-4464-A158-F77AB61F6AD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07828A24-B888-4464-A158-F77AB61F6AD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07828A24-B888-4464-A158-F77AB61F6AD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07828A24-B888-4464-A158-F77AB61F6AD9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -92,6 +98,7 @@ Global
|
||||
{20B7D199-322C-4942-85FE-46B90C75E92A} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
|
||||
{B024FD23-7084-4DDF-A185-D58BEE7A006F} = {66EB3261-A473-41C7-8D40-E1B4DC8ED4B3}
|
||||
{6005DB73-30D8-4398-8B1F-5E23C0F2FFBF} = {B024FD23-7084-4DDF-A185-D58BEE7A006F}
|
||||
{07828A24-B888-4464-A158-F77AB61F6AD9} = {11486802-8136-4958-8B32-FC34630B0306}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D28A9CF8-0235-4F8F-865F-C460BDCAE16D}
|
||||
|
||||
59
mocha-dotnet/examples/mocha-dotnet-new/Program.cs
Normal file
59
mocha-dotnet/examples/mocha-dotnet-new/Program.cs
Normal file
@ -0,0 +1,59 @@
|
||||
// See https://get.mochapowered.com/mocha-dotnet-new for more information
|
||||
|
||||
using Mocha.Core;
|
||||
using Mocha.Core.Oop;
|
||||
using Mocha.Core.Oop.Methods;
|
||||
|
||||
Mocha.Core.OmsImplementations.EmbeddedMiniOms oms = new Mocha.Core.OmsImplementations.EmbeddedMiniOms();
|
||||
oms.SystemLibraryResourceName = null;
|
||||
|
||||
// Initialize the OMS
|
||||
oms.Initialize();
|
||||
|
||||
// Load the System library
|
||||
Mocha.Core.LibraryHandle lh = oms.LoadLibrary("system/net.alcetech.Mocha.System.mcl");
|
||||
|
||||
// Add the System library reference to the default tenant ('super')
|
||||
oms.AddLibraryReference(lh);
|
||||
|
||||
// ******** Add your own application code here... ********
|
||||
|
||||
// This makes sure that the `Class` class is defined. The class Class is the class of all the classes.
|
||||
Mocha.Core.InstanceHandle clsClass = oms.GetInstance(Mocha.Core.KnownInstanceGuids.Classes.Class);
|
||||
Console.WriteLine("Hello, World! The `Class` GID is {0}", oms.GetGlobalIdentifier(clsClass));
|
||||
|
||||
// This creates a System Attribute Routine that returns the string 'Hello world!'.
|
||||
// To use it, define a Get Attribute by System Routine method that uses this System Attribute Routine.
|
||||
SystemAttributeRoutine srHelloWorld = oms.SystemRoutineBuilder.CreateSystemAttributeRoutine<string>(new Guid("{139eb04a-3da9-4b8a-bc9a-96bff240f013}"), delegate (Oms oms, OmsContext ctx)
|
||||
{
|
||||
return "Hello from a System Attribute Routine! ZQ stack trace: " + ctx.StackTrace.ToString();
|
||||
});
|
||||
|
||||
// Define a Get Attribute by System Routine method that uses this System Attribute Routine.
|
||||
// This Method is identified in UI as `Class@get Hello World(GAS)*S(public)`
|
||||
Mocha.Core.InstanceHandle attValue = oms.GetInstance(Mocha.Core.KnownAttributeGuids.Text.Value);
|
||||
MethodReturningAttribute mHello = oms.MethodBuilder.CreateGetAttributeBySystemRoutineMethod
|
||||
(
|
||||
clsClass,
|
||||
"get",
|
||||
"Hello World",
|
||||
AccessModifier.Public,
|
||||
true,
|
||||
attValue,
|
||||
srHelloWorld
|
||||
);
|
||||
|
||||
// Method Bindings allow us to separate method calls and parameter assignments from method definitions.
|
||||
// A single Method can use parameters which are passed by Method Bindings to change what objects the Method acts upon.
|
||||
ReturnAttributeMethodBinding mbHello = mHello.CreateMethodBinding(oms);
|
||||
|
||||
// An OmsContext is necessary for executing methods. The context stores information about global variables (Work Data)
|
||||
// as well as the ZQ call stack trace to aid in debugging.
|
||||
OmsContext ctx = oms.CreateContext();
|
||||
|
||||
// ExecuteReturningAttributeValue is a convenience method that calls Execute on the given Method Binding, looks up the
|
||||
// value stored in the returned Work Data, and returns that value. You can specify a type parameter to ensure that the
|
||||
// returned value is of the appropriate type. Text Attribute returns string, Boolean Attribute returns bool,
|
||||
// Numeric Attribute returns decimal, and Date Attribute returns System.DateTime
|
||||
string value = oms.ExecuteReturningAttributeValue<string>(ctx, mbHello);
|
||||
Console.WriteLine(value);
|
||||
@ -0,0 +1,17 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\plugins\Mocha.Plugins.Libraries.McxMini\Mocha.Plugins.Libraries.McxMini.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
218
mocha-dotnet/src/app/Mocha.Oms.Server/Program.cs
Normal file
218
mocha-dotnet/src/app/Mocha.Oms.Server/Program.cs
Normal file
@ -0,0 +1,218 @@
|
||||
namespace Mocha.Oms.Server;
|
||||
|
||||
using Mocha.Core;
|
||||
|
||||
using MBS.Web;
|
||||
using System;
|
||||
using Mocha.Core.OmsImplementations;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
public class Program : WebApplication
|
||||
{
|
||||
protected override int DefaultPort => 14678;
|
||||
|
||||
public Program()
|
||||
{
|
||||
ShortName = "mocha-oms-server";
|
||||
}
|
||||
|
||||
private LibraryHandle l_System, l_Web;
|
||||
|
||||
private Oms oms;
|
||||
|
||||
protected override void OnStartup(EventArgs e)
|
||||
{
|
||||
// this all has to be done before the Web server is started...
|
||||
oms = new MemoryOms();
|
||||
|
||||
TenantHandle th = oms.CreateTenant("super");
|
||||
oms.SelectTenant(th);
|
||||
|
||||
LibraryHandle lh = oms.LoadLibrary("/home/beckermj/Documents/Projects/mochapowered/mocha-dotnet/mocha-common/mocha-common/output/net.alcetech.Mocha.System.mcl");
|
||||
oms.AddLibraryReference(lh);
|
||||
|
||||
LibraryHandle lh2 = oms.LoadLibrary("/home/beckermj/Documents/Projects/mochapowered/mocha-dotnet/mocha-common/mocha-common/output/net.alcetech.Mocha.Web.mcl");
|
||||
oms.AddLibraryReference(lh);
|
||||
|
||||
// now we can start the Web server
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
protected override void OnProcessRequest(WebServerProcessRequestEventArgs e)
|
||||
{
|
||||
base.OnProcessRequest(e);
|
||||
|
||||
StreamWriter sw = new StreamWriter(e.Context.Response.Stream);
|
||||
if (e.Context.Request.Path == "/robots.txt")
|
||||
{
|
||||
|
||||
}
|
||||
else if (e.Context.Request.PathParts.Length > 1)
|
||||
{
|
||||
if (e.Context.Request.PathParts[1] == "instances")
|
||||
{
|
||||
if (e.Context.Request.PathParts.Length > 2)
|
||||
{
|
||||
if (e.Context.Request.PathParts[2] == "create")
|
||||
{
|
||||
// usage:
|
||||
// POST /instances/create
|
||||
//
|
||||
// parentClassIid=1$1&title=My+New+Class
|
||||
if (e.Context.Request.Form.ContainsKey("parentClassIid"))
|
||||
{
|
||||
string pclass = e.Context.Request.Form["parentClassIid"];
|
||||
InstanceKey key = InstanceKey.Parse(pclass);
|
||||
|
||||
if (oms.TryGetInstance(key, out InstanceHandle ihParentClass))
|
||||
{
|
||||
InstanceHandle ihRet = oms.CreateInstanceOf(ihParentClass);
|
||||
|
||||
if (e.Context.Request.Form.ContainsKey("title"))
|
||||
{
|
||||
oms.SetAttributeValue(ihRet, oms.GetInstance(KnownAttributeGuids.Text.Name), e.Context.Request.Form["title"]);
|
||||
}
|
||||
|
||||
e.Context.Response.ResponseCode = 200;
|
||||
e.Context.Response.ResponseText = "OK";
|
||||
e.Context.Response.ContentType = "application/json";
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.Add("result", JsonValue.Create("success"));
|
||||
obj.Add("iid", JsonValue.Create(oms.GetInstanceKey(ihRet).ToString()));
|
||||
sw.Write(obj.ToJsonString());
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Context.Response.ResponseCode = 422;
|
||||
e.Context.Response.ResponseText = "Unprocessable Content";
|
||||
e.Context.Response.ContentType = "application/json";
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.Add("result", JsonValue.Create("failure"));
|
||||
obj.Add("message", JsonValue.Create("parent class instance does not exist"));
|
||||
sw.Write(obj.ToJsonString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Context.Request.PathParts[2] == "search")
|
||||
{
|
||||
string query = "";
|
||||
if (e.Context.Request.Query.ContainsKey("q") && e.Context.Request.Query["q"].Count > 0)
|
||||
{
|
||||
query = e.Context.Request.Query["q"][0];
|
||||
}
|
||||
|
||||
string parentClassIid = null;
|
||||
InstanceHandle ihParentClass = InstanceHandle.Empty;
|
||||
if (e.Context.Request.Query.ContainsKey("parentClassIid") && e.Context.Request.Query["parentClassIid"].Count > 0)
|
||||
{
|
||||
parentClassIid = e.Context.Request.Query["parentClassIid"][0];
|
||||
if (InstanceKey.TryParse(parentClassIid, out InstanceKey ikParentClass))
|
||||
{
|
||||
ihParentClass = oms.GetInstance(ikParentClass);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<InstanceHandle> ihs = null;
|
||||
if (ihParentClass != InstanceHandle.Empty)
|
||||
{
|
||||
ihs = oms.GetInstancesOf(ihParentClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
ihs = oms.GetInstances();
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(query))
|
||||
{
|
||||
List<InstanceHandle> list = new List<InstanceHandle>();
|
||||
foreach (InstanceHandle ih in ihs)
|
||||
{
|
||||
string text = oms.GetInstanceText(ih);
|
||||
if (text.ToLower().Contains(query))
|
||||
{
|
||||
list.Add(ih);
|
||||
}
|
||||
}
|
||||
ihs = list;
|
||||
}
|
||||
|
||||
e.Context.Response.ResponseCode = 200;
|
||||
e.Context.Response.ResponseText = "OK";
|
||||
e.Context.Response.ContentType = "application/json";
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
|
||||
JsonArray objInstances = InstancesToJson(ihs);
|
||||
obj.Add("instances", objInstances);
|
||||
|
||||
sw.Write(obj.ToJsonString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Context.Response.ResponseCode = 200;
|
||||
e.Context.Response.ResponseText = "OK";
|
||||
e.Context.Response.ContentType = "application/json";
|
||||
|
||||
JsonObject obj = new JsonObject();
|
||||
|
||||
Stopwatch watch = new Stopwatch();
|
||||
watch.Start();
|
||||
|
||||
IEnumerable<InstanceHandle> ihs = oms.GetInstances();
|
||||
|
||||
watch.Stop();
|
||||
obj.Add("time", JsonValue.Create(watch.ElapsedMilliseconds.ToString()));
|
||||
|
||||
JsonArray objInstances = InstancesToJson(ihs);
|
||||
obj.Add("instances", objInstances);
|
||||
|
||||
sw.Write(obj.ToJsonString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Context.Response.ResponseCode = 404;
|
||||
e.Context.Response.ResponseText = "Not Found";
|
||||
e.Context.Response.ContentType = "text/html";
|
||||
|
||||
sw.WriteLine("<h1>Not Found</h1>");
|
||||
sw.WriteLine("<p>" + e.Context.Request.Path + "</p>");
|
||||
}
|
||||
sw.Flush();
|
||||
sw.Close();
|
||||
}
|
||||
|
||||
private JsonArray InstancesToJson(IEnumerable<InstanceHandle> ihs)
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
foreach (InstanceHandle ih in ihs)
|
||||
{
|
||||
InstanceHandle parentClass = oms.GetParentClass(ih);
|
||||
|
||||
JsonObject objInstance = new JsonObject();
|
||||
objInstance.Add("iid", JsonValue.Create(oms.GetInstanceKey(ih).ToString()));
|
||||
objInstance.Add("text", JsonValue.Create(oms.GetInstanceText(ih)));
|
||||
|
||||
JsonObject objParentClass = new JsonObject();
|
||||
objParentClass.Add("iid", JsonValue.Create(oms.GetInstanceKey(parentClass).ToString()));
|
||||
objParentClass.Add("text", JsonValue.Create(oms.GetInstanceText(parentClass)));
|
||||
objInstance.Add("parentClass", objParentClass);
|
||||
|
||||
array.Add(objInstance);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
return (new Program()).Start();
|
||||
}
|
||||
}
|
||||
@ -52,6 +52,20 @@ namespace Mocha.Core
|
||||
{
|
||||
return new InstanceKey(instanceKey);
|
||||
}
|
||||
public static bool TryParse(string instanceKey, out InstanceKey value)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = InstanceKey.Parse(instanceKey);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
value = InstanceKey.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
public InstanceKey(string instanceKey)
|
||||
{
|
||||
|
||||
@ -11,7 +11,10 @@ public class Library
|
||||
{
|
||||
}
|
||||
|
||||
public Guid GlobalIdentifier { get; set; } = Guid.Empty;
|
||||
|
||||
public LibraryInstance.LibraryInstanceCollection Instances { get; } = new LibraryInstance.LibraryInstanceCollection();
|
||||
public List<LibraryAttribute> Attributes { get; } = new List<LibraryAttribute>();
|
||||
public List<LibraryRelationship> Relationships { get; } = new List<LibraryRelationship>();
|
||||
public List<Guid> LibraryReferences { get; } = new List<Guid>();
|
||||
}
|
||||
|
||||
@ -344,6 +344,11 @@ public abstract class Oms
|
||||
|
||||
InstanceHandle ir = CreateInstance(guid);
|
||||
SetParentClass(ir, ir_class);
|
||||
|
||||
int ct = CountInstances(ir_class);
|
||||
InstanceKey pclass_key = GetInstanceKey(ir_class);
|
||||
InstanceKey new_index = new InstanceKey(pclass_key.InstanceIndex, ct);
|
||||
SetInstanceKey(ir, new_index);
|
||||
return ir;
|
||||
}
|
||||
|
||||
@ -381,10 +386,12 @@ public abstract class Oms
|
||||
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);
|
||||
|
||||
// FIXME: remove in future release; sibling relationships are now properly handled in ValidateConstraintsForRelationship
|
||||
// AssignRelationship(ir_parent, GetInstance(KnownRelationshipGuids.Class__has__Instance), ir);
|
||||
|
||||
int ct = CountInstances(ir_parent);
|
||||
SetInstanceKey(ir, new InstanceKey(GetInstanceKey(ir_parent).InstanceIndex, ct));
|
||||
SetInstanceKey(ir, new InstanceKey(GetInstanceKey(ir_parent).InstanceIndex, ct - 1));
|
||||
}
|
||||
|
||||
public int CountInstances(InstanceHandle ir_parent)
|
||||
@ -395,7 +402,8 @@ public abstract class Oms
|
||||
|
||||
public InstanceHandle GetParentClass(InstanceHandle ir)
|
||||
{
|
||||
IEnumerable<InstanceHandle> irs = GetRelatedInstances(ir, GetInstance(KnownRelationshipGuids.Instance__for__Class));
|
||||
InstanceHandle relInstance__for__Class = GetInstance(KnownRelationshipGuids.Instance__for__Class);
|
||||
IEnumerable<InstanceHandle> irs = GetRelatedInstances(ir, relInstance__for__Class);
|
||||
if (irs.Count() > 0)
|
||||
{
|
||||
return irs.First();
|
||||
@ -794,6 +802,10 @@ public abstract class Oms
|
||||
InstanceHandle parentClass = GetParentClass(methodOrMethodBinding);
|
||||
Guid parentClassId = GetGlobalIdentifier(parentClass);
|
||||
|
||||
context.StackTrace.Push(methodOrMethodBinding);
|
||||
|
||||
InstanceHandle? retval = null;
|
||||
|
||||
if (IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.Classes.MethodBinding)))
|
||||
/*
|
||||
if (IsInstanceOf(methodOrMethodBinding, GetInstance(KnownInstanceGuids.Classes.ReturnAttributeMethodBinding))
|
||||
@ -813,7 +825,7 @@ public abstract class Oms
|
||||
}
|
||||
context.SetWorkData(assignsToParm, assignsFromWorkData);
|
||||
}
|
||||
return ExecuteMethodBinding(context, methodOrMethodBinding);
|
||||
retval = ExecuteMethodBinding(context, methodOrMethodBinding);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -825,11 +837,19 @@ public abstract class Oms
|
||||
InstanceHandle pclassInstance = GetParentClass(hh);
|
||||
context.SetWorkData(pclassInstance, hh);
|
||||
}
|
||||
return methodImplementations[parentClassId].Execute(this, context, methodOrMethodBinding);
|
||||
retval = methodImplementations[parentClassId].Execute(this, context, methodOrMethodBinding);
|
||||
}
|
||||
}
|
||||
if (retval == null)
|
||||
{
|
||||
throw new NotImplementedException(String.Format("method implementation not found for method class {0}", GetGlobalIdentifier(parentClass)));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.StackTrace.Pop();
|
||||
return retval.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private InstanceHandle ExecuteMethodBinding(OmsContext context, InstanceHandle methodBinding)
|
||||
{
|
||||
@ -982,7 +1002,33 @@ public abstract class Oms
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public Dictionary<Guid, SystemRoutine> _systemRoutinesByInstance = new Dictionary<Guid, SystemRoutine>();
|
||||
private OmsSystemRoutineBuilder _systemRoutineBuilder = null;
|
||||
public OmsSystemRoutineBuilder SystemRoutineBuilder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_systemRoutineBuilder == null)
|
||||
{
|
||||
_systemRoutineBuilder = new OmsSystemRoutineBuilder(this);
|
||||
}
|
||||
return _systemRoutineBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
private OmsMethodBuilder _methodBuilder = null;
|
||||
public OmsMethodBuilder MethodBuilder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_methodBuilder == null)
|
||||
{
|
||||
_methodBuilder = new OmsMethodBuilder(this);
|
||||
}
|
||||
return _methodBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<Guid, SystemRoutine> _systemRoutinesByInstance = new Dictionary<Guid, SystemRoutine>();
|
||||
internal void RegisterSystemRoutine(Guid globalIdentifier, SystemRoutine routine)
|
||||
{
|
||||
_systemRoutinesByInstance[globalIdentifier] = routine;
|
||||
@ -1158,6 +1204,20 @@ public abstract class Oms
|
||||
}
|
||||
return LibraryHandle.Empty;
|
||||
}
|
||||
private Dictionary<Guid, LibraryHandle> _librariesGuids = new Dictionary<Guid, LibraryHandle>();
|
||||
/// <summary>
|
||||
/// Gets the <see cref="LibraryHandle" /> for the library with the given Global Identifier.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public LibraryHandle GetLibrary(Guid globalIdentifier)
|
||||
{
|
||||
if (_librariesGuids.ContainsKey(globalIdentifier))
|
||||
{
|
||||
return _librariesGuids[globalIdentifier];
|
||||
}
|
||||
return LibraryHandle.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified library file into memory. To add it to the tenant,
|
||||
@ -1214,7 +1274,6 @@ public abstract class Oms
|
||||
lib.Link();
|
||||
|
||||
InitializeLibrary(lh, lib);
|
||||
|
||||
return lh;
|
||||
}
|
||||
|
||||
@ -1227,6 +1286,7 @@ public abstract class Oms
|
||||
/// <returns></returns>
|
||||
public LibraryHandle LoadLibrary(string filename)
|
||||
{
|
||||
Console.WriteLine("oms: LoadLibrary '{0}'", filename);
|
||||
// some examples:
|
||||
// .mcl compiled binary library file (fastest?)
|
||||
// /path/to/directory containing a bunch of XML / JSON / YAML files
|
||||
@ -1295,6 +1355,7 @@ public abstract class Oms
|
||||
private void InitializeLibrary(LibraryHandle lh, Library lib)
|
||||
{
|
||||
InitializeLibraryInternal(lh, lib);
|
||||
_librariesGuids[lib.GlobalIdentifier] = lh;
|
||||
}
|
||||
|
||||
public string? GetTenantName(TenantHandle tenant)
|
||||
@ -1325,4 +1386,10 @@ public abstract class Oms
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<InstanceHandle> GetInstancesInternal();
|
||||
public IEnumerable<InstanceHandle> GetInstances()
|
||||
{
|
||||
return GetInstancesInternal();
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,9 +24,12 @@ namespace Mocha.Core;
|
||||
public class OmsContext
|
||||
{
|
||||
public Oms Oms { get; }
|
||||
public OmsStackTrace StackTrace { get; }
|
||||
|
||||
internal OmsContext(Oms oms)
|
||||
{
|
||||
Oms = oms;
|
||||
StackTrace = new OmsStackTrace(this);
|
||||
}
|
||||
|
||||
private Dictionary<InstanceHandle, object?> _WorkData = new Dictionary<InstanceHandle, object?>();
|
||||
|
||||
@ -63,6 +63,15 @@ public class MemoryOms : Oms
|
||||
{
|
||||
return _keysByInstance[instance];
|
||||
}
|
||||
foreach (LibraryHandle lh in _libraryReferences)
|
||||
{
|
||||
_Tenant lib = oms._libraries[lh];
|
||||
InstanceKey ik = lib.GetInstanceKey(instance);
|
||||
if (ik != InstanceKey.Empty)
|
||||
{
|
||||
return ik;
|
||||
}
|
||||
}
|
||||
return InstanceKey.Empty;
|
||||
}
|
||||
|
||||
@ -97,6 +106,19 @@ public class MemoryOms : Oms
|
||||
ih = _instancesByKey[ik];
|
||||
return true;
|
||||
}
|
||||
foreach (LibraryHandle lh in _libraryReferences)
|
||||
{
|
||||
if (oms._libraries.ContainsKey(lh))
|
||||
{
|
||||
if (oms._libraries[lh].TryGetInstance(ik, out ih))
|
||||
{
|
||||
// LibraryInst_g g = new LibraryInst_g() { InstanceHandle = ih, SourceLibrary = lh, GlobalIdentifier = globalIdentifier };
|
||||
// _libraries[lh]._libraryInst_gs[globalIdentifier] = g;
|
||||
// _libraries[lh]._libraryInst_is[ih] = g;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ih = InstanceHandle.Empty;
|
||||
return false;
|
||||
}
|
||||
@ -151,11 +173,21 @@ public class MemoryOms : Oms
|
||||
}
|
||||
public IReadOnlyCollection<InstanceHandle> GetRelatedInstances(InstanceHandle source, InstanceHandle relationship, DateTime effectiveDate)
|
||||
{
|
||||
List<InstanceHandle> list2 = new List<InstanceHandle>();
|
||||
|
||||
foreach (LibraryHandle lh in _libraryReferences)
|
||||
{
|
||||
if (oms._libraries.ContainsKey(lh))
|
||||
{
|
||||
IReadOnlyCollection<InstanceHandle> insts2 = oms._libraries[lh].GetRelatedInstances(source, relationship, effectiveDate);
|
||||
list2.AddRange(insts2);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -164,22 +196,9 @@ public class MemoryOms : Oms
|
||||
list2.AddRange(val.TargetInstances);
|
||||
}
|
||||
}
|
||||
return list2.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (LibraryHandle lh in _libraryReferences)
|
||||
{
|
||||
if (oms._libraries.ContainsKey(lh))
|
||||
{
|
||||
IReadOnlyCollection<InstanceHandle> insts2 = oms._libraries[lh].GetRelatedInstances(source, relationship, effectiveDate);
|
||||
if (insts2.Count > 0)
|
||||
{
|
||||
return insts2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new InstanceHandle[0];
|
||||
return list2;
|
||||
}
|
||||
|
||||
public bool HasAttributeValue(InstanceHandle source, InstanceHandle attribute, DateTime effectiveDate)
|
||||
@ -271,6 +290,18 @@ public class MemoryOms : Oms
|
||||
if (_libraryReferences.Contains(library))
|
||||
_libraryReferences.Remove(library);
|
||||
}
|
||||
|
||||
public IEnumerable<InstanceHandle> GetInstances()
|
||||
{
|
||||
List<InstanceHandle> list = new List<InstanceHandle>();
|
||||
foreach (LibraryHandle lh in _libraryReferences)
|
||||
{
|
||||
IEnumerable<InstanceHandle> ihs2 = oms._libraries[lh].GetInstances();
|
||||
list.AddRange(ihs2);
|
||||
}
|
||||
list.AddRange(_instancesByGuid.Values);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<TenantHandle, _Tenant> _tenantData = new Dictionary<TenantHandle, _Tenant>();
|
||||
@ -363,9 +394,21 @@ public class MemoryOms : Oms
|
||||
protected override void InitializeLibraryInternal(LibraryHandle lh, Library data)
|
||||
{
|
||||
_Tenant lib = new _Tenant(this);
|
||||
|
||||
// hack
|
||||
_Tenant old = _CurrentTenantData;
|
||||
_CurrentTenantData = lib;
|
||||
|
||||
foreach (Guid iid in data.LibraryReferences)
|
||||
{
|
||||
lib.AddLibraryReference(GetLibrary(iid));
|
||||
}
|
||||
foreach (LibraryInstance inst in data.Instances)
|
||||
{
|
||||
// Console.WriteLine("library init: created instance '{0}'", inst.InstanceGuid.ToString("B"));
|
||||
|
||||
InstanceHandle ih = lib.CreateInstance(inst.InstanceGuid);
|
||||
SetInstanceKey(ih, inst.InstanceKey);
|
||||
|
||||
// LibraryInst_g lig = new LibraryInst_g() { GlobalIdentifier = inst.InstanceGuid, InstanceHandle = ih, SourceLibrary = lh };
|
||||
// _libraryInst_is[ih] = lig;
|
||||
@ -376,19 +419,27 @@ public class MemoryOms : Oms
|
||||
if (lib.TryGetInstance(att.SourceInstanceGuid, out InstanceHandle src)
|
||||
&& lib.TryGetInstance(att.AttributeInstanceGuid, out InstanceHandle dst))
|
||||
{
|
||||
// Console.WriteLine("library init: set attribute value {0} . {1} = '{2}'", att.SourceInstanceGuid.ToString("B"), att.AttributeInstanceGuid.ToString("B"), att.Value);
|
||||
|
||||
lib.SetAttributeValue(src, dst, att.Value, DateTime.Now);
|
||||
}
|
||||
}
|
||||
foreach (LibraryRelationship rel in data.Relationships)
|
||||
{
|
||||
// here's the prroblem: rel.SourceInstance succeeds, rel.RelationshipInstance failss because it's defined on the other library
|
||||
if (lib.TryGetInstance(rel.SourceInstanceGuid, out InstanceHandle src)
|
||||
&& lib.TryGetInstance(rel.RelationshipInstanceGuid, out InstanceHandle dst)
|
||||
&& lib.TryGetInstance(rel.TargetInstanceGuid, out InstanceHandle tgt))
|
||||
{
|
||||
// Console.WriteLine("library init: assign relationship {0} . {1} = {2}", rel.SourceInstanceGuid.ToString("B"), rel.RelationshipInstanceGuid.ToString("B"), rel.TargetInstanceGuid.ToString("B"));
|
||||
|
||||
lib.AssignRelationship(src, dst, new InstanceHandle[] { tgt }, DateTime.Now);
|
||||
}
|
||||
}
|
||||
_libraries[lh] = lib;
|
||||
|
||||
// hack
|
||||
_CurrentTenantData = old;
|
||||
}
|
||||
|
||||
private struct LibraryInst_g
|
||||
@ -478,4 +529,9 @@ public class MemoryOms : Oms
|
||||
_CurrentTenantData.SetAttributeValue(source, attribute, value, effectiveDate);
|
||||
}
|
||||
|
||||
protected override IEnumerable<InstanceHandle> GetInstancesInternal()
|
||||
{
|
||||
return _CurrentTenantData.GetInstances();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
56
mocha-dotnet/src/lib/Mocha.Core/OmsStackTrace.cs
Normal file
56
mocha-dotnet/src/lib/Mocha.Core/OmsStackTrace.cs
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// Mocha.NET is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Mocha.NET is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Mocha.Core;
|
||||
|
||||
public class OmsStackTrace
|
||||
{
|
||||
private Stack<InstanceHandle> stack = new Stack<InstanceHandle>();
|
||||
|
||||
private OmsContext parent;
|
||||
internal OmsStackTrace(OmsContext parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void Push(InstanceHandle ih)
|
||||
{
|
||||
stack.Push(ih);
|
||||
}
|
||||
public InstanceHandle Pop()
|
||||
{
|
||||
return stack.Pop();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
foreach (InstanceHandle ih in stack)
|
||||
{
|
||||
sb.Append(parent.Oms.GetInstanceKey(ih));
|
||||
if (i < stack.Count - 1)
|
||||
{
|
||||
sb.Append(':');
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@ -54,7 +54,9 @@ public class McxMiniLibraryPlugin : LibraryPlugin
|
||||
McxMiniFlags flags = (McxMiniFlags)r.ReadInt32();
|
||||
|
||||
int sectionsCount = r.ReadInt32();
|
||||
|
||||
Guid libraryGuid = r.ReadGuid();
|
||||
library.GlobalIdentifier = libraryGuid;
|
||||
|
||||
Dictionary<string, McxSection> sections = new Dictionary<string, McxSection>();
|
||||
for (int i = 0; i < sectionsCount; i++)
|
||||
@ -86,11 +88,17 @@ public class McxMiniLibraryPlugin : LibraryPlugin
|
||||
McxSection attributesSection = sections["Attributes"];
|
||||
McxSection relationshipsSection = sections["Relationships"];
|
||||
McxSection stringTableSection = sections["StringTable"];
|
||||
|
||||
McxSection resourcesSection = new McxSection();
|
||||
if (sections.ContainsKey("Resources"))
|
||||
{
|
||||
resourcesSection = sections["Resources"];
|
||||
}
|
||||
McxSection libraryRefsSection = new McxSection();
|
||||
if (sections.ContainsKey("LibraryRefs"))
|
||||
{
|
||||
libraryRefsSection = sections["LibraryRefs"];
|
||||
}
|
||||
|
||||
if (guidsSection.Count != instancesSection.Count)
|
||||
{
|
||||
@ -161,6 +169,13 @@ public class McxMiniLibraryPlugin : LibraryPlugin
|
||||
library.Attributes.Add(new LibraryAttribute(attributes[i].SourceInstanceGuid, attributes[i].AttributeInstanceGuid, stringTable[attributes[i].ValueIndex]));
|
||||
}
|
||||
|
||||
r.BaseStream.Seek(libraryRefsSection.Offset, SeekOrigin.Begin);
|
||||
for (int i = 0; i < libraryRefsSection.Count; i++)
|
||||
{
|
||||
Guid guid = r.ReadGuid();
|
||||
library.LibraryReferences.Add(guid);
|
||||
}
|
||||
|
||||
if (resourcesSection.Length > 0)
|
||||
{
|
||||
|
||||
|
||||
@ -150,4 +150,22 @@ public class BasicTests : OmsTestsBase
|
||||
Assert.That(ihTextAttribute2, Is.EqualTo(ihTextAttribute));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Class_GetInstance_returns_same_InstanceHandle_before_and_after_AddLibraryReference()
|
||||
{
|
||||
// remove the Web reference just for this test
|
||||
// Oms.RemoveLibraryReference(lhWeb);
|
||||
|
||||
InstanceHandle ihTextAttribute = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
|
||||
|
||||
// load the other library, but do not reference it yet
|
||||
LibraryHandle lhWeb = Oms.LoadLibrary(typeof(LibraryLoaderTests), "Mocha.Core.Tests.Resources.net.alcetech.Mocha.Web.mcl");
|
||||
|
||||
// add back the reference to the other library
|
||||
Oms.AddLibraryReference(lhWeb);
|
||||
|
||||
InstanceHandle ihTextAttribute2 = Oms.GetInstance(KnownInstanceGuids.Classes.Class);
|
||||
Assert.That(ihTextAttribute2, Is.EqualTo(ihTextAttribute));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user