update examples and fix major bug in library loader

This commit is contained in:
Michael Becker 2024-10-29 17:03:24 -04:00
parent e322c5a01b
commit 52b1012fd1
14 changed files with 567 additions and 41 deletions

@ -1 +1 @@
Subproject commit a40a8b3685a377ab183eb0c906acf8c806b4e215
Subproject commit 8a989742ca32c5ef46dbee115675f8605fd033c1

View File

@ -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 ""

View File

@ -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}

View 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);

View File

@ -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>

View 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();
}
}

View File

@ -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)
{

View File

@ -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>();
}

View File

@ -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();
}
}

View File

@ -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?>();

View File

@ -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();
}
}

View 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();
}
}

View File

@ -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)
{

View File

@ -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));
}
}