11/*****************************************************************************
22 * SysML 2 Pilot Implementation, PlantUML Visualization
3- * Copyright (c) 2020-2024 Mgnite Inc.
3+ * Copyright (c) 2020-2026 Mgnite Inc.
44 * Copyright (c) 2022 Model Driven Solutions, Inc.
55 *
66 * This program is free software: you can redistribute it and/or modify
@@ -327,29 +327,38 @@ public PCTerminal(PC prev) {
327327
328328 // Make an InheritKey for ref, which is either a connector end or FeatureReferenceExpression or FeatureChainExpression.
329329 // These are (indirectly) owned by the innermost feature, which effectively determines the target scope.
330- private InheritKey makeInheritKeyForReferer (PC pc ) {
330+ private RefPC makeRefPCForReferer (PC pc ) {
331331 if (pc == null ) return null ;
332332 Element e = pc .getTarget ();
333333 if (!(e instanceof Feature )) return null ;
334334 Feature ref = (Feature ) e ;
335335
336- Namespace ns = getCurrentNamespace ();
336+ Namespace ns = getCurrentNamespace (); // the namespace owning a connector
337337 if (!(ns instanceof Type )) return null ;
338338
339339 if (ns instanceof Feature ) {
340- Feature tgt = (Feature ) ns ;
341- InheritKey ik = makeInheritKey (tgt );
340+ // Feature tgt = (Feature) ns;
341+ InheritKey ik = makeInheritKey (ref );
342342 if (ik != null ) {
343343 // Make the inherit key indirect in order to refer to redefined targets as well as inherited ones.
344344 ik = InheritKey .makeIndirect (ik );
345- ik = InheritKey .findTop (ik , ref );
346- if (ik != null ) return ik ;
345+ InheritKey ik2 = InheritKey .findTop (ik , ref );
346+ if (ik2 != null ) {
347+ // This is overspecifying case.
348+ return createRefPC (ik2 , pc );
349+ }
350+ // This is underspecifying case and we need to add a PCNamespace to capture ns/tgt
351+ PCNamespace pcn = new PCNamespace (ns , pc );
352+ return createRefPC (ik , pcn );
347353 }
348354 }
349355
350356 // In case that tgt inherits ref, we need to make an InheritKey for tgt.
351- Type tgt = (Type ) ns ;
352- return InheritKey .makeTargetKey (tgt , ref );
357+ {
358+ Type tgt = (Type ) ns ;
359+ InheritKey ik = InheritKey .makeTargetKey (tgt , ref );
360+ return createRefPC (ik , pc );
361+ }
353362 }
354363
355364
@@ -359,27 +368,36 @@ private InheritKey makeInheritKeyForReferer(PC pc) {
359368 iff : Feature :>> ioTarget: ReferenceUsage;
360369 }
361370 */
371+
372+ private static Feature getRootRedefinedFeature (Feature f ) {
373+ for (Redefinition rd : f .getOwnedRedefinition ()) {
374+ Feature rf = rd .getRedefinedFeature ();
375+ Feature rrf = getRootRedefinedFeature (rf );
376+ if (rrf == null ) return rf ;
377+ return rrf ;
378+ }
379+ return null ;
380+ }
381+
362382 private static Feature getIOTarget (FlowEnd ife ) {
363383 for (FeatureMembership fm : toOwnedFeatureMembershipArray (ife )) {
364384 Feature f = fm .getOwnedMemberFeature ();
365- for (Redefinition rd : f .getOwnedRedefinition ()) {
366- return rd .getRedefinedFeature ();
367- }
385+ return getRootRedefinedFeature (f );
368386 }
369387 return null ;
370388 }
371389
372- private class PCItemFlowEnd extends PC {
390+ private class PCFlowEnd extends PC {
373391 private final Feature ioTarget ;
374392 private final PC basePC ;
375393
376- public PCItemFlowEnd (FlowEnd ife , PC basePC , Feature ioTarget ) {
394+ public PCFlowEnd (FlowEnd ife , PC basePC , Feature ioTarget ) {
377395 super (ife , false );
378396 this .basePC = basePC ;
379397 this .ioTarget = ioTarget ;
380398 }
381399
382- private PCItemFlowEnd ( PCItemFlowEnd prev , PC basePC ) {
400+ private PCFlowEnd ( PCFlowEnd prev , PC basePC ) {
383401 super (prev );
384402 this .basePC = basePC ;
385403 this .ioTarget = prev .ioTarget ;
@@ -406,12 +424,12 @@ protected PC getNext() {
406424 if (basePC == null ) return new PCTerminal (this );
407425 PC ret = basePC .getNext ();
408426 if (!ret .isTerminal ()) {
409- return new PCItemFlowEnd (this , ret );
427+ return new PCFlowEnd (this , ret );
410428 }
411429 if (ioTarget == null ) {
412430 return new PCTerminal (this );
413431 } else {
414- return new PCItemFlowEnd (this , null );
432+ return new PCFlowEnd (this , null );
415433 }
416434 }
417435 }
@@ -447,6 +465,37 @@ protected Element getTarget() {
447465 }
448466 }
449467
468+ private class PCNamespace extends PC {
469+ public final Namespace ns ;
470+ private final PC pc ;
471+
472+ @ Override
473+ protected PC getNext () {
474+ return pc ;
475+ }
476+
477+ @ Override
478+ public PC enter (Namespace ns ) {
479+ if (ns .equals (this .ns )) {
480+ return pc ;
481+ } else {
482+ return this ;
483+ }
484+ }
485+
486+ public PCNamespace (Namespace ns , PC pc ) {
487+ super ((Element ) null , true );
488+ this .ns = ns ;
489+ this .pc = pc ;
490+ pc .setPrev (this );
491+ }
492+
493+ @ Override
494+ protected Element getTarget () {
495+ return null ;
496+ }
497+ }
498+
450499 private class RefPC {
451500 private PC pc ;
452501 private final InheritKey ik ;
@@ -542,37 +591,33 @@ private String addContextForFeature(Feature f, boolean isRedefinition) {
542591
543592 private String addContextForEnd (Feature f ) {
544593 if (f instanceof FlowEnd ) {
545- return addContextForItemFlowEnd ((FlowEnd ) f );
594+ return addContextForFlowEnd ((FlowEnd ) f );
546595 }
547596 PC pc = makeEndFeaturePC (f );
548- InheritKey ik = makeInheritKeyForReferer (pc );
549- if (createRefPC (ik , pc ) == null ) return null ;
597+ if (makeRefPCForReferer (pc ) == null ) return null ;
550598 return "" ;
551599 }
552600
553- private String addContextForItemFlowEnd (FlowEnd ife ) {
601+ private String addContextForFlowEnd (FlowEnd ife ) {
554602 PC pc = makeEndFeaturePC (ife );
555603 if (pc == null ) return null ;
556604 Feature ioTarget = getIOTarget (ife );
557- pc = new PCItemFlowEnd (ife , pc , ioTarget );
558- InheritKey ik = makeInheritKeyForReferer (pc );
559- if (createRefPC (ik , pc ) == null ) return null ;
605+ pc = new PCFlowEnd (ife , pc , ioTarget );
606+ if (makeRefPCForReferer (pc ) == null ) return null ;
560607 return "" ;
561608 }
562609
563610 private String addContextForFeatureChainExpression (FeatureChainExpression fce ) {
564611 PC pc = new PCFeatureChainExpression (fce );
565- InheritKey ik = makeInheritKeyForReferer (pc );
566- createRefPC (ik , pc );
612+ makeRefPCForReferer (pc );
567613 return "" ;
568614 }
569615
570616 private String addContextForFeatureReferenceExpression (FeatureReferenceExpression fre ) {
571617 Feature f = fre .getReferent ();
572618 if (f == null ) return "" ;
573619 PC pc = new PCFeature (fre , f , false );
574- InheritKey ik = makeInheritKeyForReferer (pc );
575- createRefPC (ik , pc );
620+ makeRefPCForReferer (pc );
576621 return "" ;
577622 }
578623
@@ -666,7 +711,7 @@ public String caseFeatureReferenceExpression(FeatureReferenceExpression fre) {
666711
667712 @ Override
668713 public String caseFlowEnd (FlowEnd ife ) {
669- return addContextForItemFlowEnd (ife );
714+ return addContextForFlowEnd (ife );
670715 }
671716
672717 @ Override
0 commit comments