Skip to content

Commit a7272c4

Browse files
authored
Merge pull request #27 from bci-oss/bugfix/adapt-sorted-set-for-entity-instances
Resolve entity instances for Sorted Set
2 parents a9ed813 + fa9205b commit a7272c4

File tree

7 files changed

+207
-58
lines changed

7 files changed

+207
-58
lines changed

.vscode/launch.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "Launch Program",
11+
"skipFiles": [
12+
"<node_internals>/**"
13+
],
14+
"program": "${workspaceFolder}\\dist\\index.js",
15+
"preLaunchTask": "tsc: build - tsconfig.json",
16+
"outFiles": [
17+
"${workspaceFolder}/dist/**/*.js"
18+
]
19+
}
20+
]
21+
}

src/aspect-meta-model/characteristic/default-enumeration.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
*
1111
* SPDX-License-Identifier: MPL-2.0
1212
*/
13-
1413
import {Type} from '../type';
1514
import {Characteristic, DefaultCharacteristic} from './default-characteristic';
1615
import {DefaultEntityInstance} from '../default-entity-instance';

src/aspect-meta-model/characteristic/default-sorted-set.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,40 @@
1414
import {DefaultCollection} from './default-collection';
1515
import {Characteristic} from './default-characteristic';
1616
import {Type} from '../type';
17+
import { DefaultEntityInstance } from '../default-entity-instance';
18+
import { DefaultEntity } from '../default-entity';
19+
import { Enumeration } from './default-enumeration';
1720

18-
export class DefaultSortedSet extends DefaultCollection {
19-
constructor(metaModelVersion: string, aspectModelUrn: string, name: string, elementCharacteristic?: Characteristic, dataType?: Type) {
21+
export class DefaultSortedSet extends DefaultCollection implements Enumeration {
22+
constructor(metaModelVersion: string, aspectModelUrn: string, name: string, elementCharacteristic?: Characteristic, dataType?: Type,private _values?: Array<DefaultEntityInstance | string | number>) {
2023
super(metaModelVersion, aspectModelUrn, name, false, true, elementCharacteristic, dataType);
2124
}
25+
public set values(values: Array<DefaultEntityInstance | string | number>) {
26+
this._values = values;
27+
}
28+
29+
public get values(): Array<DefaultEntityInstance | string | number> {
30+
return this._values;
31+
}
32+
33+
/**
34+
* Find the index of the given value in the values array.
35+
*
36+
* @return returns the index of the value or -1
37+
*/
38+
public indexOf(value: string): number {
39+
if (!this.values) {
40+
return -1;
41+
}
42+
43+
if (this.dataType && this.dataType.isComplex) {
44+
const propertyValue = (<DefaultEntity>this.dataType).properties.find(property => property.isNotInPayload === false);
45+
46+
return this.values.findIndex((valueEntry: DefaultEntityInstance) => {
47+
return valueEntry[propertyValue.name] === value;
48+
});
49+
} else {
50+
return this.values.findIndex(valueEntry => valueEntry === value);
51+
}
52+
}
2253
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2024 Robert Bosch Manufacturing Solutions GmbH
3+
*
4+
* See the AUTHORS file(s) distributed with this work for
5+
* additional information regarding authorship.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
10+
*
11+
* SPDX-License-Identifier: MPL-2.0
12+
*/
13+
14+
import {Quad} from "n3";
15+
16+
export interface MultiLanguageText {
17+
value: string;
18+
language: string;
19+
}
20+
21+
export class CharacteristicInstantiatorUtil {
22+
23+
public static resolveValues(quad: Quad, dataType: string): string | number {
24+
if (!dataType || !dataType.includes('#')) {
25+
return `${quad.object.value}`;
26+
}
27+
28+
switch (dataType.split('#')[1]) {
29+
case 'decimal':
30+
case 'integer':
31+
case 'double':
32+
case 'float':
33+
case 'byte':
34+
case 'short':
35+
case 'int':
36+
case 'long':
37+
case 'unsignedByte':
38+
case 'unsignedLong':
39+
case 'unsignedInt':
40+
case 'unsignedShort':
41+
case 'positiveInteger':
42+
case 'nonNegativeInteger':
43+
case 'negativeInteger':
44+
case 'nonPositiveInteger':
45+
return Number(quad.object.value);
46+
default:
47+
return `${quad.object.value}`;
48+
}
49+
}
50+
51+
public static solveBlankNodeValues(resolvedBlankNodes: Array<Quad>): Array<MultiLanguageText> {
52+
return resolvedBlankNodes.length > 0 ? resolvedBlankNodes.map(item => this.createLanguageObject(item)) : [];
53+
}
54+
55+
public static getPredicateKey(quad: Quad): string {
56+
return quad.predicate.value.split('#')[1];
57+
}
58+
59+
public static createLanguageObject(quad: Quad): MultiLanguageText {
60+
return {value: quad.object.value, language: (quad.object as any).language};
61+
}
62+
}

src/instantiator/characteristic/enumeration-characteristic-instantiator.ts

Lines changed: 5 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ import {DefaultEnumeration, Enumeration} from '../../aspect-meta-model/character
1818
import {Samm} from '../../vocabulary';
1919
import {EntityInstantiator} from '../entity-instantiator';
2020
import {DefaultEntityInstance} from '../../aspect-meta-model/default-entity-instance';
21-
22-
export interface MultiLanguageText {
23-
value: string;
24-
language: string;
25-
}
21+
import {CharacteristicInstantiatorUtil, MultiLanguageText} from './characteristic-instantiator-util';
2622

2723
export class EnumerationCharacteristicInstantiator extends CharacteristicInstantiator {
2824
constructor(metaModelElementInstantiator: MetaModelElementInstantiator, nextProcessor: CharacteristicInstantiator) {
@@ -33,7 +29,6 @@ export class EnumerationCharacteristicInstantiator extends CharacteristicInstant
3329
const samm = this.metaModelElementInstantiator.samm;
3430
const sammC = this.metaModelElementInstantiator.sammC;
3531
const enumeration = this.creatEnumerationObject();
36-
3732
const dataType = quads.find(quad => this.samm.isDataTypeProperty(quad.predicate.value));
3833

3934
quads.forEach(quad => {
@@ -57,38 +52,10 @@ export class EnumerationCharacteristicInstantiator extends CharacteristicInstant
5752
private getEnumerationValues(quad: Quad, dataType: string): Array<string | number | DefaultEntityInstance> {
5853
const quads = this.metaModelElementInstantiator.rdfModel.resolveBlankNodes(quad.object.value);
5954
return quads.map(quadValue =>
60-
Util.isLiteral(quadValue.object) ? this.resolveValues(quadValue, dataType) : this.resolveEntityInstance(quadValue)
55+
Util.isLiteral(quadValue.object) ? CharacteristicInstantiatorUtil.resolveValues(quadValue, dataType) : this.resolveEntityInstance(quadValue)
6156
);
6257
}
6358

64-
private resolveValues(quad: Quad, dataType: string): string | number {
65-
if (!dataType || !dataType.includes('#')) {
66-
return `${quad.object.value}`;
67-
}
68-
69-
switch (dataType.split('#')[1]) {
70-
case 'decimal':
71-
case 'integer':
72-
case 'double':
73-
case 'float':
74-
case 'byte':
75-
case 'short':
76-
case 'int':
77-
case 'long':
78-
case 'unsignedByte':
79-
case 'unsignedLong':
80-
case 'unsignedInt':
81-
case 'unsignedShort':
82-
case 'positiveInteger':
83-
case 'nonNegativeInteger':
84-
case 'negativeInteger':
85-
case 'nonPositiveInteger':
86-
return Number(quad.object.value);
87-
default:
88-
return `${quad.object.value}`;
89-
}
90-
}
91-
9259
protected resolveEntityInstance(quad: Quad): DefaultEntityInstance {
9360
const entityInstanceQuads = this.metaModelElementInstantiator.rdfModel.store.getQuads(quad.object, null, null, null);
9461
const entityTypeQuad = entityInstanceQuads.find(
@@ -118,7 +85,7 @@ export class EnumerationCharacteristicInstantiator extends CharacteristicInstant
11885
// create the related instance and attach the metamodel element to it
11986
const entityInstance = new DefaultEntityInstance(quad.object.value.split('#')[1], entity, descriptions);
12087
entityInstanceQuads.forEach(quad => {
121-
const predicateKey = this.getPredicateKey(quad);
88+
const predicateKey = CharacteristicInstantiatorUtil.getPredicateKey(quad);
12289
entityInstance[predicateKey] = this.resolveQuadObject(quad);
12390
});
12491

@@ -130,29 +97,17 @@ export class EnumerationCharacteristicInstantiator extends CharacteristicInstant
13097
private resolveQuadObject(quad: Quad): MultiLanguageText | Array<MultiLanguageText> | string {
13198
if (Util.isBlankNode(quad.object)) {
13299
const resolvedBlankNodes = this.metaModelElementInstantiator.rdfModel.resolveBlankNodes(quad.object.value);
133-
return this.solveBlankNodeValues([...resolvedBlankNodes]);
100+
return CharacteristicInstantiatorUtil.solveBlankNodeValues([...resolvedBlankNodes]);
134101
}
135102

136103
if (((quad.object as any).datatypeString === Samm.RDF_LANG_STRING) ||
137104
((quad.object as any).datatypeString === Samm.XML_LANG_STRING)) {
138-
return this.createLanguageObject(quad);
105+
return CharacteristicInstantiatorUtil.createLanguageObject(quad);
139106
}
140107

141108
return quad.object.value;
142109
}
143110

144-
private solveBlankNodeValues(resolvedBlankNodes: Array<Quad>): Array<MultiLanguageText> {
145-
return resolvedBlankNodes.length > 0 ? resolvedBlankNodes.map(item => this.createLanguageObject(item)) : [];
146-
}
147-
148-
private getPredicateKey(quad: Quad): string {
149-
return quad.predicate.value.split('#')[1];
150-
}
151-
152-
private createLanguageObject(quad: Quad): MultiLanguageText {
153-
return {value: quad.object.value, language: (quad.object as any).language};
154-
}
155-
156111
shouldProcess(nameNode: NamedNode): boolean {
157112
return this.metaModelElementInstantiator.sammC.EnumerationCharacteristic().equals(nameNode);
158113
}

src/instantiator/characteristic/sorted-set-characteristic-instantiator.ts

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,103 @@
1313

1414
import {CharacteristicInstantiator} from '../characteristic/characteristic-instantiator';
1515
import {MetaModelElementInstantiator} from '../meta-model-element-instantiator';
16-
import {NamedNode} from 'n3';
17-
import {Collection} from '../../aspect-meta-model';
1816
import {CollectionCharacteristicInstantiator} from './collection-characteristic-instantiator';
1917
import {DefaultSortedSet} from '../../aspect-meta-model/characteristic/default-sorted-set';
2018

19+
import {NamedNode, Quad, Util} from 'n3';
20+
import {Characteristic} from '../../aspect-meta-model';
21+
import {Samm} from '../../vocabulary';
22+
import {EntityInstantiator} from '../entity-instantiator';
23+
import {DefaultEntityInstance} from '../../aspect-meta-model/default-entity-instance';
24+
import {CharacteristicInstantiatorUtil, MultiLanguageText} from './characteristic-instantiator-util';
25+
2126
export class SortedSetCharacteristicInstantiator extends CollectionCharacteristicInstantiator {
2227
constructor(metaModelElementInstantiator: MetaModelElementInstantiator, nextProcessor: CharacteristicInstantiator) {
2328
super(metaModelElementInstantiator, nextProcessor);
2429
}
2530

26-
protected creatCollectionObject(): Collection {
31+
protected processElement(quads: Array<Quad>): Characteristic {
32+
const samm = this.metaModelElementInstantiator.samm;
33+
const sammC = this.metaModelElementInstantiator.sammC;
34+
const sortedSet = this.creatCollectionObject();
35+
36+
const dataType = quads.find(quad => this.samm.isDataTypeProperty(quad.predicate.value));
37+
38+
quads.forEach(quad => {
39+
if (samm.isValueProperty(quad.predicate.value) || sammC.isValuesProperty(quad.predicate.value)) {
40+
if (Util.isBlankNode(quad.object)) {
41+
sortedSet.values = this.getEnumerationValues(quad, dataType?.object.value);
42+
}
43+
}
44+
});
45+
return sortedSet;
46+
}
47+
48+
protected creatCollectionObject(): any {
2749
return new DefaultSortedSet(null, null, null, null);
2850
}
2951

3052
shouldProcess(nameNode: NamedNode): boolean {
3153
return this.metaModelElementInstantiator.sammC.SortedSetCharacteristic().equals(nameNode);
3254
}
55+
56+
protected resolveEntityInstance(quad: Quad): DefaultEntityInstance {
57+
const entityInstanceQuads = this.metaModelElementInstantiator.rdfModel.store.getQuads(quad.object, null, null, null);
58+
const entityTypeQuad = entityInstanceQuads.find(
59+
entityInstanceQuad => entityInstanceQuad.predicate.value === `${Samm.RDF_URI}#type`
60+
);
61+
62+
if (entityTypeQuad) {
63+
const entity = new EntityInstantiator(this.metaModelElementInstantiator).createEntity(
64+
this.metaModelElementInstantiator.rdfModel.store.getQuads(entityTypeQuad.object, null, null, null)
65+
);
66+
67+
// determine the description of the value/instance if defined
68+
const descriptionQuad = entityInstanceQuads.find(
69+
quad =>
70+
quad.predicate.id.toLowerCase().includes('description') &&
71+
entity.properties.find(property => property.isNotInPayload === false && quad.predicate.id)
72+
);
73+
const descriptions = new Map<string, string>();
74+
if (descriptionQuad) {
75+
entityInstanceQuads
76+
.filter(quad => quad.predicate.id === descriptionQuad.predicate.id)
77+
.forEach(quad =>
78+
descriptions.set(this.metaModelElementInstantiator.rdfModel.getLocale(quad) || 'en', quad.object.value)
79+
);
80+
}
81+
82+
// create the related instance and attach the metamodel element to it
83+
const entityInstance = new DefaultEntityInstance(quad.object.value.split('#')[1], entity, descriptions);
84+
entityInstanceQuads.forEach(quad => {
85+
const predicateKey = CharacteristicInstantiatorUtil.getPredicateKey(quad);
86+
entityInstance[predicateKey] = this.resolveQuadObject(quad);
87+
});
88+
89+
return entityInstance;
90+
}
91+
throw new Error(`Could resolve Entity instance ${entityTypeQuad.subject.value}`);
92+
}
93+
94+
private resolveQuadObject(quad: Quad): MultiLanguageText | Array<MultiLanguageText> | string {
95+
if (Util.isBlankNode(quad.object)) {
96+
const resolvedBlankNodes = this.metaModelElementInstantiator.rdfModel.resolveBlankNodes(quad.object.value);
97+
return CharacteristicInstantiatorUtil.solveBlankNodeValues([...resolvedBlankNodes]);
98+
}
99+
100+
if (((quad.object as any).datatypeString === Samm.RDF_LANG_STRING) ||
101+
((quad.object as any).datatypeString === Samm.XML_LANG_STRING)) {
102+
return CharacteristicInstantiatorUtil.createLanguageObject(quad);
103+
}
104+
105+
return quad.object.value;
106+
}
107+
108+
private getEnumerationValues(quad: Quad, dataType: string): Array<string | number | DefaultEntityInstance> {
109+
const quads = this.metaModelElementInstantiator.rdfModel.resolveBlankNodes(quad.object.value);
110+
return quads.map(quadValue =>
111+
Util.isLiteral(quadValue.object) ? CharacteristicInstantiatorUtil.resolveValues(quadValue, dataType) : this.resolveEntityInstance(quadValue)
112+
);
113+
}
114+
33115
}

src/instantiator/characteristic/state-characteristic-instantiator.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
import {CharacteristicInstantiator} from '../characteristic/characteristic-instantiator';
1515
import {MetaModelElementInstantiator} from '../meta-model-element-instantiator';
1616
import {NamedNode, Quad, Util} from 'n3';
17-
import {Characteristic} from '../../aspect-meta-model';
17+
import {Characteristic, Enumeration} from '../../aspect-meta-model';
1818
import {DefaultState} from '../../aspect-meta-model/characteristic/default-state';
1919
import {EnumerationCharacteristicInstantiator} from './enumeration-characteristic-instantiator';
20-
import {Enumeration} from '../../aspect-meta-model/characteristic/default-enumeration';
2120

2221
export class StateCharacteristicInstantiator extends EnumerationCharacteristicInstantiator {
2322
constructor(metaModelElementInstantiator: MetaModelElementInstantiator, nextProcessor: CharacteristicInstantiator) {

0 commit comments

Comments
 (0)