2222import dev .ikm .tinkar .common .service .PrimitiveDataSearchResult ;
2323import dev .ikm .tinkar .common .util .functional .QuadConsumer ;
2424import dev .ikm .tinkar .common .util .functional .TriConsumer ;
25+ import dev .ikm .tinkar .common .util .uuid .UuidT5Generator ;
2526import dev .ikm .tinkar .component .ConceptVersion ;
2627import dev .ikm .tinkar .coordinate .Coordinates ;
2728import dev .ikm .tinkar .coordinate .navigation .calculator .NavigationCalculator ;
3536import dev .ikm .tinkar .entity .graph .DiTreeVersion ;
3637import dev .ikm .tinkar .entity .graph .VersionVertex ;
3738import dev .ikm .tinkar .terms .ConceptFacade ;
39+ import dev .ikm .tinkar .terms .DefaultsTemplateTerm ;
3840import dev .ikm .tinkar .terms .EntityFacade ;
3941import dev .ikm .tinkar .terms .PatternFacade ;
4042import org .eclipse .collections .api .factory .Lists ;
5052import java .util .Objects ;
5153import java .util .Optional ;
5254import java .util .OptionalInt ;
55+ import java .util .UUID ;
5356import java .util .concurrent .atomic .AtomicInteger ;
5457import java .util .function .BiConsumer ;
5558import java .util .stream .Stream ;
5659
5760import static dev .ikm .tinkar .terms .TinkarTerm .STAMP_PATTERN ;
5861
62+ /**
63+ * Computes latest versions of components at a stamp coordinate's position.
64+ *
65+ * <h2>Defaults/template exclusion</h2>
66+ * Default value semantics and template semantics (IKE-Network/ike-issues#886) live in
67+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} — every version of a
68+ * defaults/template chronology is in that module, and that module holds only
69+ * defaults/template content. Version-iteration operations (the
70+ * {@code streamLatestVersionForPattern} and {@code forEachSemanticVersion*} family)
71+ * exclude versions stamped in that module, so defaults and templates never surface as
72+ * ordinary pattern or component content. Chronology-level and nid-level surfaces are
73+ * unchanged (store truth): chronology enumeration still returns defaults/template nids,
74+ * and {@link #latest(int)} on such a nid still resolves. The dedicated accessors —
75+ * {@link #getDefault(PatternFacade)}, {@link #getTemplate(ConceptFacade)} — include the
76+ * module and resolve by computed identity.
77+ */
5978public interface StampCalculator {
6079 Logger LOG = LoggerFactory .getLogger (StampCalculator .class );
80+
81+ /**
82+ * Streams the latest version of each semantic of the given pattern at this
83+ * calculator's position — a version-iteration operation: versions stamped in
84+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} are excluded, so a
85+ * defaults/template semantic of the pattern contributes an empty {@link Latest}.
86+ *
87+ * @param patternFacade the pattern whose semantics to stream
88+ * @return one {@link Latest} per semantic chronology of the pattern; empty entries
89+ * for semantics with no reachable, allowed-state, non-defaults version
90+ */
6191 default Stream <Latest <SemanticEntityVersion >> streamLatestVersionForPattern (PatternFacade patternFacade ) {
6292 return streamLatestVersionForPattern (patternFacade .nid ());
6393 }
@@ -110,7 +140,17 @@ static RelativePosition getRelativePositionTimeOnly(int stampNid1, int stampNid2
110140 StampCoordinate stampCoordinate ();
111141
112142
113- Stream <Latest <SemanticEntityVersion >> streamLatestVersionForPattern (int patternNid );
143+ /**
144+ * Streams the latest version of each semantic of the given pattern at this
145+ * calculator's position — a version-iteration operation: versions stamped in
146+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} are excluded, so a
147+ * defaults/template semantic of the pattern contributes an empty {@link Latest}.
148+ *
149+ * @param patternNid the nid of the pattern whose semantics to stream
150+ * @return one {@link Latest} per semantic chronology of the pattern; empty entries
151+ * for semantics with no reachable, allowed-state, non-defaults version
152+ */
153+ Stream <Latest <SemanticEntityVersion >> streamLatestVersionForPattern (int patternNid );
114154
115155 default Stream <SemanticEntityVersion > streamLatestActiveVersionForPattern (PatternFacade patternFacade ) {
116156 return streamLatestActiveVersionForPattern (patternFacade .nid ());
@@ -266,17 +306,54 @@ default void forEachSemanticVersionOfPattern(PatternFacade patternFacade,
266306
267307 }
268308
309+ /**
310+ * Applies the procedure to the latest version of each semantic of the given pattern
311+ * at this calculator's position — a version-iteration operation: versions stamped in
312+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} are excluded, so
313+ * defaults/template semantics of the pattern are never presented.
314+ *
315+ * @param patternNid the nid of the pattern whose semantics to iterate
316+ * @param procedure receives each latest semantic version with the pattern's latest version
317+ */
269318 void forEachSemanticVersionOfPattern (int patternNid , BiConsumer <SemanticEntityVersion , PatternEntityVersion > procedure );
270319
320+ /**
321+ * Parallel form of {@link #forEachSemanticVersionOfPattern(int, BiConsumer)} — the
322+ * same version-iteration contract, including the exclusion of versions stamped in
323+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE}.
324+ *
325+ * @param patternNid the nid of the pattern whose semantics to iterate
326+ * @param procedure receives each latest semantic version with the pattern's latest version
327+ */
271328 void forEachSemanticVersionOfPatternParallel (int patternNid , BiConsumer <SemanticEntityVersion , PatternEntityVersion > procedure );
272329
330+ /**
331+ * Parallel form of {@link #forEachSemanticVersionOfPattern(int, BiConsumer)}
332+ * restricted to the given semantic nids — the same version-iteration contract,
333+ * including the exclusion of versions stamped in
334+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE}.
335+ *
336+ * @param semanticNidSet the semantic nids to consider
337+ * @param patternNid the nid of the pattern whose semantics to iterate
338+ * @param procedure receives each latest semantic version with the pattern's latest version
339+ */
273340 void forEachSemanticVersionInSetOfPatternParallel (ImmutableIntSet semanticNidSet , int patternNid , BiConsumer <SemanticEntityVersion , PatternEntityVersion > procedure );
274341
275342 default void forEachSemanticVersionForComponent (EntityFacade component ,
276343 BiConsumer <SemanticEntityVersion , EntityVersion > procedure ) {
277344 forEachSemanticVersionForComponent (component .nid (), procedure );
278345 }
279346
347+ /**
348+ * Applies the procedure to the latest version of each semantic referencing the given
349+ * component at this calculator's position — a version-iteration operation: versions
350+ * stamped in {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} are
351+ * excluded, so defaults/template semantics attached to the component are never
352+ * presented.
353+ *
354+ * @param componentNid the nid of the referenced component
355+ * @param procedure receives each latest semantic version with the component's latest version
356+ */
280357 void forEachSemanticVersionForComponent (int componentNid ,
281358 BiConsumer <SemanticEntityVersion , EntityVersion > procedure );
282359
@@ -286,6 +363,18 @@ default void forEachSemanticVersionForComponentOfPattern(EntityFacade component,
286363 forEachSemanticVersionForComponentOfPattern (component .nid (), patternFacade .nid (), procedure );
287364 }
288365
366+ /**
367+ * Applies the procedure to the latest version of each semantic of the given pattern
368+ * referencing the given component at this calculator's position — a
369+ * version-iteration operation: versions stamped in
370+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE} are excluded, so
371+ * defaults/template semantics are never presented.
372+ *
373+ * @param componentNid the nid of the referenced component
374+ * @param patternNid the nid of the pattern whose semantics to iterate
375+ * @param procedure receives each latest semantic version with the component's and
376+ * pattern's latest versions
377+ */
289378 void forEachSemanticVersionForComponentOfPattern (int componentNid , int patternNid , TriConsumer <SemanticEntityVersion , EntityVersion , PatternEntityVersion > procedure );
290379
291380 default void forEachSemanticVersionWithFieldsOfPattern (PatternFacade patternFacade ,
@@ -337,7 +426,125 @@ default Latest<SemanticEntityVersion> latestSemanticVersion(SemanticEntity<?> se
337426 return (Latest <SemanticEntityVersion >) latest (semanticEntity );
338427 }
339428
429+ /**
430+ * Resolves the default value semantic of the given pattern at this calculator's
431+ * position: the semantic of {@code pattern} whose referenced component is
432+ * {@link DefaultsTemplateTerm#DEFAULT_VALUE_CONCEPT}, located by its computed
433+ * identity — {@link UuidT5Generator#singleSemanticUuid(PublicId, PublicId)} of the
434+ * pattern's public id and the defaults attachment concept's public id — never by
435+ * iteration.
436+ * <p>
437+ * Unlike the version-iteration operations, which exclude every version stamped in
438+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE}, this accessor includes
439+ * that module. Resolution is the ordinary path calculus at the caller's position, so
440+ * preference is per-path: a default authored on the caller's path overrides one
441+ * inherited through the path's origins, and a retirement (an inactive version in the
442+ * same module) is honored with no resurrection of earlier active versions.
443+ *
444+ * @param pattern the pattern whose default value semantic to resolve
445+ * @return the latest version of the pattern's default value semantic at this
446+ * calculator's position; empty if none exists, none is reachable, or the
447+ * latest reachable version's state is not an allowed state
448+ */
449+ default Latest <SemanticEntityVersion > getDefault (PatternFacade pattern ) {
450+ return latest (defaultsSemanticNid (pattern , DefaultsTemplateTerm .DEFAULT_VALUE_CONCEPT ));
451+ }
452+
453+ /**
454+ * Resolves the template semantic for the given purpose concept at this calculator's
455+ * position: the semantic whose referenced component is {@code purposeConcept} and
456+ * whose identity is the computed template identity
457+ * ({@link UuidT5Generator#singleSemanticUuid(PublicId, PublicId)} of its own
458+ * pattern's public id and the purpose concept's public id). Candidate semantics
459+ * attached to the purpose concept are enumerated at the chronology level (store
460+ * truth), and only the one carrying its computed identity is a template — other
461+ * attachments (descriptions, axioms) never match.
462+ * <p>
463+ * Unlike the version-iteration operations, which exclude every version stamped in
464+ * {@link DefaultsTemplateTerm#DEFAULTS_AND_TEMPLATES_MODULE}, this accessor includes
465+ * that module, and resolves per-path preference through the ordinary path calculus
466+ * at the caller's position.
467+ *
468+ * @param purposeConcept the template purpose concept — a child of
469+ * {@link DefaultsTemplateTerm#TEMPLATE_CONCEPT}
470+ * @return the latest version of the purpose's template semantic at this calculator's
471+ * position; empty if no template exists, none is reachable, or the latest
472+ * reachable version's state is not an allowed state
473+ * @throws IllegalStateException if more than one pattern declares a template for the
474+ * purpose concept — disambiguate with
475+ * {@link #getTemplate(PatternFacade, ConceptFacade)}
476+ */
477+ default Latest <SemanticEntityVersion > getTemplate (ConceptFacade purposeConcept ) {
478+ int templateNid = 0 ;
479+ for (int candidateNid : PrimitiveData .get ().semanticNidsForComponent (purposeConcept .nid ())) {
480+ EntityHandle handle = EntityHandle .get (candidateNid );
481+ if (!handle .isPresent () || !handle .isSemantic ()) {
482+ continue ;
483+ }
484+ SemanticEntity <?> candidate = handle .expectSemantic ();
485+ UUID expectedIdentity = UuidT5Generator .singleSemanticUuid (
486+ PrimitiveData .publicId (candidate .patternNid ()), purposeConcept .publicId ());
487+ boolean identityMatches = false ;
488+ for (UUID candidateUuid : candidate .publicId ().asUuidArray ()) {
489+ if (candidateUuid .equals (expectedIdentity )) {
490+ identityMatches = true ;
491+ break ;
492+ }
493+ }
494+ if (!identityMatches ) {
495+ continue ;
496+ }
497+ if (templateNid != 0 ) {
498+ throw new IllegalStateException (
499+ "More than one pattern declares a template for purpose " + purposeConcept
500+ + " — resolve with getTemplate(pattern, purposeConcept)" );
501+ }
502+ templateNid = candidateNid ;
503+ }
504+ if (templateNid == 0 ) {
505+ return Latest .empty ();
506+ }
507+ return latest (templateNid );
508+ }
509+
510+ /**
511+ * Resolves the template semantic of the given pattern for the given purpose concept
512+ * at this calculator's position, directly by computed identity —
513+ * {@link UuidT5Generator#singleSemanticUuid(PublicId, PublicId)} of the pattern's
514+ * public id and the purpose concept's public id. The pattern-free form
515+ * ({@link #getTemplate(ConceptFacade)}) resolves the same semantic by verifying
516+ * computed identity over the purpose concept's attachments; this form is exact when
517+ * the pattern is known.
518+ *
519+ * @param pattern the pattern whose template semantic to resolve
520+ * @param purposeConcept the template purpose concept — a child of
521+ * {@link DefaultsTemplateTerm#TEMPLATE_CONCEPT}
522+ * @return the latest version of the template semantic at this calculator's position;
523+ * empty if none exists, none is reachable, or the latest reachable version's
524+ * state is not an allowed state
525+ */
526+ default Latest <SemanticEntityVersion > getTemplate (PatternFacade pattern , ConceptFacade purposeConcept ) {
527+ return latest (defaultsSemanticNid (pattern , purposeConcept ));
528+ }
340529
530+ /**
531+ * Computes the nid of a defaults/template semantic from its computed identity:
532+ * {@link UuidT5Generator#singleSemanticUuid(PublicId, PublicId)} of the pattern's
533+ * public id and the attachment concept's public id, minted pattern-scoped exactly as
534+ * the writing side mints it, so reader and writer resolve the same nid whether or
535+ * not the semantic exists yet.
536+ *
537+ * @param pattern the semantic's pattern
538+ * @param attachmentConcept the semantic's referenced component — the defaults
539+ * attachment concept, or a template purpose concept
540+ * @return the nid of the computed identity (minted if not yet present)
541+ */
542+ private static int defaultsSemanticNid (PatternFacade pattern , EntityFacade attachmentConcept ) {
543+ UUID semanticUuid = UuidT5Generator .singleSemanticUuid (
544+ pattern .publicId (), attachmentConcept .publicId ());
545+ return ScopedValue .where (PrimitiveData .SCOPED_PATTERN_PUBLICID_FOR_NID , pattern .publicId ())
546+ .call (() -> PrimitiveData .nid (semanticUuid ));
547+ }
341548
342549 OptionalInt getIndexForMeaning (int patternNid , int meaningNid );
343550
0 commit comments