@knora/core
Version:
Knora ui module: core
892 lines • 117 kB
JavaScript
import * as tslib_1 from "tslib";
import { Injectable } from '@angular/core';
import { Constants } from '@knora/api';
import { forkJoin, from, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import { Utils } from '../../declarations/utils';
import { OntologyService } from './ontology.service';
import * as i0 from "@angular/core";
import * as i1 from "./ontology.service";
var jsonld = require('jsonld');
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
*
* Represents an error occurred in OntologyCacheService.
*/
var OntologyCacheError = /** @class */ (function (_super) {
tslib_1.__extends(OntologyCacheError, _super);
function OntologyCacheError(message) {
var _this = _super.call(this, message) || this;
_this.message = message;
return _this;
}
return OntologyCacheError;
}(Error));
/**
*
* Represents an ontology's metadata.
*/
var OntologyMetadata = /** @class */ (function () {
/**
* @hideconstructor
*
* @param {string} id Iri identifying the ontology.
* @param {string} label a label describing the ontology.
*/
function OntologyMetadata(id, label) {
this.id = id;
this.label = label;
}
return OntologyMetadata;
}());
export { OntologyMetadata };
/**
* Occurrence of a property for a resource class (its cardinality).
*/
export var CardinalityOccurrence;
(function (CardinalityOccurrence) {
CardinalityOccurrence[CardinalityOccurrence["minCard"] = 0] = "minCard";
CardinalityOccurrence[CardinalityOccurrence["card"] = 1] = "card";
CardinalityOccurrence[CardinalityOccurrence["maxCard"] = 2] = "maxCard";
})(CardinalityOccurrence || (CardinalityOccurrence = {}));
/**
* Cardinality of a property for the given resource class.
*/
var Cardinality = /** @class */ (function () {
/**
* @param {CardinalityOccurrence} occurrence type of given occurrence.
* @param {number} value numerical value of given occurrence.
* @param {string} property the property the given occurrence applies to.
*/
function Cardinality(occurrence, value, property) {
this.occurrence = occurrence;
this.value = value;
this.property = property;
}
return Cardinality;
}());
export { Cardinality };
/**
* Property gui order
*/
var GuiOrder = /** @class */ (function () {
/**
* @param {number} value
* @param {string} property
*/
function GuiOrder(value, property) {
this.value = value;
this.property = property;
}
return GuiOrder;
}());
export { GuiOrder };
/**
* A resource class definition.
*/
var ResourceClass = /** @class */ (function () {
/**
* @param {string} id Iri identifying the resource class.
* @param {string} icon path to an icon representing the resource class.
* @param {string} comment comment on the resource class.
* @param {string} label label describing the resource class.
* @param {Cardinality[]} cardinalities the resource class's properties.
* @param {GuiOrder[]} guiOrder the resource class's gui-order properties.
*/
function ResourceClass(id, icon, comment, label, cardinalities, guiOrder) {
this.id = id;
this.icon = icon;
this.comment = comment;
this.label = label;
this.cardinalities = cardinalities;
this.guiOrder = guiOrder;
}
return ResourceClass;
}());
export { ResourceClass };
/**
* A map of resource class Iris to resource class definitions.
*/
var ResourceClasses = /** @class */ (function () {
function ResourceClasses() {
}
return ResourceClasses;
}());
export { ResourceClasses };
/**
* A property definition.
*/
var Property = /** @class */ (function () {
/**
* @param {string} id Iri identifying the property definition.
* @param {string} objectType the property's object constraint.
* @param {string} comment comment on the property definition.
* @param {string} label label describing the property definition.
* @param {string[]} subPropertyOf Iris of properties the given property is a subproperty of.
* @param {boolean} isEditable indicates whether the given property can be edited by the client.
* @param {boolean} isLinkProperty indicates whether the given property is a linking property.
* @param {boolean} isLinkValueProperty indicates whether the given property refers to a link value.
* @param {string} guiAttribute the gui attribute assigned to this property, if any.
*/
function Property(id, objectType, comment, label, subPropertyOf, isEditable, isLinkProperty, isLinkValueProperty, guiAttribute) {
this.id = id;
this.objectType = objectType;
this.comment = comment;
this.label = label;
this.subPropertyOf = subPropertyOf;
this.isEditable = isEditable;
this.isLinkProperty = isLinkProperty;
this.isLinkValueProperty = isLinkValueProperty;
this.guiAttribute = guiAttribute;
}
return Property;
}());
export { Property };
/**
* A map of property Iris to property definitions.
*/
var Properties = /** @class */ (function () {
function Properties() {
}
return Properties;
}());
export { Properties };
/**
* Groups resource classes by the ontology they are defined in.
*
* A map of ontology Iris to an array of resource class Iris.
*/
var ResourceClassIrisForOntology = /** @class */ (function () {
function ResourceClassIrisForOntology() {
}
return ResourceClassIrisForOntology;
}());
export { ResourceClassIrisForOntology };
/**
* Represents cached ontology information (only used by this service internally).
* This cache is updated whenever new definitions are requested from Knora.
*
* Requested ontology information by a service is represented by [[OntologyInformation]].
*/
var OntologyCache = /** @class */ (function () {
function OntologyCache() {
this.ontologies = [];
this.resourceClassIrisForOntology = new ResourceClassIrisForOntology();
this.resourceClasses = new ResourceClasses();
this.properties = new Properties();
}
return OntologyCache;
}());
/**
* Represents ontology information requested from this service.
*
* For every request, an instance of this class is returned containing the requested information.
*/
var OntologyInformation = /** @class */ (function () {
/**
* @param {ResourceClassIrisForOntology} resourceClassesForOntology all resource class Iris for a given ontology.
* @param {ResourceClasses} resourceClasses resource class definitions.
* @param {Properties} properties property definitions.
*/
function OntologyInformation(resourceClassesForOntology, resourceClasses, properties) {
this.resourceClassesForOntology = resourceClassesForOntology;
this.resourceClasses = resourceClasses;
this.properties = properties;
}
/**
* Sorts an array of `ResourceClass` or `Property` by label.
*
* @param a first element
* @param b second element
* @return negative -1 if the first element is considered lower than the second, 1 if the second element is considered bigger, 0 if they are equal
*/
OntologyInformation.sortFunc = function (a, b) {
// dealing with 'undefined' labels
if (a.label === undefined) {
return 1;
}
else if (b.label === undefined) {
return -1;
}
var labelA = a.label.toLowerCase();
var labelB = b.label.toLowerCase();
if (labelA < labelB) {
return -1;
}
else if (labelA > labelB) {
return 1;
}
else {
return 0;
}
};
/**
* Merge the given [[OntologyInformation]] into the current instance,
* updating the existing information.
* This is necessary when a service like the search fetches new results
* that have to be added to an existing collection.
* The existing ontology information must not be lost.
*
* @param {OntologyInformation} ontologyInfo the given definitions that have to be integrated.
* @returns void
*/
OntologyInformation.prototype.updateOntologyInformation = function (ontologyInfo) {
// get new resourceClassIrisForOntology
var newResourceClassesForOntology = ontologyInfo.getResourceClassForOntology();
// update new resourceClassIrisForOntology
// tslint:disable-next-line:forin
for (var newResClassForOntology in newResourceClassesForOntology) {
this.resourceClassesForOntology[newResClassForOntology] = newResourceClassesForOntology[newResClassForOntology];
}
// get new resource class definitions
var newResourceClasses = ontologyInfo.getResourceClasses();
// update resourceClasses
// tslint:disable-next-line:forin
for (var newResClass in newResourceClasses) {
this.resourceClasses[newResClass] = newResourceClasses[newResClass];
}
// get new property definitions
var newProperties = ontologyInfo.getProperties();
// update properties
// tslint:disable-next-line:forin
for (var newProp in newProperties) {
this.properties[newProp] = newProperties[newProp];
}
};
/**
* Returns resource class definitions for ontologies.
*
* @returns ResourceClassIrisForOntology - all resource class definitions grouped by ontologies.
*/
OntologyInformation.prototype.getResourceClassForOntology = function () {
return this.resourceClassesForOntology;
};
/**
* Returns all resource classes as an object.
*
* @returns ResourceClasses - all resource class definitions as an object.
*/
OntologyInformation.prototype.getResourceClasses = function () {
return this.resourceClasses;
};
/**
* Returns all resource classes as an array.
*
* @param {boolean} sortAsc sort resource classes by label in ascending order by default
* @returns ResourceClass[]
*/
OntologyInformation.prototype.getResourceClassesAsArray = function (sortAsc) {
if (sortAsc === void 0) { sortAsc = true; }
var resClasses = [];
// tslint:disable-next-line:forin
for (var resClassIri in this.resourceClasses) {
var resClass = this.resourceClasses[resClassIri];
resClasses.push(resClass);
}
// resourceClasses order by label in ascending order
resClasses.sort(OntologyInformation.sortFunc);
// resourceClasses order by label in descending order
if (!sortAsc) {
resClasses.reverse();
}
return resClasses;
};
/**
* Returns a resource class's label.
*
* @param {string} resClass resource class to query for.
* @returns string - the resource class's label.
*/
OntologyInformation.prototype.getLabelForResourceClass = function (resClass) {
if (resClass !== undefined) {
var resClassDef = this.resourceClasses[resClass];
if (resClassDef !== undefined && resClassDef.label !== undefined) {
return resClassDef.label;
}
else {
console.log("cannot get label for " + resClass);
}
}
else {
console.log('call of OntologyInformation.getLabelForResourceClass without argument resClass');
}
};
/**
* Returns all properties as an object.
*
* @returns Properties - all properties as an object.
*/
OntologyInformation.prototype.getProperties = function () {
return this.properties;
};
/**
* Returns all properties as an array.
*
* @param {boolean} sortAsc sort properties by label in ascending order by default
* @returns Property[] - all properties as an array.
*/
OntologyInformation.prototype.getPropertiesAsArray = function (sortAsc) {
if (sortAsc === void 0) { sortAsc = true; }
var properties = [];
// tslint:disable-next-line:forin
for (var propIri in this.properties) {
var prop = this.properties[propIri];
properties.push(prop);
}
// properties order by label in ascending order
properties.sort(OntologyInformation.sortFunc);
// properties order by label in descending order
if (!sortAsc) {
properties.reverse();
}
return properties;
};
/**
* Returns a property's label.
*
* @param {string} property to query for.
* @returns string - the property's label.
*/
OntologyInformation.prototype.getLabelForProperty = function (property) {
if (property !== undefined) {
var propDef = this.properties[property];
if (propDef !== undefined && propDef.label !== undefined) {
return propDef.label;
}
else {
console.log("cannot get label for " + property);
}
}
else {
console.log('call of OntologyInformation.getLabelForProperty without argument property');
}
};
return OntologyInformation;
}());
export { OntologyInformation };
/**
* Requests ontology information from Knora and caches it.
* Other components or services obtain ontology information through this service.
*/
var OntologyCacheService = /** @class */ (function () {
function OntologyCacheService(_ontologyService) {
this._ontologyService = _ontologyService;
/**
* Ontologies ingored by this service.
* @param {string[]} excludedOntologies
*/
this.excludedOntologies = [Constants.SalsahGui, Constants.StandoffOntology];
/**
* @param {string[]} excludedProperties properties that Knora is not responsible for and that have to be ignored because they cannot be resolved at the moment.
*/
this.excludedProperties = [Constants.Label];
/**
* @param {string[]} nonResourceClasses class definitions that are not be treated as Knora resource classes
*/
this.nonResourceClasses = [Constants.ForbiddenResource, Constants.XMLToStandoffMapping, Constants.ListNode];
/**
* @param {OntologyCache} cacheOntology central instance that caches all definitions
*/
this.cacheOntology = new OntologyCache();
}
/**
* Requests the metadata of all ontologies from Knora.
*
* @returns Observable<object> - metadata for all ontologies as JSON-LD (no prefixes, all Iris fully expanded).
*/
OntologyCacheService.prototype.getOntologiesMetadataFromKnora = function () {
return this._ontologyService.getOntologiesMetadata().pipe(mergeMap(
// this would return an Observable of a PromiseObservable -> combine them into one Observable
// http://reactivex.io/documentation/operators/flatmap.html
// http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-mergeMap
function (ontRes) {
var ontPromises = jsonld.promises;
// compact JSON-LD using an empty context: expands all Iris
var ontPromise = ontPromises.compact(ontRes.body, {});
// convert promise to Observable and return it
// https://www.learnrxjs.io/operators/creation/frompromise.html
return from(ontPromise);
}));
};
/**
* Requests all entity definitions (resource classes and properties) for the given ontology from Knora.
*
* @param {string} ontologyIri the Iri of the requested ontology.
* @returns Observable<object> - metadata for all entity definitions for ontology from Knora.
*/
OntologyCacheService.prototype.getAllEntityDefinitionsForOntologyFromKnora = function (ontologyIri) {
return this._ontologyService.getAllEntityDefinitionsForOntologies(ontologyIri).pipe(mergeMap(
// this would return an Observable of a PromiseObservable -> combine them into one Observable
// http://reactivex.io/documentation/operators/flatmap.html
// http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-mergeMap
function (ontRes) {
var ontPromises = jsonld.promises;
// compact JSON-LD using an empty context: expands all Iris
var ontPromise = ontPromises.compact(ontRes.body, {});
// convert promise to Observable and return it
// https://www.learnrxjs.io/operators/creation/frompromise.html
return from(ontPromise);
}));
};
/**
* Writes all the ontologies' metadata returned by Knora to the cache.
*
* @param {object[]} ontologies metadata of all existing ontologies as JSON-LD.
* @returns a new OntologyMetadata object
*/
OntologyCacheService.prototype.convertAndWriteOntologiesMetadataToCache = function (ontologies) {
this.cacheOntology.ontologies = ontologies.map(function (ontology) {
return new OntologyMetadata(ontology['@id'], ontology[Constants.Label]);
});
};
/**
* Returns all ontologies' metadata from the cache and returns them.
*
* @returns Array<OntologyMetadata> - metadata of all existing ontologies.
*/
OntologyCacheService.prototype.getAllOntologiesMetadataFromCache = function () {
return this.cacheOntology.ontologies;
};
/**
* Returns resource class Iris from the ontology response.
* `knora-api:Resource` will be excluded.
*
* @param {Array<object>} classDefinitions the class definitions in an ontology response.
* @returns string[] - resource class Iris from the given class definitions.
*/
OntologyCacheService.prototype.getResourceClassIrisFromOntologyResponse = function (classDefinitions) {
var e_1, _a;
var resourceClassIris = [];
try {
for (var classDefinitions_1 = tslib_1.__values(classDefinitions), classDefinitions_1_1 = classDefinitions_1.next(); !classDefinitions_1_1.done; classDefinitions_1_1 = classDefinitions_1.next()) {
var classDef = classDefinitions_1_1.value;
var classIri = classDef['@id'];
// check that class name is not listed as a non resource class and that the isResourceClass flag is present and set to true
if (classIri !== Constants.Resource && this.nonResourceClasses.indexOf(classIri)
=== -1 && (classDef[Constants.IsResourceClass] !== undefined && classDef[Constants.IsResourceClass] === true)) {
// it is not a value class, but a resource class definition
resourceClassIris.push(classIri);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (classDefinitions_1_1 && !classDefinitions_1_1.done && (_a = classDefinitions_1.return)) _a.call(classDefinitions_1);
}
finally { if (e_1) throw e_1.error; }
}
return resourceClassIris;
};
/**
* Converts a Knora response for all entity definitions for the requested ontology
* into an internal representation and caches it.
*
* Knora automatically includes the property definitions referred to in the cardinalities of resource classes.
* If they are defined in another ontology, that ontology is requested from Knora too.
*
* @param {Object} ontology the ontology to be cached.
* @returns void
*/
OntologyCacheService.prototype.convertAndWriteAllEntityDefinitionsForOntologyToCache = function (ontology) {
var graph = ontology['@graph'];
// get all class definitions
var classDefs = graph.filter(function (entity) {
var entityType = entity['@type'];
return entityType === Constants.Class;
});
// get all property definitions
var propertyDefs = graph.filter(function (entity) {
var entityType = entity['@type'];
return entityType === Constants.ObjectProperty ||
entityType === Constants.DataTypeProperty ||
entityType === Constants.Owl + Constants.Delimiter + 'AnnotationProperty' ||
entityType === Constants.RdfProperty;
});
// cache all resource class Iris belonging to the current ontology
this.cacheOntology.resourceClassIrisForOntology[ontology['@id']] = this.getResourceClassIrisFromOntologyResponse(classDefs);
// write class and property defintions to cache
this.convertAndWriteEntityDefinitionsToCache(classDefs, propertyDefs);
};
/**
* Returns definitions for the requested ontologies from the cache.
*
* @param {string[]} ontologyIris the ontologies for which definitions should be returned.
* @returns Observable<OntologyInformation> - the definitions for the requested ontologies.
*/
OntologyCacheService.prototype.getOntologyInformationFromCache = function (ontologyIris) {
var e_2, _a;
var resourceClassesForOntology = new ResourceClassIrisForOntology();
// collect resource class Iris for all requested named graphs
var allResourceClassIris = [];
try {
for (var ontologyIris_1 = tslib_1.__values(ontologyIris), ontologyIris_1_1 = ontologyIris_1.next(); !ontologyIris_1_1.done; ontologyIris_1_1 = ontologyIris_1.next()) {
var ontologyIri = ontologyIris_1_1.value;
if (this.cacheOntology.resourceClassIrisForOntology[ontologyIri] === undefined) {
throw new OntologyCacheError("getResourceClassesForOntologiesFromCache: ontology not found in cache: " + ontologyIri);
}
// add information for the given ontology
resourceClassesForOntology[ontologyIri] = this.cacheOntology.resourceClassIrisForOntology[ontologyIri];
// add all resource class Iris of this ontology
allResourceClassIris = allResourceClassIris.concat(this.cacheOntology.resourceClassIrisForOntology[ontologyIri]);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (ontologyIris_1_1 && !ontologyIris_1_1.done && (_a = ontologyIris_1.return)) _a.call(ontologyIris_1);
}
finally { if (e_2) throw e_2.error; }
}
// get resource class definitions for all requested ontologies
return this.getResourceClassDefinitions(allResourceClassIris).pipe(map(function (resClassDefs) {
return new OntologyInformation(resourceClassesForOntology, resClassDefs.getResourceClasses(), resClassDefs.getProperties());
}));
};
/**
* Converts a Knora ontology response into an internal representation and caches it.
*
* @param {object[]} resourceClassDefinitions the resource class definitions returned by Knora.
* @param {object[]} propertyClassDefinitions the property definitions returned by Knora.
* @returns void
*/
OntologyCacheService.prototype.convertAndWriteEntityDefinitionsToCache = function (resourceClassDefinitions, propertyClassDefinitions) {
var e_3, _a, e_4, _b;
try {
// convert and cache each given resource class definition
for (var resourceClassDefinitions_1 = tslib_1.__values(resourceClassDefinitions), resourceClassDefinitions_1_1 = resourceClassDefinitions_1.next(); !resourceClassDefinitions_1_1.done; resourceClassDefinitions_1_1 = resourceClassDefinitions_1.next()) {
var resClass = resourceClassDefinitions_1_1.value;
var resClassIri = resClass['@id'];
// represents all cardinalities of this resource class
var cardinalities = [];
var guiOrder = [];
if (resClass[Constants.SubClassOf] !== undefined) {
var subclassOfCollection = void 0;
// check if it is a single object or a collection
if (!Array.isArray(resClass[Constants.SubClassOf])) {
subclassOfCollection = [resClass[Constants.SubClassOf]];
}
else {
subclassOfCollection = resClass[Constants.SubClassOf];
}
try {
// get cardinalities for the properties of a resource class
for (var subclassOfCollection_1 = tslib_1.__values(subclassOfCollection), subclassOfCollection_1_1 = subclassOfCollection_1.next(); !subclassOfCollection_1_1.done; subclassOfCollection_1_1 = subclassOfCollection_1.next()) {
var curCard = subclassOfCollection_1_1.value;
// make sure it is a cardinality (it could also be an Iri of a superclass)
if (curCard instanceof Object && curCard['@type'] !== undefined && curCard['@type'] === Constants.Restriction) {
var newCard = void 0;
// get occurrence
if (curCard[Constants.MinCardinality] !== undefined) {
newCard = new Cardinality(CardinalityOccurrence.minCard, curCard[Constants.MinCardinality], curCard[Constants.OnProperty]['@id']);
}
else if (curCard[Constants.Cardinality] !== undefined) {
newCard = new Cardinality(CardinalityOccurrence.card, curCard[Constants.Cardinality], curCard[Constants.OnProperty]['@id']);
}
else if (curCard[Constants.MaxCardinality] !== undefined) {
newCard = new Cardinality(CardinalityOccurrence.maxCard, curCard[Constants.MaxCardinality], curCard[Constants.OnProperty]['@id']);
}
else {
// no known occurrence found
throw new TypeError("cardinality type invalid for " + resClass['@id'] + " " + curCard[Constants.OnProperty]);
}
// add cardinality
cardinalities.push(newCard);
// get gui order
var newGuiOrder = void 0;
if (curCard[Constants.GuiOrder] !== undefined) {
newGuiOrder = new GuiOrder(curCard[Constants.GuiOrder], curCard[Constants.OnProperty]['@id']);
// add gui order
guiOrder.push(newGuiOrder);
}
}
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (subclassOfCollection_1_1 && !subclassOfCollection_1_1.done && (_b = subclassOfCollection_1.return)) _b.call(subclassOfCollection_1);
}
finally { if (e_4) throw e_4.error; }
}
}
var resClassObj = new ResourceClass(resClassIri, resClass[Constants.ResourceIcon], resClass[Constants.Comment], resClass[Constants.Label], cardinalities, guiOrder);
// write this resource class definition to the cache object
this.cacheOntology.resourceClasses[resClassIri] = resClassObj;
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (resourceClassDefinitions_1_1 && !resourceClassDefinitions_1_1.done && (_a = resourceClassDefinitions_1.return)) _a.call(resourceClassDefinitions_1);
}
finally { if (e_3) throw e_3.error; }
}
// cache the property definitions
this.convertAndWriteKnoraPropertyDefinitionsToOntologyCache(propertyClassDefinitions);
};
/**
* Gets information about resource classes from the cache.
* The answer includes the property definitions referred to by the cardinalities of the given resource classes.
*
* @param {string[]} resClassIris the given resource class Iris
* @returns Observable<OntologyInformation> - an [[OntologyCache]] representing the requested resource classes.
*/
OntologyCacheService.prototype.getResourceClassDefinitionsFromCache = function (resClassIris) {
// collect the definitions for each resource class from the cache
var _this = this;
var resClassDefs = new ResourceClasses();
// collect the properties from the cardinalities of the given resource classes
var propertyIris = [];
resClassIris.forEach(function (resClassIri) {
resClassDefs[resClassIri] = _this.cacheOntology.resourceClasses[resClassIri];
_this.cacheOntology.resourceClasses[resClassIri].cardinalities.forEach(function (card) {
// get property definition for each cardinality
propertyIris.push(card.property);
});
});
return this.getPropertyDefinitions(propertyIris).pipe(map(function (propDefs) {
return new OntologyInformation(new ResourceClassIrisForOntology(), resClassDefs, propDefs.getProperties());
}));
};
/**
* Converts a Knora response for ontology information about properties
* into an internal representation and cache it.
*
* @param {object[]} propertyDefinitionsFromKnora the property definitions returned by Knora
* @returns void
*/
OntologyCacheService.prototype.convertAndWriteKnoraPropertyDefinitionsToOntologyCache = function (propertyDefinitionsFromKnora) {
var e_5, _a, e_6, _b;
try {
// convert and cache each given property definition
for (var propertyDefinitionsFromKnora_1 = tslib_1.__values(propertyDefinitionsFromKnora), propertyDefinitionsFromKnora_1_1 = propertyDefinitionsFromKnora_1.next(); !propertyDefinitionsFromKnora_1_1.done; propertyDefinitionsFromKnora_1_1 = propertyDefinitionsFromKnora_1.next()) {
var propDef = propertyDefinitionsFromKnora_1_1.value;
var propIri = propDef['@id'];
var isEditable = false;
if (propDef[Constants.IsEditable] !== undefined && propDef[Constants.IsEditable] === true) {
isEditable = true;
}
var isLinkProperty = false;
if (propDef[Constants.IsLinkProperty] !== undefined && propDef[Constants.IsLinkProperty] === true) {
isLinkProperty = true;
}
var isLinkValueProperty = false;
if (propDef[Constants.IsLinkValueProperty] !== undefined && propDef[Constants.IsLinkValueProperty] === true) {
isLinkValueProperty = true;
}
var subPropertyOf = [];
if (propDef[Constants.SubPropertyOf] !== undefined && Array.isArray(propDef[Constants.SubPropertyOf])) {
subPropertyOf = propDef[Constants.SubPropertyOf].map(function (superProp) { return superProp['@id']; });
}
else if (propDef[Constants.SubPropertyOf] !== undefined) {
subPropertyOf.push(propDef[Constants.SubPropertyOf]['@id']);
}
var objectType = void 0;
if (propDef[Constants.ObjectType] !== undefined) {
objectType = propDef[Constants.ObjectType]['@id'];
}
var guiAttribute = [];
if (propDef[Constants.GuiAttribute] !== undefined) {
if (Array.isArray(propDef[Constants.GuiAttribute])) {
try {
for (var _c = tslib_1.__values(propDef[Constants.GuiAttribute]), _d = _c.next(); !_d.done; _d = _c.next()) {
var attr = _d.value;
guiAttribute.push(attr);
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
}
finally { if (e_6) throw e_6.error; }
}
}
else {
guiAttribute.push(propDef[Constants.GuiAttribute]);
}
}
// cache property definition
this.cacheOntology.properties[propIri] = new Property(propIri, objectType, propDef[Constants.Comment], propDef[Constants.Label], subPropertyOf, isEditable, isLinkProperty, isLinkValueProperty, guiAttribute);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (propertyDefinitionsFromKnora_1_1 && !propertyDefinitionsFromKnora_1_1.done && (_a = propertyDefinitionsFromKnora_1.return)) _a.call(propertyDefinitionsFromKnora_1);
}
finally { if (e_5) throw e_5.error; }
}
};
/**
* Returns property definitions from the cache.
*
* @param {string[]} propertyIris the property definitions to be returned.
* @returns OntologyInformation - requested property defintions.
*/
OntologyCacheService.prototype.getPropertyDefinitionsFromCache = function (propertyIris) {
var _this = this;
var propertyDefs = new Properties();
propertyIris.forEach(function (propIri) {
// ignore non Knora props: if propIri is contained in excludedProperties, skip this propIri
if (_this.excludedProperties.indexOf(propIri) > -1) {
return;
}
if (_this.cacheOntology.properties[propIri] === undefined) {
throw new OntologyCacheError("getPropertyDefinitionsFromCache: property not found in cache: " + propIri);
}
propertyDefs[propIri] = _this.cacheOntology.properties[propIri];
});
return new OntologyInformation(new ResourceClassIrisForOntology(), new ResourceClasses(), propertyDefs);
};
/**
* Returns metadata about all ontologies.
*
* @returns Observable<Array<OntologyMetadata>> - metadata about all ontologies.
*/
OntologyCacheService.prototype.getOntologiesMetadata = function () {
var _this = this;
if (this.cacheOntology.ontologies.length === 0) {
// nothing in cache yet, get metadata from Knora
return this.getOntologiesMetadataFromKnora().pipe(map(function (metadata) {
_this.convertAndWriteOntologiesMetadataToCache(metadata['@graph'].filter(function (onto) {
// ignore excluded ontologies
return _this.excludedOntologies.indexOf(onto['@id']) === -1;
}));
return _this.getAllOntologiesMetadataFromCache();
}));
}
else {
// return metadata from cache
return of(this.getAllOntologiesMetadataFromCache());
}
};
/**
* Requests the requested ontologies from Knora, adding them to the cache.
*
* @param {string[]} ontologyIris Iris of the ontologies to be requested.
* @returns Observable<any[]>
*/
OntologyCacheService.prototype.getAndCacheOntologies = function (ontologyIris) {
var _this = this;
// array to be populated with Observables
var observables = [];
// do a request for each ontology
ontologyIris.forEach(function (ontologyIri) {
// push an Observable onto `observables`
observables.push(_this.getAllEntityDefinitionsForOntologyFromKnora(ontologyIri).pipe(map(function (ontology) {
// write response to cache
_this.convertAndWriteAllEntityDefinitionsForOntologyToCache(ontology);
})));
});
// forkJoin returns an Observable of an array of results
// returned by each Observable contained in `observables`
// a subscription to the Observable returned by forkJoin is executed
// once all Observables have been completed
return forkJoin(observables);
};
/**
* Returns the entity definitions for the requested ontologies.
*
* @param {string[]} ontologyIris Iris of the ontologies to be queried.
* @returns Observable<OntologyInformation> - all ontology metadata from the cache
*/
OntologyCacheService.prototype.getEntityDefinitionsForOntologies = function (ontologyIris) {
var _this = this;
var ontologyIrisToQuery = ontologyIris.filter(function (ontologyIri) {
// return the ontology Iris that are not cached yet
return _this.cacheOntology.resourceClassIrisForOntology[ontologyIri] === undefined;
});
// get ontologies that are mot cached yet
if (ontologyIrisToQuery.length > 0) {
return this.getAndCacheOntologies(ontologyIrisToQuery).pipe(mergeMap(function () {
// executed once all ontologies have been cached
return _this.getOntologyInformationFromCache(ontologyIris);
}));
}
else {
return this.getOntologyInformationFromCache(ontologyIris);
}
};
/**
* Returns the definitions for the given resource class Iris.
* If the definitions are not already in the cache, the will be retrieved from Knora and cached.
*
* Properties contained in the cardinalities will be returned too.
*
* @param {string[]} resourceClassIris the given resource class Iris
* @returns Observable<OntologyInformation> - the requested resource classes (including properties).
*/
OntologyCacheService.prototype.getResourceClassDefinitions = function (resourceClassIris) {
var _this = this;
var resClassIrisToQueryFor = resourceClassIris.filter(function (resClassIri) {
// return the resource class Iris that are not cached yet
return _this.cacheOntology.resourceClasses[resClassIri] === undefined;
});
if (resClassIrisToQueryFor.length > 0) {
// get a set of ontology Iris that have to be queried to obtain the missing resource classes
var ontologyIris = resClassIrisToQueryFor.map(function (resClassIri) {
return Utils.getOntologyIriFromEntityIri(resClassIri);
}).filter(Utils.filterOutDuplicates);
// obtain missing resource class information
return this.getAndCacheOntologies(ontologyIris).pipe(mergeMap(function () {
return _this.getResourceClassDefinitionsFromCache(resourceClassIris);
}));
}
else {
return this.getResourceClassDefinitionsFromCache(resourceClassIris);
}
};
/**
* Get definitions for the given property Iris.
* If the definitions are not already in the cache, the will be retrieved from Knora and cached.
*
* @param {string[]} propertyIris the Iris of the properties to be returned .
* @returns Observable<OntologyInformation> - the requested property definitions.
*/
OntologyCacheService.prototype.getPropertyDefinitions = function (propertyIris) {
var _this = this;
var propertiesToQuery = propertyIris.filter(function (propIri) {
// ignore non Knora props: if propIri is contained in excludedProperties, skip this propIri
if (_this.excludedProperties.indexOf(propIri) > -1) {
return false;
}
// return the property Iris that are not cached yet
return _this.cacheOntology.properties[propIri] === undefined;
});
if (propertiesToQuery.length > 0) {
// get a set of ontology Iris that have to be queried to obtain the missing properties
var ontologyIris = propertiesToQuery.map(function (propIri) {
return Utils.getOntologyIriFromEntityIri(propIri);
}).filter(Utils.filterOutDuplicates);
// obtain missing resource class information
return this.getAndCacheOntologies(ontologyIris).pipe(map(function (results) {
if (results) {
return _this.getPropertyDefinitionsFromCache(propertyIris);
}
else {
throw new Error('Problem with: return this.getPropertyDefinitionsFromCache(propertyIris);');
}
}));
}
else {
return of(this.getPropertyDefinitionsFromCache(propertyIris));
}
};
OntologyCacheService.ctorParameters = function () { return [
{ type: OntologyService }
]; };
OntologyCacheService.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function OntologyCacheService_Factory() { return new OntologyCacheService(i0.ɵɵinject(i1.OntologyService)); }, token: OntologyCacheService, providedIn: "root" });
OntologyCacheService = tslib_1.__decorate([
Injectable({
providedIn: 'root'
}),
tslib_1.__metadata("design:paramtypes", [OntologyService])
], OntologyCacheService);
return OntologyCacheService;
}());
export { OntologyCacheService };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib250b2xvZ3ktY2FjaGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0Brbm9yYS9jb3JlLyIsInNvdXJjZXMiOlsibGliL3NlcnZpY2VzL3YyL29udG9sb2d5LWNhY2hlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN2QyxPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEQsT0FBTyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUcvQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFakQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDOzs7QUFHckQsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBRWpDOzs7Ozs7R0FNRztBQUNIO0lBQWlDLDhDQUFLO0lBRWxDLDRCQUFxQixPQUFlO1FBQXBDLFlBQ0ksa0JBQU0sT0FBTyxDQUFDLFNBQ2pCO1FBRm9CLGFBQU8sR0FBUCxPQUFPLENBQVE7O0lBRXBDLENBQUM7SUFDTCx5QkFBQztBQUFELENBQUMsQUFMRCxDQUFpQyxLQUFLLEdBS3JDO0FBR0Q7OztHQUdHO0FBQ0g7SUFFSTs7Ozs7T0FLRztJQUNILDBCQUFxQixFQUFVLEVBQ2xCLEtBQWE7UUFETCxPQUFFLEdBQUYsRUFBRSxDQUFRO1FBQ2xCLFVBQUssR0FBTCxLQUFLLENBQVE7SUFFMUIsQ0FBQztJQUVMLHVCQUFDO0FBQUQsQ0FBQyxBQWJELElBYUM7O0FBR0Q7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxxQkFJWDtBQUpELFdBQVkscUJBQXFCO0lBQzdCLHVFQUFXLENBQUE7SUFDWCxpRUFBUSxDQUFBO0lBQ1Is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