Skip to content
This repository has been archived by the owner on Apr 16, 2024. It is now read-only.

Commit

Permalink
* have Cardinality for SME but
Browse files Browse the repository at this point in the history
   put it in Organizes as well
  • Loading branch information
festo-i40 committed Nov 22, 2023
1 parent 2b45cfd commit 0172385
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 39 deletions.
15 changes: 14 additions & 1 deletion src/AasxCsharpLibrary/Extensions/ExtendISubmodelElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,20 @@ public static IQualifier FindQualifierOfType(this ISubmodelElement submodelEleme

}

public static IReference GetModelReference(this ISubmodelElement sme, bool includeParents = true)
public static IEnumerable<IQualifier> FindQualifierOfAnyType(
this ISubmodelElement submodelElement, string[] qualifierTypes)
{
if (qualifierTypes == null || qualifierTypes.Length < 1)
yield break;
foreach (var qualifierType in qualifierTypes)
{
var res = FindQualifierOfType(submodelElement, qualifierType);
if (res != null)
yield return res;
}
}

public static IReference GetModelReference(this ISubmodelElement sme, bool includeParents = true)
{
// this will be the tail of our chain
var keyList = new List<IKey>();
Expand Down
3 changes: 2 additions & 1 deletion src/AasxPackageExplorer/options-debug.MIHO.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
// "AuxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_Sample_A.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\00_FestoDemoBox-Module-2-Kopie2.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\SMT_and_SAMM_Showcase_v01.aasx",
"AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\Run2_DNP_plus_CD_SM_step_2.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\Run2_DNP_plus_CD_SM_step_2.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\Test1.aasx",
"AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\SMT_and_SAMM_Showcase_v02.aasx",
"WindowLeft": 200,
"WindowTop": -1,
"WindowWidth": 900,
Expand Down
180 changes: 150 additions & 30 deletions src/AasxPackageLogic/DispEditHelperExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,13 @@ protected void ExtensionHelperAddEnumField(
});
}

public AnyUiLambdaActionBase ExtensionHelperIdfReferenceAction(
public AnyUiLambdaActionBase ExtensionHelperIdfReferenceAction<T>(
Aas.Environment env,
Aas.IReferable relatedReferable,
int actionIndex,
ExtIdfReference sr,
Action<ExtIdfReference> setValue,
Func<string, ExtIdfReference> createInstance)
T sr,
Action<T> setValue,
Func<string, T> createInstance) where T : ExtIdfReference
{
if (actionIndex == 0)
{
Expand Down Expand Up @@ -343,18 +343,18 @@ public AnyUiLambdaActionBase ExtensionHelperIdfReferenceAction(
return new AnyUiLambdaActionNone();
}

public void ExtensionHelperAddIdfReference(
public void ExtensionHelperAddIdfReference<T>(
Aas.Environment env,
AnyUiStackPanel stack,
string caption,
ExtensionRecordBase recInst,
Aas.IReferable relatedReferable,
ExtIdfReference sr,
Action<ExtIdfReference> setValue,
Func<string, ExtIdfReference> createInstance,
T sr,
Action<T> setValue,
Func<string, T> createInstance,
int firstColumnWidth = -1, // -1 = Standard
string[] presetList = null,
bool showButtons = true)
bool showButtons = true) where T : ExtIdfReference
{
var grid = AddSmallGrid(1, 2, colWidths: new[] { "*", "#" });
stack.Add(grid);
Expand Down Expand Up @@ -386,25 +386,41 @@ public void ExtensionHelperAddIdfReference(
setValue: setValue,
createInstance: createInstance);
});

if (sr is ExtIdfCardinalityReference cardrf)
{
// edit
ExtensionHelperAddEnumField(
grid, 0, 1,
"",
typeForEnum: typeof(SmtCardinality),
enumValue: cardrf.Cardinality,
setEnumValue: (o) =>
{
cardrf.Cardinality = (SmtCardinality)o;
setValue?.Invoke(cardrf as T);
return new AnyUiLambdaActionNone();
});
}
}

public void ExtensionHelperAddListOfIdfReference(
public void ExtensionHelperAddListOfIdfReference<T>(
Aas.Environment env,
AnyUiStackPanel stack,
QuickLookupIdentifiable lookupIdf,
string caption,
ExtensionRecordBase recInst,
Aas.IReferable relatedReferable,
List<ExtIdfReference> value,
Action<List<ExtIdfReference>> setValue,
Func<string, ExtIdfReference> createInstance)
List<T> value,
Action<List<T>> setValue,
Func<string, T> createInstance) where T : ExtIdfReference
{
this.AddVerticalSpace(stack);

if (this.SafeguardAccess(stack, repo, value, "" + caption + ":",
"Create data element!",
v => {
setValue?.Invoke(new List<ExtIdfReference>(new ExtIdfReference[] { createInstance?.Invoke("") }));
setValue?.Invoke(new List<T>(new T[] { createInstance?.Invoke("") }));
return new AnyUiLambdaActionRedrawEntity();
}))
{
Expand Down Expand Up @@ -544,6 +560,14 @@ public void ExtensionHelperAddEditFieldsByReflection(
var propType = pii.PropertyType;
var underlyingType = Nullable.GetUnderlyingType(propType);

// some flags logic
var propFlags = pii.GetCustomAttribute<ExtensionFlagsAttribute>()?.Flags;
if (propFlags != null)
{
if (relatedReferable is Aas.IConceptDescription && propFlags.Contains("SKIPFORCD"))
continue;
}

// make hint lambda
Action<bool> hintLambda = (hint) =>
{
Expand Down Expand Up @@ -682,7 +706,7 @@ public void ExtensionHelperAddEditFieldsByReflection(
hintLambda(lidr == null || lidr.Count < 1);

// edit
ExtensionHelperAddListOfIdfReference(
ExtensionHelperAddListOfIdfReference<ExtIdfReference>(
env, stack,
lookupIdf,
caption: "" + pii.Name,
Expand All @@ -697,6 +721,31 @@ public void ExtensionHelperAddEditFieldsByReflection(
createInstance: (eir) => new ExtIdfReference(eir));
}

// List of SmtIdfCardinalityReference?
if (pii.PropertyType.IsAssignableTo(typeof(List<ExtIdfCardinalityReference>)))
{
// value
var lidr = (List<ExtIdfCardinalityReference>)pii.GetValue(recInst);

// hint?
hintLambda(lidr == null || lidr.Count < 1);

// edit
ExtensionHelperAddListOfIdfReference<ExtIdfCardinalityReference>(
env, stack,
lookupIdf,
caption: "" + pii.Name,
recInst,
relatedReferable,
value: lidr,
setValue: (v) =>
{
pii.SetValue(recInst, v);
setValue?.Invoke(recInst);
},
createInstance: (eir) => new ExtIdfCardinalityReference(eir));
}

// single IdfReference?
if (pii.PropertyType.IsAssignableTo(typeof(ExtIdfReference)))
{
Expand Down Expand Up @@ -1367,8 +1416,10 @@ public static SmtAttributeRecord FindSmtQualifiers(Aas.IReferable rf, bool remov
// to convert
rec = rec ?? new SmtAttributeRecord();

if (qti.Type == "SMT/Cardinality")
rec.Cardinality = (SmtCardinality)
if (qti.Type == "SMT/Cardinality"
|| qti.Type == "Cardinality"
|| qti.Type == "Multiplicity")
rec.SmeCardinality = (SmtCardinality)
EnumHelper.GetEnumMemberFromValueString<SmtCardinality>(qf.Value);

if (qti.Type == "SMT/EitherOr")
Expand Down Expand Up @@ -1426,6 +1477,20 @@ public static bool ConvertSmtQualifiersToExtension(Aas.IReferable rf)
}
}

/// <summary>
/// Some string based flags to attach to the property
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)]
public class ExtensionFlagsAttribute : System.Attribute
{
public string Flags = "";

public ExtensionFlagsAttribute(string flags)
{
Flags = flags;
}
}

/// <summary>
/// This attribute gives a list of given presets to an field or property.
/// in order to avoid cycles
Expand Down Expand Up @@ -1498,6 +1563,21 @@ public ExtIdfReference(string val = "")
}
}

/// <summary>
/// This class creates a reference to an Identifiable, which "feels" like a string.
/// A cardinality is included, as well
/// </summary>
public class ExtIdfCardinalityReference : ExtIdfReference
{
public SmtCardinality Cardinality { get; set; }

public ExtIdfCardinalityReference(string val = "", SmtCardinality cardinality = SmtCardinality.One)
{
Value = val;
Cardinality = cardinality;
}
}

/// <summary>
/// Shall be implemented in order to give hints about the
/// (hierarchical) structuring of elements
Expand Down Expand Up @@ -1573,8 +1653,10 @@ IEnumerable<ExtIdfReference> IAbstractStructureModel<ExtIdfReference>.DescendOnc
// attributes

[ExtensionHintAttribute("Specifies, how many SubmodelElement instances of this " +
"SMT element are allowed in the actual collection (hierarchy level of the Submodel).")]
public AasSmtQualifiers.SmtCardinality Cardinality { get; set; } = AasSmtQualifiers.SmtCardinality.One;
"SMT element are allowed in the actual collection (hierarchy level of the Submodel). " +
"Note: This attribute is only valid for annotating SMEs, not CDs!")]
[ExtensionFlags("SKIPFORCD")]
public AasSmtQualifiers.SmtCardinality SmeCardinality { get; set; } = AasSmtQualifiers.SmtCardinality.One;

[ExtensionHintAttribute("Specifies an id of an equivalence class. " +
"Only ids in the range [A-Za-z0-9] are allowed. If multiple SMT elements feature the same equivalency " +
Expand Down Expand Up @@ -1631,7 +1713,7 @@ IEnumerable<ExtIdfReference> IAbstractStructureModel<ExtIdfReference>.DescendOnc
[ExtensionHintAttribute("\u00ab Experimental \u00bb Specifies a list of concepts, which are " +
"organized, hierarchically structured, within this concept. This does not impose a type-like " +
"semantic. A concept might be organized by multiple concepts.")]
public List<ExtIdfReference> Organizes { get; set; } = null;
public List<ExtIdfCardinalityReference> Organizes { get; set; } = null;

//
// Init
Expand All @@ -1653,18 +1735,26 @@ static SmtAttributeRecord()
}).ToArray();
}

public string CardinalityShort()
public static string CardinalityShort(SmtCardinality card)
{
if (CardinalitiesShort == null)
return "";
var i = ((int)this.Cardinality) % CardinalitiesShort.Length;
var i = ((int)card) % CardinalitiesShort.Length;
return CardinalitiesShort[i];
}

//
// Access
//

public IEnumerable<ExtIdfCardinalityReference> FindOrganizesForId(string id)
{
if (Organizes != null)
foreach (var org in Organizes)
if (org?.Value != null && org.Value == id)
yield return org;
}

public static bool ConceptSuitableForSubmodelCreate(SmtAttributeRecord smtRec)
{
// access
Expand Down Expand Up @@ -1700,6 +1790,7 @@ public static IEnumerable<DispEditHelperMiniModules.ConceptOrganizedChildItem>
yield return new ConceptOrganizedChildItem()
{
Cd = cd2,
Card = orgId.Cardinality,
SmtRec = smtRec2
};
}
Expand Down Expand Up @@ -1742,7 +1833,7 @@ public void JoinAttributes(SmtAttributeRecord other)
};

// apply
Cardinality = other.Cardinality;
SmeCardinality = other.SmeCardinality;
EitherOr = JoinStrings(EitherOr, other.EitherOr, "|");
InitialValue = OverStrings(InitialValue, other.InitialValue);
DefaultValue = OverStrings(DefaultValue, other.DefaultValue);
Expand All @@ -1766,7 +1857,7 @@ public void JoinAttributes(SmtAttributeRecord other)
if (other.Organizes != null && other.Organizes.Count > 0)
foreach (var oorg in other.Organizes)
{
Organizes = Organizes ?? new List<ExtIdfReference>();
Organizes = Organizes ?? new List<ExtIdfCardinalityReference>();
var found = false;
foreach (var org in Organizes)
if (org?.Value == oorg?.Value)
Expand Down Expand Up @@ -1949,7 +2040,9 @@ public List<SmtAttributeCheckItem> PerformAttributeCheck(Aas.IMultiLanguagePrope
/// Note: this function needs a lambda for looking up SMT attribute records
/// of subordinate elements either by Referable or SemanticId reference.
/// </summary>
public static List<SmtAttributeCheckItem> PerformAttributeCheck(List<Aas.ISubmodelElement> elems,
public static List<SmtAttributeCheckItem> PerformAttributeCheck(
Aas.IReferable parentRf,
List<Aas.ISubmodelElement> elems,
Func<Aas.IReferable, SmtAttributeRecord> lambdaLookupSmtRec,
List<SmtAttributeCheckItem> inList = null)
{
Expand All @@ -1958,6 +2051,9 @@ public static List<SmtAttributeCheckItem> PerformAttributeCheck(List<Aas.ISubmod
return inList;
var res = inList ?? new List<SmtAttributeCheckItem>();

// try to access attributes of the parent
var smtParent = lambdaLookupSmtRec?.Invoke(parentRf);

// make two dictionaries on these elements
// (to count elemens per semantic id and have SmtAttributes available)
var elemPerSemId = new MultiValueDictionary<string, Aas.ISubmodelElement>();
Expand Down Expand Up @@ -1985,13 +2081,19 @@ public static List<SmtAttributeCheckItem> PerformAttributeCheck(List<Aas.ISubmod
if (rec == null)
continue;

// cardinality
var card = rec.SmeCardinality;
var parentOrg = smtParent?.FindOrganizesForId(ssiKey)?.FirstOrDefault();
if (parentOrg != null)
card = parentOrg.Cardinality;

// check
var complain = "";
if (rec.Cardinality == SmtCardinality.One && els.Count != 1)
if (card == SmtCardinality.One && els.Count != 1)
complain = "[1]";
if (rec.Cardinality == SmtCardinality.OneToMany && els.Count < 1)
if (card == SmtCardinality.OneToMany && els.Count < 1)
complain = "[1..*]";
if (rec.Cardinality == SmtCardinality.ZeroToOne && els.Count > 1)
if (card == SmtCardinality.ZeroToOne && els.Count > 1)
complain = "[0..1]";

// give out
Expand Down Expand Up @@ -2105,9 +2207,27 @@ public static bool TakeoverSmOrganizeToCds(
if (already)
continue;

// try identify cardinality
var card = SmtCardinality.One;
var smeFromDictKey = dict[dictKey].FirstOrDefault() as Aas.ISubmodelElement;

// access cardinality of the SME by qualifier
var qf = smeFromDictKey?.FindQualifierOfAnyType(new[] {
"SMT/Cardinality", "Cardinality", "Multiplicity" })?.FirstOrDefault();
if (qf?.Value != null)
card = (SmtCardinality) EnumHelper.GetEnumMemberFromValueString<SmtCardinality>(
qf.Value, valElse: SmtCardinality.One);

// access cardinality of the SME by SmtAttributeRec?
var smtRecFromSme = DispEditHelperExtensions
.CheckReferableForExtensionRecords<SmtAttributeRecord>(smeFromDictKey)?
.FirstOrDefault();
if (smtRecFromSme != null)
card = smtRecFromSme.SmeCardinality;

// without further ado, just put it in!
smtRec.Organizes = smtRec.Organizes ?? new List<ExtIdfReference>();
smtRec.Organizes.Add(new ExtIdfReference(dictKey));
smtRec.Organizes = smtRec.Organizes ?? new List<ExtIdfCardinalityReference>();
smtRec.Organizes.Add(new ExtIdfCardinalityReference(dictKey, card));
changes = true;
}

Expand Down
Loading

0 comments on commit 0172385

Please sign in to comment.