11/* ****************************************************************************
22 * SysML 2 Pilot Implementation
33 * Copyright (c) 2018 IncQuery Labs Ltd.
4- * Copyright (c) 2018-2025 Model Driven Solutions, Inc.
4+ * Copyright (c) 2018-2026 Model Driven Solutions, Inc.
55 * Copyright (c) 2020 California Institute of Technology/Jet Propulsion Laboratory
66 *
77 * This program is free software: you can redistribute it and/or modify
@@ -103,6 +103,10 @@ import java.util.Collections
103103import java.util.HashMap
104104import java.util.Set
105105import java.util.Map
106+ import org.omg.sysml.lang.sysml.EndFeatureMembership
107+ import org.omg.sysml.lang.sysml.CollectExpression
108+ import org.omg.sysml.lang.sysml.SelectExpression
109+ import org.omg.sysml.lang.sysml.IndexExpression
106110
107111/**
108112 * This class contains custom validation rules.
@@ -160,6 +164,9 @@ class KerMLValidator extends AbstractKerMLValidator {
160164
161165 public static val INVALID_CLASSIFIER_MULTIPLICITY_DOMAIN = " validateClassifierMultiplicityDomain"
162166 public static val INVALID_CLASSIFIER_MULTIPLICITY_DOMAIN_MSG = " Multiplicity must not have a featuring type"
167+
168+ public static val INVALID_END_FEATURE_MEMBERSHIP_IS_END = " validateEndFeatureMembershpIsEnd"
169+ public static val INVALID_END_FEATURE_MEMBERSHIP_IS_END_MSG = " Must be an end feature"
163170
164171 // Note: validateFeatureHasType is not in the spec, but it is implied by semantic constraints on features.
165172 public static val INVALID_FEATURE_HAS_TYPE = ' validateFeatureHasType_'
@@ -264,6 +271,8 @@ class KerMLValidator extends AbstractKerMLValidator {
264271 public static val INVALID_BEHAVIOR_SPECIALIZATION = " validateBehaviorSpecialization"
265272 public static val INVALID_BEHAVIOR_SPECIALIZATION_MSG = " Cannot specialize structure"
266273
274+ public static val INVALID_PARAMETER_MEMBERSHIP_DIRECTION = " validateParameterMembershipDirection"
275+ public static val INVALID_PARAMETER_MEMBERSHIP_DIRECTION_MSG = " Must have direction '{direction}'"
267276 public static val INVALID_PARAMETER_MEMBERSHIP_OWNING_TYPE = " validateParameterMembershipOwningType"
268277 public static val INVALID_PARAMETER_MEMBERSHIP_OWNING_TYPE_MSG = " Parameter membership not allowed"
269278
@@ -319,9 +328,23 @@ class KerMLValidator extends AbstractKerMLValidator {
319328 public static val INVALID_OPERATOR_EXPRESSION_BRACKET_OPERATOR = " validateOperatorExpressionBracketOperator_"
320329 public static val INVALID_OPERATOR_EXPRESSION_BRACKET_OPERATOR_MSG = " Use #(...) for indexing"
321330
331+ public static val INVALID_COLLECT_EXPRESSION_OPERATOR = " validateCollectExpressionOperator"
332+ public static val INVALID_COLLECT_EXPRESSION_OPERATOR_MSG = " Operator must be 'collect'"
333+
334+ public static val INVALID_FEATURE_CHAIN_EXPRESSION_OPERATOR = " validateFeatureChainExpressionOperator"
335+ public static val INVALID_FEATURE_CHAIN_EXPRESSION_OPERATOR_MSG = " Operator must be '.'"
336+
337+ public static val INVALID_INDEX_EXPRESSION_OPERATOR = " validateIndexExpressionOperator"
338+ public static val INVALID_INDEX_EXPRESSION_OPERATOR_MSG = " Operator must be '#'"
339+
340+ public static val INVALID_SELECT_EXPRESSION_OPERATOR = " validateSelectExpressionOperator"
341+ public static val INVALID_SELECT_EXPRESSION_OPERATOR_MSG = " Operator must be 'select'"
342+
322343 public static val INVALID_FLOW_ITEM_FEATURE = " validateFlowItemFeature"
323344 public static val INVALID_FLOW_ITEM_FEATURE_MSG = " Only one item feature is allowed"
324345
346+ public static val INVALID_FLOW_END_IS_END = " validateFlowEndIsEnd"
347+ public static val INVALID_FLOW_END_IS_END_MSG = " Must be an end feature"
325348 public static val INVALID_FLOW_END_OWNING_TYPE = " validateFlowEndOwningType"
326349 public static val INVALID_FLOW_END_OWNING_TYPE_MSG = " Flow end not allowed"
327350 public static val INVALID_FLOW_END_NESTED_FEATURE = " validateFlowEndNestedFeature"
@@ -555,10 +578,14 @@ class KerMLValidator extends AbstractKerMLValidator {
555578 }
556579 }
557580
558- // @Check
559- // def checkEndFeatureMembership(EndFeatureMembership m) {
560- // // validateEndFeatureMembershipIsEnd is automatically satisfied
561- // }
581+ @Check
582+ def checkEndFeatureMembership (EndFeatureMembership m ) {
583+ // validateEndFeatureMembershipIsEnd
584+ var ownedMemberFeature = m. ownedMemberFeature
585+ if (ownedMemberFeature !== null && ! ownedMemberFeature. isEnd) {
586+ error(INVALID_END_FEATURE_MEMBERSHIP_IS_END_MSG , ownedMemberFeature, null , INVALID_END_FEATURE_MEMBERSHIP_IS_END )
587+ }
588+ }
562589
563590 @Check
564591 def checkFeature (Feature f ){
@@ -1026,9 +1053,12 @@ class KerMLValidator extends AbstractKerMLValidator {
10261053 ExpressionUtil . isConstructorResult(owningType))) {
10271054 error(INVALID_PARAMETER_MEMBERSHIP_OWNING_TYPE_MSG , m, SysMLPackage . eINSTANCE. parameterMembership_OwnedMemberParameter, INVALID_PARAMETER_MEMBERSHIP_OWNING_TYPE )
10281055 }
1029-
1030- // validateParameterMembershipParameterHasDirection is automatically satisfied
10311056 }
1057+ // validateParameterMembershipParameterDirection
1058+ var ownedMemberParameter = m. ownedMemberParameter
1059+ if (ownedMemberParameter !== null && ownedMemberParameter. direction != m. parameterDirection) {
1060+ error(INVALID_PARAMETER_MEMBERSHIP_DIRECTION_MSG . replace(" {direction}" , m. parameterDirection. toString. toLowerCase), ownedMemberParameter, null , INVALID_PARAMETER_MEMBERSHIP_DIRECTION )
1061+ }
10321062 }
10331063
10341064 @Check
@@ -1074,8 +1104,6 @@ class KerMLValidator extends AbstractKerMLValidator {
10741104 if (! (owningType instanceof Function || owningType instanceof Expression )) {
10751105 error(INVALID_RETURN_PARAMETER_MEMBERSHIP_OWNING_TYPE_MSG , m, SysMLPackage . eINSTANCE. parameterMembership_OwnedMemberParameter, INVALID_RETURN_PARAMETER_MEMBERSHIP_OWNING_TYPE )
10761106 }
1077-
1078- // validateReturnParameterMembershipParameterHasDirectionOut is automatically satisfied
10791107 }
10801108
10811109 @Check
@@ -1085,19 +1113,15 @@ class KerMLValidator extends AbstractKerMLValidator {
10851113 if (! (owningType instanceof Function || owningType instanceof Expression )) {
10861114 error(INVALID_RESULT_EXPRESSION_MEMBERSHIP_OWNING_TYPE_MSG , m, SysMLPackage . eINSTANCE. parameterMembership_OwnedMemberParameter, INVALID_RESULT_EXPRESSION_MEMBERSHIP_OWNING_TYPE )
10871115 }
1088-
1089- // validateReturnParameterMembershipParameterHasDirectionOut is automatically satisfied
10901116 }
10911117
1092- // @Check
1093- // def checkReturnParameterMembership(ReturnParameterMembership m) {
1094- // // validateReturnParameterMembershipParameterHasDirection is automatically satisfied
1095- // }
1096-
1097- // @Check
1098- // def checkCollectExpression(CollectExpression e) {
1099- // // validateCollectExpressionOperator is automatically satisfied
1100- // }
1118+ @Check
1119+ def checkCollectExpression (CollectExpression e ) {
1120+ // validateCollectExpressionOperator
1121+ if (e. operator != " collect" ) {
1122+ error(INVALID_COLLECT_EXPRESSION_OPERATOR_MSG , e, null , INVALID_COLLECT_EXPRESSION_OPERATOR );
1123+ }
1124+ }
11011125
11021126 @Check
11031127 def checkFeatureChainExpression (FeatureChainExpression e ) {
@@ -1112,7 +1136,10 @@ class KerMLValidator extends AbstractKerMLValidator {
11121136 error(INVALID_FEATURE_CHAIN_EXPRESSION_FEATURE_CONFORMANCE_MSG , e. ownedMembership. get(1 ), SysMLPackage . eINSTANCE. membership_MemberElement, INVALID_FEATURE_CHAIN_EXPRESSION_FEATURE_CONFORMANCE )
11131137 }
11141138
1115- // validateFeatureChainExpressionOperator is automatically satisfied
1139+ // validateFeatureChainExpressionOperator
1140+ if (e. operator != " ." ) {
1141+ error(INVALID_FEATURE_CHAIN_EXPRESSION_OPERATOR_MSG , e, null , INVALID_FEATURE_CHAIN_EXPRESSION_OPERATOR );
1142+ }
11161143 }
11171144
11181145 @Check
@@ -1235,15 +1262,21 @@ class KerMLValidator extends AbstractKerMLValidator {
12351262 }
12361263 }
12371264
1238- // @Check
1239- // def checkSelectExpression(SelectExpression e) {
1240- // // validateSelectExpressionOperator is automatically satisfied
1241- // }
1242-
1243- // @Check
1244- // def checkIndexExpression(IndexExpression e) {
1245- // // validateIndexExpressionOperator is automatically satisfied
1246- // }
1265+ @Check
1266+ def checkSelectExpression (SelectExpression e ) {
1267+ // validateSelectExpressionOperator
1268+ if (e. operator != " select" ) {
1269+ error(INVALID_SELECT_EXPRESSION_OPERATOR_MSG , e, null , INVALID_SELECT_EXPRESSION_OPERATOR );
1270+ }
1271+ }
1272+
1273+ @Check
1274+ def checkIndexExpression (IndexExpression e ) {
1275+ // validateIndexExpressionOperator
1276+ if (e. operator != " #" ) {
1277+ error(INVALID_INDEX_EXPRESSION_OPERATOR_MSG , e, null , INVALID_INDEX_EXPRESSION_OPERATOR );
1278+ }
1279+ }
12471280
12481281 @Check
12491282 def checkFlow (Flow flow ) {
@@ -1254,7 +1287,10 @@ class KerMLValidator extends AbstractKerMLValidator {
12541287
12551288 @Check
12561289 def checkFlowEnd (FlowEnd flowEnd ) {
1257- // validateFlowEndIsEnd is automatically satisfied
1290+ // validateFlowEndIsEnd
1291+ if (! flowEnd. isEnd) {
1292+ error(INVALID_FLOW_END_IS_END_MSG , flowEnd, null , INVALID_FLOW_END_IS_END )
1293+ }
12581294
12591295 // validateFlowEndNestedFeature
12601296 if (flowEnd. ownedFeature. size != 1 ) {
0 commit comments