Hi
I have this model below, where I want to calculate the sum
of the costs of the tasks performed by a part.
package costRollUp{
private import ScalarValues::*;
action def Task{
attribute cost : Real default 0;
}
action t1 : Task{
attribute :>> cost = 5;
}
action t2 : Task{
attribute :>> cost = 7;
}
action t3 : Task{
attribute :>> cost = 10;
}
part p{
perform t1;
perform t2;
}
part costAnalysis{
attribute totalCost : Real = RealFunctions::sum((p.performedActions as Task).cost);
}
}
When running the code below, totalCost the result is 0 instead of 12:
costRollUp::Task::cost: 0
costRollUp::t1::cost: 5
costRollUp::t2::cost: 7
costRollUp::t3::cost: 10
costRollUp::costAnalysis::totalCost: 0
`def find_expression_attribute_values(element, syside_mod, level: int = 0) → None:
“”"
One expression per AttributeUsage — no duplicate lines.
Prefer feature.feature_value_expression (Sensmetry / rollups). If missing, use the CTO
rule: first owned child if it is an Expression (matches jl_sysmlv2_api).
"""
indent = " " * level
compiler = syside_mod.Compiler()
lib = syside_mod.Environment.get_default().lib
if hasattr(element, "try_cast") and element.try_cast(syside_mod.AttributeUsage):
attr = element.cast(syside_mod.AttributeUsage)
owner_scope = getattr(attr, "owner", attr)
expr = getattr(attr, "feature_value_expression", None) or getattr(
attr, "featureValueExpression", None
)
if expr is None:
try:
expression_a1 = next(iter(attr.owned_elements), None)
except Exception:
expression_a1 = None
if expression_a1 is not None and isinstance(
expression_a1, syside_mod.Expression
):
expr = expression_a1
if expr is not None and isinstance(expr, syside_mod.Expression):
try:
value, report = compiler.evaluate(
expr,
scope=owner_scope,
stdlib=lib,
experimental_quantities=True,
)
except TypeError:
value, report = compiler.evaluate(expr)
if not getattr(report, "fatal", False):
name = (
getattr(attr, "qualified_name", None)
or getattr(attr, "declared_name", None)
or getattr(attr, "name", None)
or "<unnamed>"
)
print(f"{indent}{name}: {value}")
try:
element.owned_elements.for_each(
lambda owned_element: find_expression_attribute_values(
owned_element, syside_mod, level + 1
)
)
except Exception:
try:
for owned_element in element.owned_elements:
find_expression_attribute_values(owned_element, syside_mod, level + 1)
except Exception:
pass
def run(model, syside_mod) → None:
attr_iter = None
if hasattr(model, “elements”) and callable(model.elements):
try:
attr_iter = model.elements(syside_mod.AttributeUsage) # type: ignore[arg-type]
except TypeError:
attr_iter = model.elements()
elif hasattr(model, “nodes”) and callable(model.nodes):
try:
attr_iter = model.nodes(syside_mod.AttributeUsage) # type: ignore[arg-type]
except TypeError:
attr_iter = model.nodes()
if attr_iter is None:
print(“Model exposes neither elements() nor nodes()”, file=sys.stderr)
return
for el in attr_iter:
try:
if hasattr(el, "try_cast") and el.try_cast(syside_mod.AttributeUsage):
find_expression_attribute_values(el, syside_mod)
except Exception:
pass`