Skip to content

Commit 0af45f2

Browse files
feat: unify refProcess naming and add AML base library references
- Rename refObj to refProcess on ProcessOperator (RCL, SUC, instances) - Add ExternalReference to AutomationML Base Libraries (Ed2 v2.11.0) - Add AML base inheritance: FPD_Port→Port, FPD_Process→Structure, FPD_Object→BaseRole - Add dual SupportedRoleClass on SUCs (FPD + AML base roles) - Propagate all SupportedRoleClasses as RoleRequirements on CreateClassInstance - Add GetRefProcessValue() for AML→JSON reading of refProcess attribute - Fix syntax error in ConversionTests.cs
1 parent ee68fa2 commit 0af45f2

4 files changed

Lines changed: 82 additions & 14 deletions

File tree

dotnet/FpbMapper.Conversion/CaexToFpbJson.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ public static ConversionResult<string> Convert(CAEXDocument doc)
4040
{
4141
if (ie.RefBaseSystemUnitPath == ElementToSuc["fpb:ProcessOperator"])
4242
{
43-
var poRefObj = GetRefObjValue(ie);
44-
if (poRefObj != null)
45-
poRefObjMap[ie.ID] = poRefObj;
43+
var poRefProcess = GetRefProcessValue(ie);
44+
if (poRefProcess != null)
45+
poRefObjMap[ie.ID] = poRefProcess;
4646
}
4747
}
4848
}
@@ -238,8 +238,8 @@ private static void ParseProcess(
238238
string? amlIdForPostProcess = null;
239239
if (fpbType == "fpb:ProcessOperator")
240240
{
241-
var poRefObj = GetRefObjValue(ie);
242-
if (poRefObj != null)
241+
var poRefProcess = GetRefProcessValue(ie);
242+
if (poRefProcess != null)
243243
{
244244
decomposedView = "__pending__";
245245
amlIdForPostProcess = ie.ID;
@@ -435,6 +435,14 @@ private static void ParseProcess(
435435
return string.IsNullOrEmpty(val) ? null : val;
436436
}
437437

438+
private static string? GetRefProcessValue(InternalElementType ie)
439+
{
440+
var attr = ie.Attribute["refProcess"];
441+
if (attr == null) return null;
442+
var val = attr.Value;
443+
return string.IsNullOrEmpty(val) ? null : val;
444+
}
445+
438446
private static string? ParseShortName(InternalElementType ie)
439447
{
440448
var ident = ie.Attribute["Identification"];

dotnet/FpbMapper.Conversion/FpbJsonToCaex.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,17 @@ string GetNextInterfaceName(string elementId, string baseName)
223223
SetIdentification(ie, obj.Identification, elemName);
224224
SetCharacteristics(ie, obj.Characteristics);
225225

226-
// refObj
226+
// refProcess (on ProcessOperator only)
227227
if (obj.Type == "fpb:ProcessOperator")
228228
{
229229
if (!string.IsNullOrEmpty(obj.DecomposedView) && poToChildProcess.ContainsKey(obj.Id))
230230
{
231231
var childProcessId = poToChildProcess[obj.Id];
232-
SetAttrValue(ie, "refObj", processAmlIds.GetValueOrDefault(childProcessId, ""));
232+
SetAttrValue(ie, "refProcess", processAmlIds.GetValueOrDefault(childProcessId, ""));
233233
}
234234
else
235235
{
236-
SetAttrValue(ie, "refObj", "");
236+
SetAttrValue(ie, "refProcess", "");
237237
}
238238
}
239239
else if (StateTypes.Contains(obj.Type))
@@ -362,7 +362,18 @@ private static InternalElementType CreateInstance(Dictionary<string, SystemUnitF
362362
{
363363
if (!sucLookup.TryGetValue(sucName, out var suc))
364364
throw new InvalidOperationException($"SystemUnitClass '{sucName}' not found in library");
365-
return (InternalElementType)suc.CreateClassInstance(sucName);
365+
var ie = (InternalElementType)suc.CreateClassInstance(sucName);
366+
367+
// CreateClassInstance only copies the first SupportedRoleClass as RoleRequirement.
368+
// Add any additional SupportedRoleClasses (e.g. AML base roles) manually.
369+
var existingRRs = new HashSet<string>(ie.RoleRequirements.Select(r => r.RefBaseRoleClassPath));
370+
foreach (var src in suc.SupportedRoleClass)
371+
{
372+
if (!existingRRs.Contains(src.RefRoleClassPath))
373+
ie.RoleRequirements.Append().RefBaseRoleClassPath = src.RefRoleClassPath;
374+
}
375+
376+
return ie;
366377
}
367378

368379
// ========================================================================

dotnet/FpbMapper.Conversion/FpbMappings.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,21 @@ public static class LibNames
8383
public const string AttributeTypeLib = "VDI_FPD_AttributeTypeLib";
8484
public const string DIAttributeTypeLib = "VDI_FPD_DI_AttributeTypeLib";
8585
}
86+
87+
// AML Base Library references (AutomationML Edition 2, v2.11.0)
88+
public static class AmlBase
89+
{
90+
public const string Alias = "AutomationMLBaseLibrariesAMLEd22_11_0";
91+
public const string Path = "https://9t4kqL7NX8JsW6o@automationml.ovgu.de/public.php/webdav/AutomationML_Base_Libraries_AMLEd2_2.11.0.aml";
92+
93+
// InterfaceClassLib base
94+
public const string Port = Alias + "@AutomationMLInterfaceClassLib/AutomationMLBaseInterface/Port";
95+
96+
// RoleClassLib bases
97+
public const string BaseRole = Alias + "@AutomationMLBaseRoleClassLib/AutomationMLBaseRole";
98+
public const string Structure = Alias + "@AutomationMLBaseRoleClassLib/AutomationMLBaseRole/Structure";
99+
public const string Product = Alias + "@AutomationMLBaseRoleClassLib/AutomationMLBaseRole/Product";
100+
public const string Process = Alias + "@AutomationMLBaseRoleClassLib/AutomationMLBaseRole/Process";
101+
public const string Resource = Alias + "@AutomationMLBaseRoleClassLib/AutomationMLBaseRole/Resource";
102+
}
86103
}

dotnet/FpbMapper.Conversion/FpdLibraries.cs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,27 @@ public static class FpdLibraries
1313
{
1414
public static void EnsureLibraries(CAEXFileType caex)
1515
{
16+
EnsureExternalReference(caex);
1617
EnsureInterfaceClassLib(caex);
1718
EnsureRoleClassLib(caex);
1819
EnsureAttributeTypeLib(caex);
1920
EnsureDIAttributeTypeLib(caex);
2021
EnsureSystemUnitClassLib(caex);
2122
}
2223

24+
// -- 0. ExternalReference to AML Base Libraries ----------------------------
25+
26+
private static void EnsureExternalReference(CAEXFileType caex)
27+
{
28+
// Check if the reference already exists
29+
foreach (var er in caex.ExternalReference)
30+
if (er.Alias == AmlBase.Alias) return;
31+
32+
var extRef = caex.ExternalReference.Append();
33+
extRef.Alias = AmlBase.Alias;
34+
extRef.Path = AmlBase.Path;
35+
}
36+
2337
// -- 1. InterfaceClassLib ------------------------------------------------
2438

2539
private static void EnsureInterfaceClassLib(CAEXFileType caex)
@@ -33,6 +47,7 @@ private static void EnsureInterfaceClassLib(CAEXFileType caex)
3347
var port = icl.InterfaceClass.Append("FPD_Port");
3448
port.Description = "Abstract base port for all FPD connections.";
3549
port.Version = "1.0.0";
50+
port.RefBaseClassPath = AmlBase.Port;
3651
AddPointAttr(port, "PortCoordinate");
3752

3853
foreach (var name in new[]
@@ -59,10 +74,11 @@ private static void EnsureRoleClassLib(CAEXFileType caex)
5974
rcl.Description = "Semantic model of the FPD per VDI/VDE 3682. Flat layout with explicit inheritance via RefBaseClassPath.";
6075
rcl.Version = "1.0.0";
6176

62-
// FPD_Process
77+
// FPD_Process (inherits AML Structure)
6378
var proc = rcl.RoleClass.Append("FPD_Process");
6479
proc.Description = "Process (Part 2, Fig. 2). Aggregates states (2..*), system limit (1), and process operators (1..*).";
6580
proc.Version = "1.0.0";
81+
proc.RefBaseClassPath = AmlBase.Structure;
6682
AddRefObjAttr(proc, "IDREF to the parent process operator whose decomposition this process represents.");
6783

6884
// FPD_SystemLimit
@@ -72,10 +88,11 @@ private static void EnsureRoleClassLib(CAEXFileType caex)
7288
AddIdentificationAttr(sl);
7389
AddBoundsAttr(sl, "ViewInformation");
7490

75-
// FPD_Object (abstract base)
91+
// FPD_Object (abstract base, inherits AML BaseRole)
7692
var obj = rcl.RoleClass.Append("FPD_Object");
7793
obj.Description = "Abstract base for all FPB objects (Part 1, p. 4: product, energy, information, process operator, technical resource).";
7894
obj.Version = "1.0.0";
95+
obj.RefBaseClassPath = AmlBase.BaseRole;
7996
AddIdentificationAttr(obj);
8097
var charAttr = AddAttr(obj, "Characteristics", "xs:string");
8198
charAttr.Description = "Container for characteristics (Part 2, Fig. 3).";
@@ -101,7 +118,7 @@ private static void EnsureRoleClassLib(CAEXFileType caex)
101118
po.Description = "Process operator (Part 2, Fig. 2). Inherits Identification and Characteristics from FPD_Object.";
102119
po.Version = "1.0.0";
103120
po.RefBaseClassPath = $"{LibNames.RoleClassLib}/FPD_Object";
104-
AddRefObjAttr(po, "IDREF to the child process that decomposes this operator. Empty if the operator is not further decomposed.");
121+
AddRefProcessAttr(po, "IDREF to the child process that decomposes this operator. Empty if the operator is not further decomposed.");
105122

106123
// FPD_TechnicalResource (inherits FPD_Object)
107124
var tr = rcl.RoleClass.Append("FPD_TechnicalResource");
@@ -195,6 +212,7 @@ private static void EnsureSystemUnitClassLib(CAEXFileType caex)
195212
procSuc.Version = "1.0.0";
196213
AddRefObjAttr(procSuc, null);
197214
procSuc.SupportedRoleClass.Append().RefRoleClassPath = $"{LibNames.RoleClassLib}/FPD_Process";
215+
procSuc.SupportedRoleClass.Append().RefRoleClassPath = AmlBase.Structure;
198216

199217
// FPD_SystemLimit (standalone)
200218
var slSuc = sucl.SystemUnitClass.Append("FPD_SystemLimit");
@@ -219,26 +237,31 @@ private static void EnsureSystemUnitClassLib(CAEXFileType caex)
219237
stateSuc.SupportedRoleClass.Append().RefRoleClassPath = $"{LibNames.RoleClassLib}/FPD_State";
220238

221239
// Concrete states (inherit FPD_State)
240+
// Only FPD_Product gets AML base Product role (Energy/Information have no AML base equivalent)
222241
foreach (var name in new[] { "FPD_Product", "FPD_Energy", "FPD_Information" })
223242
{
224243
var suc = sucl.SystemUnitClass.Append(name);
225244
suc.Version = "1.0.0";
226245
suc.RefBaseClassPath = $"{LibNames.SystemUnitClassLib}/FPD_State";
227246
suc.SupportedRoleClass.Append().RefRoleClassPath = $"{LibNames.RoleClassLib}/{name}";
247+
if (name == "FPD_Product")
248+
suc.SupportedRoleClass.Append().RefRoleClassPath = AmlBase.Product;
228249
}
229250

230-
// FPD_ProcessOperator (inherits FPD_Object, adds refObj)
251+
// FPD_ProcessOperator (inherits FPD_Object, adds refProcess)
231252
var poSuc = sucl.SystemUnitClass.Append("FPD_ProcessOperator");
232253
poSuc.Version = "1.0.0";
233254
poSuc.RefBaseClassPath = $"{LibNames.SystemUnitClassLib}/FPD_Object";
234-
AddRefObjAttr(poSuc, null);
255+
AddRefProcessAttr(poSuc, null);
235256
poSuc.SupportedRoleClass.Append().RefRoleClassPath = $"{LibNames.RoleClassLib}/FPD_ProcessOperator";
257+
poSuc.SupportedRoleClass.Append().RefRoleClassPath = AmlBase.Process;
236258

237259
// FPD_TechnicalResource (inherits FPD_Object)
238260
var trSuc = sucl.SystemUnitClass.Append("FPD_TechnicalResource");
239261
trSuc.Version = "1.0.0";
240262
trSuc.RefBaseClassPath = $"{LibNames.SystemUnitClassLib}/FPD_Object";
241263
trSuc.SupportedRoleClass.Append().RefRoleClassPath = $"{LibNames.RoleClassLib}/FPD_TechnicalResource";
264+
trSuc.SupportedRoleClass.Append().RefRoleClassPath = AmlBase.Resource;
242265
}
243266

244267
// -- Helpers --------------------------------------------------------------
@@ -289,4 +312,13 @@ private static void AddRefObjAttr(IObjectWithAttributes parent, string? descript
289312
if (description != null)
290313
attr.Description = description;
291314
}
315+
316+
private static void AddRefProcessAttr(IObjectWithAttributes parent, string? description)
317+
{
318+
var attr = parent.Attribute.Append("refProcess");
319+
attr.AttributeDataType = "xs:string";
320+
attr.RefAttributeType = AttrRefs.RefObj;
321+
if (description != null)
322+
attr.Description = description;
323+
}
292324
}

0 commit comments

Comments
 (0)