Mercurial > hg > ng2-query-ismi
annotate src/app/query.service.ts @ 62:7787ca310644 webpack tip
update @angular to 4.4.5.
| author | Robert Casties <casties@mpiwg-berlin.mpg.de> |
|---|---|
| date | Wed, 18 Oct 2017 17:46:41 +0200 |
| parents | 7b9d616695d3 |
| children |
| rev | line source |
|---|---|
| 45 | 1 import {Injectable} from '@angular/core'; |
| 2 import {Http, Headers} from '@angular/http'; | |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
3 |
| 60 | 4 //import 'rxjs/Rx'; // import all RxJS operators |
| 5 import 'rxjs/add/operator/map'; | |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
6 |
| 41 | 7 import {NEO4J_BASE_URL, NEO4J_AUTHENTICATION} from './app-config'; |
| 34 | 8 import {QueryMode, QUERY_MODES, FIRST_QUERY_MODES} from './query-mode'; |
|
5
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
9 import {QueryState} from './query-state'; |
|
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
10 import {QueryStep} from './query-step'; |
|
30
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
11 import {getResultType} from './result-type'; |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
12 import {ISMI_RESULT_TYPES} from './ismi-result-types'; |
| 39 | 13 import {getRelationType} from './ismi-relation-types'; |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
14 |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
15 @Injectable() |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
16 export class QueryService { |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
17 |
| 32 | 18 public typeAttribute = '_type'; |
| 19 public excludedAttributes = {}; | |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
20 public state: QueryState; |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
21 public objectTypes: string[]; |
| 2 | 22 |
|
5
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
23 constructor(private _http: Http) { |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
24 // init query state |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
25 this.state = new QueryState(); |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
26 } |
|
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
27 |
| 55 | 28 setup(newStateString: string) { |
| 29 // get list of object types | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
30 this.setupObjectTypes(); |
| 55 | 31 // get state from string |
| 32 if (newStateString) { | |
| 33 this.state.setStateFromString(newStateString); | |
| 34 } | |
| 8 | 35 } |
| 36 | |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
37 getState() { |
|
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
38 return this.state; |
|
5
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
39 } |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
40 |
| 34 | 41 getQueryModes(index: number): QueryMode[] { |
| 42 if (index == 0) { | |
| 43 return FIRST_QUERY_MODES; | |
| 44 } else { | |
| 45 return QUERY_MODES; | |
| 46 } | |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
47 } |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
48 |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
49 /** |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
50 * return the first set of options for the given query mode. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
51 */ |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
52 getQueryOptions(queryMode: QueryMode) { |
|
47
b65a031c4967
first step to angular2-final (2.4) version of the query browser.
casties
parents:
45
diff
changeset
|
53 let options: any[] = []; |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
54 if (queryMode == null) return options; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
55 if (queryMode.id === 'type_is') { |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
56 options = this.objectTypes; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
57 } else if (queryMode.id === 'relation_is') { |
| 21 | 58 options = this.state.resultRelations; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
59 } else if (queryMode.id === 'att_contains') { |
| 21 | 60 options = this.filterAttributes(this.state.resultAttributes); |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
61 } else if (queryMode.id === 'att_contains_norm') { |
| 21 | 62 options = this.filterAttributes(this.state.resultAttributes, true); |
|
15
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
63 } else if (queryMode.id === 'att_num_range') { |
| 21 | 64 options = this.filterAttributes(this.state.resultAttributes); |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
65 } |
|
5
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
66 console.debug("getQueryOptions returns: ", options); |
|
b06a5d61afed
new query state stuff.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
3
diff
changeset
|
67 return options; |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
68 } |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
69 |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
70 /** |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
71 * fetch all object types from Neo4j and store in this.objectTypes. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
72 */ |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
73 setupObjectTypes() { |
| 41 | 74 let query = `MATCH (n) WITH DISTINCT labels(n) AS labels |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
75 UNWIND labels AS label |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
76 RETURN DISTINCT label ORDER BY label`; |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
77 |
| 41 | 78 let res = this.fetchCypherResults([query]); |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
79 res.subscribe( |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
80 data => { |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
81 console.debug("neo4j data=", data); |
| 55 | 82 this.objectTypes = data.results[0].data |
| 83 .map(elem => elem.row[0]) | |
| 84 .filter(elem => elem[0] != "_"); | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
85 console.debug("object types=", this.objectTypes); |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
86 }, |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
87 err => console.error("neo4j error=", err), |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
88 () => console.debug('neo4j query Complete') |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
89 ); |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
90 } |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
91 |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
92 /** |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
93 * Set the query step at index. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
94 */ |
| 6 | 95 setQueryStep(index: number, step: QueryStep) { |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
96 this.state.steps[index] = step; |
| 6 | 97 } |
| 98 | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
99 /** |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
100 * Create the cypher queries for the current query state. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
101 * |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
102 * Updates the queries for results, attributes and relations. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
103 */ |
| 6 | 104 createCypherQuery() { |
| 41 | 105 let queryMatch = ''; |
| 106 let queryWhere = ''; | |
| 107 let queryReturn = ''; | |
| 108 let queryParams = {}; | |
| 109 let resultQuery = ''; | |
| 110 let attributesQuery = ''; | |
| 111 let outRelsQuery = ''; | |
| 112 let inRelsQuery = ''; | |
| 113 let returnType = ''; | |
| 114 let nIdx = 1; | |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
115 this.state.steps.forEach((step, stepIdx) => { |
| 41 | 116 let mode = step.mode.id; |
| 117 let params = step.params; | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
118 |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
119 /* |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
120 * step: object type is |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
121 */ |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
122 if (mode === 'type_is') { |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
123 queryMatch = `MATCH (n${nIdx}:${params.objectType})`; |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
124 queryWhere = ''; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
125 queryReturn = `RETURN n${nIdx}`; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
126 returnType = 'node'; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
127 } |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
128 |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
129 /* |
| 32 | 130 * step: object id is |
| 131 */ | |
| 132 if (mode === 'id_is') { | |
| 133 if (!queryMatch) { | |
| 134 // first step - use match clause | |
| 135 queryMatch = `MATCH (n${nIdx} {ismi_id: {att_val${stepIdx}}})`; | |
| 136 queryParams[`att_val${stepIdx}`] = parseInt(params.value, 10); | |
| 137 queryWhere = ''; | |
| 138 queryReturn = `RETURN n${nIdx}`; | |
| 139 returnType = 'node'; | |
| 140 } else { | |
| 141 // use where clause | |
| 142 if (!queryWhere) { | |
| 143 queryWhere = 'WHERE '; | |
| 144 } else { | |
| 145 queryWhere += ' AND '; | |
| 146 } | |
| 147 queryWhere += `n${nIdx}.ismi_id = {att_val${stepIdx}}`; | |
| 148 queryParams[`att_val${stepIdx}`] = parseInt(params.value, 10); | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 /* | |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
153 * step: relation type is |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
154 */ |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
155 if (mode === 'relation_is') { |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
156 nIdx += 1; |
| 39 | 157 let rel = params.relationType; |
| 158 if (rel.isOutgoing()) { | |
| 40 | 159 queryMatch += `-[:\`${rel.getRelType()}\`]->(n${nIdx})`; |
| 39 | 160 } else { |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
161 // inverse relation |
| 40 | 162 queryMatch += `<-[:\`${rel.getRelType()}\`]-(n${nIdx})`; |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
163 } |
| 39 | 164 queryReturn = `RETURN DISTINCT n${nIdx}`; |
| 8 | 165 returnType = 'node'; |
| 166 } | |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
167 |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
168 /* |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
169 * step: attribute contains(_norm) |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
170 */ |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
171 if (mode === 'att_contains' || mode === 'att_contains_norm') { |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
172 if (!queryWhere) { |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
173 queryWhere = 'WHERE '; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
174 } else { |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
175 queryWhere += ' AND '; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
176 } |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
177 if (params.attribute === 'ismi_id') { |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
178 // ismi_id is integer |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
179 queryWhere += `n${nIdx}.ismi_id = {att_val${stepIdx}}`; |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
180 queryParams[`att_val${stepIdx}`] = parseInt(params.value, 10); |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
181 } else { |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
182 if (mode === 'att_contains_norm') { |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
183 // match _n_attribute with normValue |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
184 queryWhere += `lower(n${nIdx}._n_${params.attribute}) CONTAINS lower({att_val${stepIdx}})`; |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
185 queryParams[`att_val${stepIdx}`] = params.normValue; |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
186 } else { |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
187 queryWhere += `lower(n${nIdx}.${params.attribute}) CONTAINS lower({att_val${stepIdx}})`; |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
188 queryParams[`att_val${stepIdx}`] = params.value; |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
189 } |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
190 } |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
191 } |
|
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
192 |
|
15
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
193 /* |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
194 * step: attribute number range |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
195 */ |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
196 if (mode === 'att_num_range') { |
|
15
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
197 if (!queryWhere) { |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
198 queryWhere = 'WHERE '; |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
199 } else { |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
200 queryWhere += ' AND '; |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
201 } |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
202 queryWhere += `toint(n${nIdx}.${params.attribute}) >= toint({att_nlo${stepIdx}})` |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
203 + ` AND toint(n${nIdx}.${params.attribute}) <= toint({att_nhi${stepIdx}})`; |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
204 queryParams[`att_nlo${stepIdx}`] = params.numLo; |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
205 queryParams[`att_nhi${stepIdx}`] = params.numHi; |
|
15
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
206 } |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
207 |
| 9 | 208 }); |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
209 // compose query |
| 32 | 210 resultQuery = queryMatch + (queryWhere ? '\n'+queryWhere : '') + '\n' + queryReturn; |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
211 // compose query for attributes of result |
|
15
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
212 attributesQuery = queryMatch + ' ' + queryWhere + ` WITH DISTINCT keys(n${nIdx}) AS atts` |
|
f84ff6781e57
added att_num_range query type.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
14
diff
changeset
|
213 + ` UNWIND atts AS att RETURN DISTINCT att ORDER BY att`; |
|
18
65bb467abcc6
inverse relations are now generated on the fly.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
17
diff
changeset
|
214 // compose query for relations of result |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
215 outRelsQuery = queryMatch + '-[r]->() ' + queryWhere + ' RETURN DISTINCT type(r)'; |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
216 inRelsQuery = queryMatch + '<-[r]-() ' + queryWhere + ' RETURN DISTINCT type(r)'; |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
217 this.state.resultCypherQuery = resultQuery; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
218 this.state.cypherQueryParams = queryParams; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
219 this.state.attributesCypherQuery = attributesQuery; |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
220 this.state.outRelsCypherQuery = outRelsQuery; |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
221 this.state.inRelsCypherQuery = inRelsQuery; |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
222 this.state.resultTypes = returnType; |
|
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
223 } |
|
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
224 |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
225 /** |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
226 * Create and run the cypher queries for the current query state. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
227 * |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
228 * Updates the results and nextQuery attributes and relations. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
229 */ |
| 40 | 230 runQuery() { |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
231 this.createCypherQuery(); |
|
13
98b435bb6c0c
more query work.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
12
diff
changeset
|
232 this.state.resultInfo = 'loading...'; |
|
16
7d82ca32833c
omit some attributes from list.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
15
diff
changeset
|
233 /* |
|
7d82ca32833c
omit some attributes from list.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
15
diff
changeset
|
234 * run query for result table |
|
7d82ca32833c
omit some attributes from list.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
15
diff
changeset
|
235 */ |
| 41 | 236 let queries = [this.state.resultCypherQuery]; |
| 237 let params = [this.state.cypherQueryParams]; | |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
238 if (this.state.attributesCypherQuery) { |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
239 queries.push(this.state.attributesCypherQuery); |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
240 params.push(this.state.cypherQueryParams); |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
241 } |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
242 if (this.state.outRelsCypherQuery) { |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
243 queries.push(this.state.outRelsCypherQuery); |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
244 params.push(this.state.cypherQueryParams); |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
245 } |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
246 if (this.state.inRelsCypherQuery) { |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
247 queries.push(this.state.inRelsCypherQuery); |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
248 params.push(this.state.cypherQueryParams); |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
249 } |
| 41 | 250 let res = this.fetchCypherResults(queries, params); |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
251 res.subscribe( |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
252 data => { |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
253 console.debug("neo4j result data=", data); |
| 41 | 254 let resIdx = 0; |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
255 /* |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
256 * results for result table |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
257 */ |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
258 this.state.results = data.results[resIdx].data.map(elem => elem.row[0]); |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
259 this.state.numResults = this.state.results.length; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
260 // count all types |
| 32 | 261 let resTypes = {}; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
262 this.state.results.forEach((r) => { |
| 32 | 263 let t = r[this.typeAttribute]; |
| 264 if (resTypes[t] == null) { | |
| 265 resTypes[t] = 1; | |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
266 } else { |
| 32 | 267 resTypes[t] += 1; |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
268 } |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
269 }); |
| 32 | 270 let info = ''; |
| 41 | 271 for (let t in resTypes) { |
|
11
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
272 info += t + '(' + resTypes[t] + ') '; |
|
6989cd00e8d7
relations work now as well as longer queries.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
10
diff
changeset
|
273 } |
|
14
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
274 info = info.substr(0, info.length-1); |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
275 this.state.resultInfo = info; |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
276 // save info also in last step |
|
7dc7ea95ca26
show result types below query steps.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
13
diff
changeset
|
277 this.state.steps[this.state.steps.length-1].resultInfo = info; |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
278 /* |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
279 * results for attribute list |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
280 */ |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
281 if (this.state.attributesCypherQuery) { |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
282 resIdx += 1; |
|
30
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
283 let atts = data.results[resIdx].data.map(elem => elem.row[0]); |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
284 this.state.resultAttributes = atts; |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
285 // the following assumes only one type in the result |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
286 for (let t in resTypes) { |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
287 this.state.resultType = getResultType(t, ISMI_RESULT_TYPES); |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
288 break; |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
289 } |
|
193271b6b9d2
configure attributes per result type. select number of items per result page.
casties
parents:
25
diff
changeset
|
290 this.state.resultColumns = this.state.resultType.getColumns(atts); |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
291 } |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
292 /* |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
293 * results for relations list |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
294 */ |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
295 if (this.state.outRelsCypherQuery) { |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
296 // outgoing aka forward relations |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
297 resIdx += 1; |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
298 let rels = data.results[resIdx].data.map(elem => elem.row[0]) |
| 39 | 299 .filter(elem => elem[0] != "_") |
| 300 .map(elem => getRelationType(elem, true)); | |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
301 this.state.resultRelations = rels; |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
302 } |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
303 if (this.state.inRelsCypherQuery) { |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
304 // incoming aka reverse relations |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
305 resIdx += 1; |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
306 let rels = data.results[resIdx].data.map(elem => elem.row[0]) |
|
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
307 .filter(elem => elem[0] != "_") |
| 39 | 308 .map(elem => getRelationType(elem, false)); |
|
36
e8dc6a4c6773
only show possible incoming/outgoing relation types.
casties
parents:
35
diff
changeset
|
309 this.state.resultRelations = this.state.resultRelations.concat(rels); |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
310 } |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
311 }, |
|
10
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
312 err => console.error("neo4j result error=", err), |
|
66dce99cef4e
attribute contains works now.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
9
diff
changeset
|
313 () => console.debug('neo4j result query Complete') |
|
7
6cd6c09032aa
object type query with results!
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
6
diff
changeset
|
314 ); |
| 6 | 315 } |
| 316 | |
| 21 | 317 |
| 318 filterAttributes(attributes: string[], normalized=false) { | |
| 41 | 319 let atts = []; |
| 21 | 320 if (normalized) { |
| 321 attributes.forEach((att) => { | |
| 322 if (att.substr(0, 3) == "_n_") { | |
| 323 atts.push(att.substr(3)); | |
| 324 } | |
| 325 }); | |
| 326 } else { | |
| 327 atts = attributes.filter(elem => elem[0] != "_" && !this.excludedAttributes[elem]); | |
| 328 } | |
| 329 return atts; | |
| 330 } | |
| 331 | |
| 332 /** | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
333 * Run the given queries on the Neo4J server. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
334 * |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
335 * Returns an Observable with the results. |
|
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
336 */ |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
337 fetchCypherResults(queries: string[], params=[{}]) { |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
338 console.debug("fetching cypher queries: ", queries); |
| 41 | 339 let headers = new Headers(); |
| 340 let auth = NEO4J_AUTHENTICATION; | |
|
20
34cd764e234b
make interfaces into classes. factor out NormalizationService.
casties
parents:
19
diff
changeset
|
341 headers.append('Authorization', 'Basic ' + btoa(`${auth.user}:${auth.password}`)); |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
342 headers.append('Content-Type', 'application/json'); |
|
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
343 headers.append('Accept', 'application/json'); |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
344 // put headers in options |
| 41 | 345 let opts = {'headers': headers}; |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
346 // unpack queries into statements |
| 41 | 347 let statements = queries.map((q, i) => { |
|
17
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
348 return {'statement': q, 'parameters': (params[i])?params[i]:{}}; |
|
f6af2c8347de
send multiple cypher queries in one request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
16
diff
changeset
|
349 }); |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
350 // create POST data from query |
| 41 | 351 let data = JSON.stringify({'statements': statements}); |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
352 // make post request asynchronously |
| 41 | 353 let resp = this._http.post(NEO4J_BASE_URL+'/transaction/commit', data, opts) |
|
3
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
354 // filter result as JSON |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
355 .map(res => res.json()); |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
356 // return Observable |
|
c741a00d38de
first list of object types :-)
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
2
diff
changeset
|
357 return resp; |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
358 } |
|
13
98b435bb6c0c
more query work.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
12
diff
changeset
|
359 |
|
1
59b7c3afcc6b
first interface and http request.
Robert Casties <casties@mpiwg-berlin.mpg.de>
parents:
diff
changeset
|
360 } |
