1
+ import { blueprint , rdf , rdfs } from "@blueprint/ontology" ;
2
+ import { ICompositionToNodeLink } from "../../model/composition/composition-to-node-link" ;
3
+ import { CompositionToNodeQueryStrategy } from "./composition-to-node-query-strategy" ;
4
+
5
+ /**
6
+ * CompositionToNodeRootStrategy
7
+ * The subject class is the root of the source composition. That means we are on top of the Hierarchy and we link to
8
+ * the target node.
9
+ */
10
+ export class CompositionToNodeRootStrategy extends CompositionToNodeQueryStrategy {
11
+ filter ( links : ICompositionToNodeLink [ ] , classIris : string [ ] ) : ICompositionToNodeLink [ ] {
12
+ return links . filter ( link => {
13
+ const sourceComposition = link . sourceComposition ;
14
+ if ( sourceComposition === null ) {
15
+ return false ;
16
+ }
17
+ const root = sourceComposition . aggregateNodes . find ( memberNode => memberNode . iri === sourceComposition . rootIri ) ;
18
+ return classIris . includes ( root ?. targetClassIri ) ;
19
+ } ) ;
20
+ }
21
+
22
+ createQuery ( link : ICompositionToNodeLink , subject : string ) : string [ ] {
23
+ console . log ( '%cCompositionToNodeRootStrategy query' , 'color: red' , link . label ) ;
24
+ return this . #createQueryForRootOfSourceAggregate( link , subject ) ;
25
+ }
26
+
27
+ #createQueryForRootOfSourceAggregate( link : ICompositionToNodeLink , subject : string ) : string [ ] {
28
+ const linkTargetNodeClass = link . targetNodeIri ;
29
+ const linkSourceComposition = link . sourceComposition ;
30
+
31
+ if ( linkSourceComposition === null ) {
32
+ console . warn ( 'No source composition' ) ;
33
+ return [ ] ;
34
+ }
35
+ const q = link . path . flatMap ( pathFromLink => {
36
+ const firstPathElement = pathFromLink [ 0 ] ;
37
+
38
+ const connectionPoints = linkSourceComposition . connectionPoints . filter ( connectorNode => connectorNode . targetClassIri === firstPathElement . sourceClassIri ) ;
39
+ if ( connectionPoints . length === 0 ) {
40
+ console . warn ( 'No connection points' ) ;
41
+ return [ ] ;
42
+ }
43
+
44
+ // the subject is the root node of the source of the link -> all links are from this to the targetNode
45
+ // that means we are always source of the link
46
+ const lastPathElement = pathFromLink [ pathFromLink . length - 1 ] ;
47
+ if ( lastPathElement . targetClassIri !== linkTargetNodeClass ) {
48
+ console . warn ( `Last path element is not the target class for link <${ link . iri } >. This is a configuration error.` ) ;
49
+ return [ ] ;
50
+ }
51
+
52
+ const sourceConnectors = connectionPoints . filter ( connectorNode => connectorNode . targetClassIri === firstPathElement . sourceClassIri ) ;
53
+ if ( sourceConnectors . length === 0 ) {
54
+ console . warn ( `No connector class <${ firstPathElement . sourceClassIri } > for link <${ link . iri } >. This is a configuration error.` ) ;
55
+ return [ ] ;
56
+ }
57
+
58
+ const queries = sourceConnectors . flatMap ( ( connectionPoint , outerIndex ) => {
59
+ const pathFromRoot = connectionPoint . pathFromRoot ;
60
+ const linkPath = pathFromLink ;
61
+ const path = [ ...pathFromRoot , ...linkPath ] ;
62
+
63
+ const body = path . map ( ( pathElement , index ) => {
64
+ if ( index === pathFromRoot . length - 1 && pathFromRoot . length != 0 ) {
65
+ if ( index === 0 ) {
66
+ return `
67
+ <${ subject } > a <${ pathElement . sourceClassIri } > .
68
+ <${ subject } > ${ pathElement . path } ?element_${ outerIndex } _${ index + 1 } .
69
+ VALUES ?connectionPointP {
70
+ ${ rdfs . labelPrefixed }
71
+ ${ rdf . typePrefixed }
72
+ }
73
+ ?element_${ outerIndex } _${ index + 1 } ?connectionPointP ?connectionPointO .
74
+ ?element_${ outerIndex } _${ index + 1 } a <${ pathElement . targetClassIri } > .
75
+ ` ;
76
+ } else {
77
+ return `
78
+ ?element_${ outerIndex } _${ index } ${ pathElement . path } ?element_${ outerIndex } _${ index + 1 } .
79
+ ?element_${ outerIndex } _${ index + 1 } a <${ pathElement . targetClassIri } > .
80
+ VALUES ?connectionPointP {
81
+ ${ rdfs . labelPrefixed }
82
+ ${ rdf . typePrefixed }
83
+ }
84
+ ?element_${ outerIndex } _${ index + 1 } ?connectionPointP ?connectionPointO .
85
+ ` ;
86
+ }
87
+ }
88
+
89
+ if ( index === 0 ) {
90
+ if ( pathFromRoot . length === 0 ) {
91
+ return `
92
+ # first path element - form link
93
+ <${ subject } > a <${ pathElement . sourceClassIri } > .
94
+ <${ subject } > ${ pathElement . path } ?result .
95
+ ?result a <${ pathElement . targetClassIri } > .
96
+
97
+ VALUES ?resultP {
98
+ ${ rdf . typePrefixed }
99
+ ${ rdfs . labelPrefixed }
100
+ }
101
+ ?result ?resultP ?resultO .
102
+ BIND(?result as ?connectionPointO)
103
+ BIND(?result as ?element_0_0)
104
+
105
+ ` ;
106
+ }
107
+ return `
108
+ <${ subject } > a <${ pathElement . sourceClassIri } > .
109
+ <${ subject } > ${ pathElement . path } ?element_${ outerIndex } _${ index + 1 } .
110
+ ?element_${ outerIndex } _${ index + 1 } a <${ pathElement . targetClassIri } > .
111
+ ` ;
112
+ }
113
+ if ( index === path . length - 1 ) {
114
+ return `
115
+ ?element_${ outerIndex } _${ index } ${ pathElement . path } ?result .
116
+ ?result a <${ pathElement . targetClassIri } > .
117
+
118
+ VALUES ?resultP {
119
+ ${ rdf . typePrefixed }
120
+ ${ rdfs . labelPrefixed }
121
+ }
122
+ ?result ?resultP ?resultO .
123
+ ` ;
124
+ }
125
+ return `
126
+ ?element_${ outerIndex } _${ index } ${ pathElement . path } ?element_${ outerIndex } _${ index + 1 } .
127
+ ?element_${ outerIndex } _${ index + 1 } a <${ pathElement . targetClassIri } > .
128
+ ` ;
129
+ } ) . join ( '\n' ) ;
130
+
131
+
132
+ const query = `
133
+ ${ rdf . sparqlPrefix ( ) }
134
+ ${ rdfs . sparqlPrefix ( ) }
135
+ ${ blueprint . sparqlPrefix ( ) }
136
+
137
+ CONSTRUCT {
138
+ <${ link . iri } > ${ blueprint . resultPrefixed } <${ link . iri } /${ outerIndex } > .
139
+ <${ link . iri } /${ outerIndex } > a ${ blueprint . CompositionLinkResultPrefixed } .
140
+ <${ link . iri } /${ outerIndex } > ${ blueprint . resultPrefixed } ?result .
141
+ <${ link . iri } /${ outerIndex } > ${ rdfs . labelPrefixed } "${ link . label } " .
142
+ ?result ?resultP ?resultO .
143
+ ?element_${ outerIndex } _${ pathFromRoot . length } ?connectionPointP ?connectionPointO .
144
+ ?result ${ blueprint . sourcePrefixed } ?element_${ outerIndex } _${ pathFromRoot . length } .
145
+ } WHERE {
146
+ ${ body }
147
+ }` ;
148
+ return query ;
149
+ } ) ;
150
+ return queries ;
151
+ } ) ;
152
+ return q ;
153
+ }
154
+ }
0 commit comments