@knora/core
Version:
Knora ui module: core
1,292 lines (1,266 loc) • 85.9 kB
JavaScript
import { __decorate, __param, __metadata } from 'tslib';
import { InjectionToken, NgModule, Inject, ɵɵdefineInjectable, ɵɵinject, Injectable } from '@angular/core';
import { Constants, KnoraApiConnection, KnoraApiConfig } from '@knora/api';
import * as momentImported from 'moment';
import { JsonConvert, OperationMode, ValueCheckingMode } from 'json2typescript';
import { BehaviorSubject, from, Observable, of, forkJoin } from 'rxjs';
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { throwError } from 'rxjs/internal/observable/throwError';
import { map, catchError, mergeMap } from 'rxjs/operators';
var KuiCoreModule_1;
// config for knora-api-js-lib (@knora/api)
const KnoraApiConfigToken = new InjectionToken('Knora api configuration');
// connection config for knora-api-js-lib (@knora/api)
const KnoraApiConnectionToken = new InjectionToken('Knora api connection configuration');
// config for knora-ui (@knora/action, @knora/search, @knora/viewer)
const KuiConfigToken = new InjectionToken('Main configuration for knora-ui modules');
let KuiCoreModule = KuiCoreModule_1 = class KuiCoreModule {
static forRoot(kuiConfig) {
// get the app environment configuration here
// console.log('KuiCoreModule - forRoot - config: ', config);
return {
ngModule: KuiCoreModule_1,
providers: [
{ provide: KuiConfigToken, useValue: kuiConfig }
]
};
}
};
KuiCoreModule = KuiCoreModule_1 = __decorate([
NgModule({
imports: [],
declarations: [],
exports: []
})
], KuiCoreModule);
class KuiConfig {
constructor(knora, app) {
this.knora = knora;
this.app = app;
}
}
const moment = momentImported;
let SessionService = class SessionService {
constructor(knoraApiConnection, knoraApiConfig) {
this.knoraApiConnection = knoraApiConnection;
this.knoraApiConfig = knoraApiConfig;
/**
* max session time in milliseconds
* default value (24h): 86400000
*
*/
this.MAX_SESSION_TIME = 86400000; // 1d = 24 * 60 * 60 * 1000
}
/**
* set the session by using the json web token (jwt) and the user object;
* it will be used in the login process
*
* @param jwt
* @param username
*/
setSession(jwt, identifier, identifierType) {
let session;
this.updateKnoraApiConnection(jwt);
// get user information
this.knoraApiConnection.admin.usersEndpoint.getUser(identifierType, identifier).subscribe((response) => {
let sysAdmin = false;
const projectAdmin = [];
// get permission inforamation: a) is user sysadmin? b) get list of project iris where user is project admin
const groupsPerProjectKeys = Object.keys(response.body.user.permissions.groupsPerProject);
for (const key of groupsPerProjectKeys) {
if (key === Constants.SystemProjectIRI) {
sysAdmin = response.body.user.permissions.groupsPerProject[key].indexOf(Constants.SystemAdminGroupIRI) > -1;
}
if (response.body.user.permissions.groupsPerProject[key].indexOf(Constants.ProjectAdminGroupIRI) > -1) {
projectAdmin.push(key);
}
}
// store session information in browser's localstorage
session = {
id: this.setTimestamp(),
user: {
name: response.body.user.username,
jwt: jwt,
lang: response.body.user.lang,
sysAdmin: sysAdmin,
projectAdmin: projectAdmin
}
};
// update localStorage
localStorage.setItem('session', JSON.stringify(session));
}, (error) => {
localStorage.removeItem('session');
console.error(error);
});
}
/**
* Validate intern session and check knora api credentials if necessary.
* If a json web token exists, it doesn't mean, that the knora api credentials are still valid.
*
* @returns boolean
*/
validateSession() {
// mix of checks with session.validation and this.authenticate
const session = JSON.parse(localStorage.getItem('session'));
const tsNow = this.setTimestamp();
if (session) {
this.updateKnoraApiConnection(session.user.jwt);
// check if the session is still valid:
if (session.id + this.MAX_SESSION_TIME <= tsNow) {
// the internal (knora-ui) session has expired
// check if the api credentails are still valid
// console.error('session is not valid; check knora api credentials');
this.knoraApiConnection.v2.auth.checkCredentials().subscribe((response) => {
// the knora api credentials are still valid
// console.log('knora api credentials', response);
// refresh the jwt in @knora/api
this.updateKnoraApiConnection(session.user.jwt);
// update the session.id
session.id = tsNow;
localStorage.setItem('session', JSON.stringify(session));
// console.log('knora api credentials are valid; return', true);
return true;
}, (error) => {
// a user is not authenticated anymore!
// console.error('session.service -- validateSession -- authenticate: the session expired on API side');
this.destroySession();
// console.warn('knora api credentials are not valid; return', false);
return false;
});
}
else {
// the internal (knora-ui) session is still valid
// console.log('session is valid; return', true);
return true;
}
}
else {
// no session found; update knora api connection with empty jwt
this.updateKnoraApiConnection();
// console.warn('session is not valid; return', false);
return false;
}
}
/**
* update the session storage
* @param jwt
* @param username
*
* @returns boolean
*/
updateSession(jwt, username) {
if (jwt && username) {
this.setSession(jwt, username, 'username');
return true;
}
else {
return false;
}
}
/**
* Destroy session by removing the session from local storage
*
*/
destroySession() {
localStorage.removeItem('session');
}
/**
* Update the knora-api-config and knora-api-connection of @knora/api
*
* @param {string} jwt?
*/
updateKnoraApiConnection(jwt) {
this.knoraApiConfig.jsonWebToken = (jwt ? jwt : '');
this.knoraApiConnection = new KnoraApiConnection(this.knoraApiConfig);
}
/**
* Convert a timestamp in a number
* @returns number
*/
setTimestamp() {
return (moment().add(0, 'second')).valueOf();
}
};
SessionService.ctorParameters = () => [
{ type: KnoraApiConnection, decorators: [{ type: Inject, args: [KnoraApiConnectionToken,] }] },
{ type: KnoraApiConfig, decorators: [{ type: Inject, args: [KnoraApiConfigToken,] }] }
];
SessionService.ngInjectableDef = ɵɵdefineInjectable({ factory: function SessionService_Factory() { return new SessionService(ɵɵinject(KnoraApiConnectionToken), ɵɵinject(KnoraApiConfigToken)); }, token: SessionService, providedIn: "root" });
SessionService = __decorate([
Injectable({
providedIn: 'root'
}),
__param(0, Inject(KnoraApiConnectionToken)),
__param(1, Inject(KnoraApiConfigToken)),
__metadata("design:paramtypes", [KnoraApiConnection,
KnoraApiConfig])
], SessionService);
/**
* @deprecated Use ApiResponseData from `@knora/api` (github:dasch-swiss/knora-api-js-lib) instead
* Result class used as API url response in ApiService
*/
class ApiServiceResult {
constructor() {
/**
* Status number
*/
this.status = 0;
/**
* Status text
*/
this.statusText = '';
/**
* API url
*/
this.url = '';
}
/**
* Gets the result body as instance of classObject.
* @param classObject
* @returns {any}
* @throws
*/
getBody(classObject) {
// console.log(this.body);
return ApiServiceResult.jsonConvert.deserialize(this.body, classObject);
}
}
ApiServiceResult.jsonConvert = new JsonConvert(OperationMode.ENABLE, ValueCheckingMode.ALLOW_NULL);
/**
* @deprecated Use ApiResponseError from `@knora/api` (github:dasch-swiss/knora-api-js-lib) instead
*
* Error class used as API response in ApiService
*/
class ApiServiceError {
constructor() {
/**
* Status number
*/
this.status = 0;
/**
* Status text
*/
this.statusText = '';
/**
* API url
*/
this.url = '';
/**
* Additional error info
*/
this.errorInfo = '';
}
}
class KnoraConstants {
}
// The following version of Knora is needed to work properly with this module
KnoraConstants.KnoraVersion = '12.0.0';
KnoraConstants.KnoraApi = 'http://api.knora.org/ontology/knora-api';
KnoraConstants.PathSeparator = '#';
// Simple
KnoraConstants.KnoraApiV2SimplePath = KnoraConstants.KnoraApi + '/simple/v2' + KnoraConstants.PathSeparator;
KnoraConstants.resourceSimple = KnoraConstants.KnoraApiV2SimplePath + 'Resource';
KnoraConstants.dateSimple = KnoraConstants.KnoraApiV2SimplePath + 'Date';
KnoraConstants.intervalSimple = KnoraConstants.KnoraApiV2SimplePath + 'Interval';
KnoraConstants.geomSimple = KnoraConstants.KnoraApiV2SimplePath + 'Geom';
KnoraConstants.colorSimple = KnoraConstants.KnoraApiV2SimplePath + 'Color';
KnoraConstants.geonameSimple = KnoraConstants.KnoraApiV2SimplePath + 'Geoname';
KnoraConstants.fileSimple = KnoraConstants.KnoraApiV2SimplePath + 'File';
KnoraConstants.listNodeSimple = KnoraConstants.KnoraApiV2SimplePath + 'ListNode';
// comparison operators --> TODO: should be moved to search-module!?
KnoraConstants.EqualsComparisonOperator = '=';
KnoraConstants.EqualsComparisonLabel = 'is equal to';
KnoraConstants.NotEqualsComparisonOperator = '!=';
KnoraConstants.NotEqualsComparisonLabel = 'is not equal to';
KnoraConstants.GreaterThanComparisonOperator = '>';
KnoraConstants.GreaterThanComparisonLabel = 'is greater than';
KnoraConstants.GreaterThanEqualsComparisonOperator = '>=';
KnoraConstants.GreaterThanEqualsComparisonLabel = 'is greater than equals to';
KnoraConstants.LessThanComparisonOperator = '<';
KnoraConstants.LessThanComparisonLabel = 'is less than';
KnoraConstants.LessThanEqualsComparisonOperator = '<=';
KnoraConstants.LessThanQualsComparisonLabel = 'is less than equals to';
KnoraConstants.ExistsComparisonOperator = 'E';
KnoraConstants.ExistsComparisonLabel = 'exists';
KnoraConstants.LikeComparisonOperator = 'regex';
KnoraConstants.LikeComparisonLabel = 'is like';
KnoraConstants.MatchComparisonOperator = 'contains';
KnoraConstants.MatchComparisonLabel = 'matches';
KnoraConstants.MatchFunction = KnoraConstants.KnoraApi + '/v2' + KnoraConstants.PathSeparator + 'match';
// Knora Schema
var KnoraSchema;
(function (KnoraSchema) {
KnoraSchema[KnoraSchema["complex"] = 0] = "complex";
KnoraSchema[KnoraSchema["simple"] = 1] = "simple";
})(KnoraSchema || (KnoraSchema = {}));
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
*
* Represents the parameters of an extended search.
*/
class ExtendedSearchParams {
/**
*
* @param generateGravsearch a function that generates a Gravsearch query.
*
* The function takes the offset
* as a parameter and returns a Gravsearch query string.
* Returns false if not set correctly (init state).
*/
constructor(generateGravsearch) {
this.generateGravsearch = generateGravsearch;
}
}
let SearchParamsService =
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
* Temporarily stores the parameters of an extended search.
*/
class SearchParamsService {
constructor() {
// init with a dummy function that returns false
// if the application is reloaded, this will be returned
this._currentSearchParams = new BehaviorSubject(new ExtendedSearchParams((offset) => false));
}
/**
* Updates the parameters of an extended search.
*
* @param {ExtendedSearchParams} searchParams
* @returns void
*/
changeSearchParamsMsg(searchParams) {
this._currentSearchParams.next(searchParams);
}
/**
* Gets the search params of an extended search.
*
* @returns ExtendedSearchParams - search parameters
*/
getSearchParams() {
return this._currentSearchParams.getValue();
}
};
SearchParamsService.ngInjectableDef = ɵɵdefineInjectable({ factory: function SearchParamsService_Factory() { return new SearchParamsService(); }, token: SearchParamsService, providedIn: "root" });
SearchParamsService = __decorate([
Injectable({
providedIn: 'root'
})
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
* Temporarily stores the parameters of an extended search.
*/
,
__metadata("design:paramtypes", [])
], SearchParamsService);
var GravsearchGenerationService_1;
/**
* @deprecated Use new service from `@knora/api` (github:dasch-swiss/knora-api-js-lib) instead
*
* Create GravSearch queries from provided parameters.
*/
let GravsearchGenerationService = GravsearchGenerationService_1 = class GravsearchGenerationService {
constructor(_searchParamsService) {
this._searchParamsService = _searchParamsService;
}
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
*
* Generates a Gravsearch query from the provided arguments.
*
* @param {PropertyWithValue[]} properties the properties specified by the user.
* @param {string} [mainResourceClassOption] the class of the main resource, if specified.
* @param {number} offset the offset to be used (nth page of results).
* @returns string - a KnarQL query string.
*/
createGravsearchQuery(properties, mainResourceClassOption, offset = 0) {
// class restriction for the resource searched for
let mainResourceClass = '';
// if given, create the class restriction for the main resource
if (mainResourceClassOption !== undefined) {
mainResourceClass = `?mainRes a <${mainResourceClassOption}> .`;
}
// criteria for the order by statement
const orderByCriteria = [];
// statements to be returned in query results
const returnStatements = [];
// loop over given properties and create statements and filters from them
const props = properties.map((propWithVal, index) => {
// represents the object of a statement
let propValue;
if (!propWithVal.property.isLinkProperty || propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Exists') {
// it is not a linking property, create a variable for the value (to be used by a subsequent FILTER)
// OR the comparison operator Exists is used in which case we do not need to specify the object any further
propValue = `?propVal${index}`;
}
else {
// it is a linking property and the comparison operator is not Exists, use its IRI
propValue = propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex);
}
// generate statement
let statement = `?mainRes <${propWithVal.property.id}> ${propValue} .`;
// check if it is a linking property that has to be wrapped in a FILTER NOT EXISTS (comparison operator NOT_EQUALS) to negate it
if (propWithVal.property.isLinkProperty && propWithVal.valueLiteral.comparisonOperator.getClassName() === 'NotEquals') {
// do not include statement in results, because the query checks for the absence of this statement
statement = `FILTER NOT EXISTS {
${statement}
}`;
}
else {
// TODO: check if statement should be returned returned in results (Boolean flag from checkbox)
returnStatements.push(statement);
statement = `
${statement}
`;
}
// generate restricting expression (e.g., a FILTER) if comparison operator is not Exists
let restriction = '';
// only create a FILTER if the comparison operator is not EXISTS and it is not a linking property
if (!propWithVal.property.isLinkProperty && propWithVal.valueLiteral.comparisonOperator.getClassName() !== 'Exists') {
// generate variable for value literal
const propValueLiteral = `${propValue}Literal`;
if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Like') {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// use regex function for LIKE
restriction += `FILTER regex(${propValueLiteral}, ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)}, "i")`;
}
else if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'Match') {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// use contains function for MATCH
restriction += `FILTER <${KnoraConstants.MatchFunction}>(${propValueLiteral}, ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
else if (propWithVal.property.objectType === Constants.DateValue) {
// handle date property
restriction = `FILTER(knora-api:toSimpleDate(${propValue}) ${propWithVal.valueLiteral.comparisonOperator.type} ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
else if (propWithVal.property.objectType === Constants.ListValue) {
// handle list node
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)}` + '\n';
// check for comparison operator "not equals"
if (propWithVal.valueLiteral.comparisonOperator.getClassName() === 'NotEquals') {
restriction = `FILTER NOT EXISTS {
${restriction}
}`;
}
}
else {
// generate statement to value literal
restriction = `${propValue} <${GravsearchGenerationService_1.complexTypeToProp[propWithVal.property.objectType]}> ${propValueLiteral}` + '\n';
// generate filter expression
restriction += `FILTER(${propValueLiteral} ${propWithVal.valueLiteral.comparisonOperator.type} ${propWithVal.valueLiteral.value.toSparql(KnoraSchema.complex)})`;
}
}
// check if current value is a sort criterion
if (propWithVal.isSortCriterion)
orderByCriteria.push(propValue);
return `${statement}
${restriction}
`;
});
let orderByStatement = '';
if (orderByCriteria.length > 0) {
orderByStatement = `
ORDER BY ${orderByCriteria.join(' ')}
`;
}
// template of the Gravsearch query with dynamic components
const gravsearchTemplate = `
PREFIX knora-api: <http://api.knora.org/ontology/knora-api/v2#>
CONSTRUCT {
?mainRes knora-api:isMainResource true .
${returnStatements.join('\n')}
} WHERE {
?mainRes a knora-api:Resource .
${mainResourceClass}
${props.join('')}
}
${orderByStatement}`;
// offset component of the Gravsearch query
const offsetTemplate = `
OFFSET ${offset}
`;
// function that generates the same KnarQL query with the given offset
const generateGravsearchQueryWithCustomOffset = (localOffset) => {
const offsetCustomTemplate = `
OFFSET ${localOffset}
`;
return gravsearchTemplate + offsetCustomTemplate;
};
if (offset === 0) {
// store the function so another KnarQL query can be created with an increased offset
this._searchParamsService.changeSearchParamsMsg(new ExtendedSearchParams(generateGravsearchQueryWithCustomOffset));
}
return gravsearchTemplate + offsetTemplate;
}
};
/**
* @ignore
*
* Map of complex knora-api value types to simple ones.
* Use computed property name: http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
*/
GravsearchGenerationService.typeConversionComplexToSimple = {
'http://api.knora.org/ontology/knora-api/v2#IntValue': Constants.XsdInteger,
'http://api.knora.org/ontology/knora-api/v2#DecimalValue': Constants.XsdDecimal,
'http://api.knora.org/ontology/knora-api/v2#BooleanValue': Constants.XsdBoolean,
'http://api.knora.org/ontology/knora-api/v2#TextValue': Constants.XsdString,
'http://api.knora.org/ontology/knora-api/v2#UriValue': Constants.XsdAnyUri,
'http://api.knora.org/ontology/knora-api/v2#DateValue': KnoraConstants.dateSimple,
'http://api.knora.org/ontology/knora-api/v2#IntervalValue': KnoraConstants.intervalSimple,
'http://api.knora.org/ontology/knora-api/v2#GeomValue': KnoraConstants.geomSimple,
'http://api.knora.org/ontology/knora-api/v2#ColorValue': KnoraConstants.colorSimple,
'http://api.knora.org/ontology/knora-api/v2#GeonameValue': KnoraConstants.geonameSimple,
'http://api.knora.org/ontology/knora-api/v2#StillImageFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#FileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#MovingImageFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#DDDFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#AudioFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#DocumentFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#TextFileValue': KnoraConstants.fileSimple,
'http://api.knora.org/ontology/knora-api/v2#ListValue': KnoraConstants.listNodeSimple
};
GravsearchGenerationService.complexTypeToProp = {
'http://api.knora.org/ontology/knora-api/v2#IntValue': Constants.IntValueAsInt,
'http://api.knora.org/ontology/knora-api/v2#DecimalValue': Constants.DecimalValueAsDecimal,
'http://api.knora.org/ontology/knora-api/v2#BooleanValue': Constants.BooleanValueAsBoolean,
'http://api.knora.org/ontology/knora-api/v2#TextValue': Constants.ValueAsString,
'http://api.knora.org/ontology/knora-api/v2#UriValue': Constants.UriValueAsUri,
'http://api.knora.org/ontology/knora-api/v2#ListValue': Constants.ListValueAsListNode
};
GravsearchGenerationService.ctorParameters = () => [
{ type: SearchParamsService }
];
GravsearchGenerationService.ngInjectableDef = ɵɵdefineInjectable({ factory: function GravsearchGenerationService_Factory() { return new GravsearchGenerationService(ɵɵinject(SearchParamsService)); }, token: GravsearchGenerationService, providedIn: "root" });
GravsearchGenerationService = GravsearchGenerationService_1 = __decorate([
Injectable({
providedIn: 'root'
}),
__metadata("design:paramtypes", [SearchParamsService])
], GravsearchGenerationService);
class Equals {
constructor() {
this.type = KnoraConstants.EqualsComparisonOperator;
this.label = KnoraConstants.EqualsComparisonLabel;
}
getClassName() {
return 'Equals';
}
}
class NotEquals {
constructor() {
this.type = KnoraConstants.NotEqualsComparisonOperator;
this.label = KnoraConstants.NotEqualsComparisonLabel;
}
getClassName() {
return 'NotEquals';
}
}
class GreaterThanEquals {
constructor() {
this.type = KnoraConstants.GreaterThanEqualsComparisonOperator;
this.label = KnoraConstants.GreaterThanEqualsComparisonLabel;
}
getClassName() {
return 'GreaterThanEquals';
}
}
class GreaterThan {
constructor() {
this.type = KnoraConstants.GreaterThanComparisonOperator;
this.label = KnoraConstants.GreaterThanComparisonLabel;
}
getClassName() {
return 'GreaterThan';
}
}
class LessThan {
constructor() {
this.type = KnoraConstants.LessThanComparisonOperator;
this.label = KnoraConstants.LessThanComparisonLabel;
}
getClassName() {
return 'LessThan';
}
}
class LessThanEquals {
constructor() {
this.type = KnoraConstants.LessThanEqualsComparisonOperator;
this.label = KnoraConstants.LessThanQualsComparisonLabel;
}
getClassName() {
return 'LessThanEquals';
}
}
class Exists {
constructor() {
this.type = KnoraConstants.ExistsComparisonOperator;
this.label = KnoraConstants.ExistsComparisonLabel;
}
getClassName() {
return 'Exists';
}
}
class Like {
constructor() {
this.type = KnoraConstants.LikeComparisonOperator;
this.label = KnoraConstants.LikeComparisonLabel;
}
getClassName() {
return 'Like';
}
}
class Match {
constructor() {
this.type = KnoraConstants.MatchComparisonOperator;
this.label = KnoraConstants.MatchComparisonLabel;
}
getClassName() {
return 'Match';
}
}
/**
* Combination of a comparison operator and a value literal or an IRI.
* In case the comparison operator is 'Exists', no value is given.
*/
class ComparisonOperatorAndValue {
constructor(comparisonOperator, value) {
this.comparisonOperator = comparisonOperator;
this.value = value;
}
}
/**
* Represents a property's value as a literal with the indication of its type.
*/
class ValueLiteral {
/**
* Constructs a [ValueLiteral].
*
* @param {string} value the literal representation of the value.
* @param {string} type the type of the value (making use of xsd).
*/
constructor(value, type) {
this.value = value;
this.type = type;
}
/**
* Creates a type annotated value literal to be used in a SPARQL query.
*
* @param schema indicates the Knora schema to be used.
* @returns {string}
*/
toSparql(schema) {
let literalType;
// check if a Knora schema conversion is necessary, e.g., knora-api:dateValue (complex) to knora-api:date (simple).
// xsd types will remain unchanged
if (schema === KnoraSchema.simple && GravsearchGenerationService.typeConversionComplexToSimple[this.type] !== undefined) {
// convert to simple schema
literalType = GravsearchGenerationService.typeConversionComplexToSimple[this.type];
}
else {
// do not convert
literalType = this.type;
}
return `"${this.value}"^^<${literalType}>`;
}
}
/**
* Represents an IRI.
*/
class IRI {
/**
* Constructs an [IRI].
*
* @param {string} iri the IRI of a resource instance.
*/
constructor(iri) {
this.iri = iri;
}
/**
* Creates a SPARQL representation of the IRI.
*
* @param schema indicates the Knora schema to be used.
* @returns {string}
*/
toSparql(schema) {
// this is an instance Iri and does not have to be converted.
return `<${this.iri}>`;
}
}
/**
* Represents a property, the specified comparison operator, and value.
*/
class PropertyWithValue {
/**
* Constructs a [PropertyWithValue].
*
* @param {Property} property the specified property.
* @param {ComparisonOperatorAndValue} valueLiteral the specified comparison operator and value.
* @param isSortCriterion indicates if the property is used as a sort criterion.
*/
constructor(property, valueLiteral, isSortCriterion) {
this.property = property;
this.valueLiteral = valueLiteral;
this.isSortCriterion = isSortCriterion;
}
}
/**
* Collection of useful utility functions.
*/
// @dynamic
class Utils {
/**
* Given a Knora entity IRI, gets the ontology Iri.
*
* @param {string} entityIri an entity Iri.
* @return {string} the ontology IRI
*/
static getOntologyIriFromEntityIri(entityIri) {
// split class Iri on "#"
const segments = entityIri.split(KnoraConstants.PathSeparator);
if (segments.length !== 2)
console.error(`Error: ${entityIri} is not a valid entity IRI.`);
return segments[0];
}
/**
* Converts a complex knora-api entity Iri to a knora-api simple entity Iri.
*
* @param {string} complexEntityIri
* @returns {string}
*/
static convertComplexKnoraApiEntityIritoSimple(complexEntityIri) {
// split entity Iri on "#"
const segments = complexEntityIri.split('v2' + KnoraConstants.PathSeparator);
if (segments.length !== 2)
console.error(`Error: ${complexEntityIri} is not a valid entity IRI.`);
// add 'simple' to base path
return segments[0] + 'simple/v2' + KnoraConstants.PathSeparator + segments[1];
}
}
/**
* A regex to validate Email address.
*
* @type {RegExp}
*/
Utils.RegexEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
/**
* A regex to validate Username.
*
* @type {RegExp}
*/
Utils.RegexUsername = /^[a-zA-Z0-9]+$/;
/**
* A regex to validate URLs.
*
* @type {RegExp}
*/
Utils.RegexUrl = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}(:[0-9]{1,5})?(\/.*)?$/i;
/**
* A regex to validate Passwords
*
* @type {RegExp}
*/
Utils.RegexPassword = /^(?=.*\d)(?=.*[a-zA-Z]).{8,}$/i;
/**
* A regex to validate Hexadecimal values
*
* @type {RegExp}
*/
Utils.RegexHex = /^[0-9A-Fa-f]+$/;
/**
* A regex to validate shortname in projects
*
* @type {RegExp}
*/
Utils.RegexShortname = /^[a-zA-Z]+\S*$/;
/**
* Lambda function eliminating duplicates in a collection to be passed to [[filter]].
*
* @param elem element of an Array that is currently being looked at.
* @param index current elements index.
* @param self reference to the whole Array.
* @returns {boolean} true if the same element does not already exist in the Array.
*/
Utils.filterOutDuplicates = (elem, index, self) => {
// https://stackoverflow.com/questions/16747798/delete-duplicate-elements-from-an-array
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter?v=example
// returns true if the element's index equals the index of the leftmost element
// -> this means that there is no identical element before this index, hence it is not a duplicate
// for all other elements, false is returned
return index === self.indexOf(elem);
};
/**
* Represents a region.
* Contains a reference to the resource representing the region and its geometries.
*/
class Region {
/**
*
* @param {ReadResource} regionResource a resource of type Region
*/
constructor(regionResource) {
this.regionResource = regionResource;
}
/**
* Get all geometry information belonging to this region.
*
* @returns {ReadGeomValue[]}
*/
getGeometries() {
return this.regionResource.properties[Constants.HasGeometry];
}
}
/**
* @deprecated since v 10.0.0: replaced by knora-api-js-lib
*
*/
const jsonld = require('jsonld');
const semver = require('semver');
let ApiService = class ApiService {
constructor(http, knoraApiConfig) {
this.http = http;
this.knoraApiConfig = knoraApiConfig;
// if is loading, set it true;
// it can be used in components
// for progress loader element
this.loading = false;
}
/**
* @deprecated since v9.5.0
*
* GET
*
* @param {string} path the URL for the GET request.
* @param {HttpParams} params the parameters for the GET request.
* @returns Observable of any
*/
httpGet(path, params) {
this.loading = true;
const headers = this.setHeaders();
return this.http.get(this.knoraApiConfig.apiUrl + path, { headers: headers, observe: 'response', params: params }).pipe(map((response) => {
this.loading = false;
const result = new ApiServiceResult();
result.header = { 'server': response.headers.get('Server') };
this.compareVersion(response.headers.get('Server'));
result.status = response.status;
result.statusText = response.statusText;
result.url = path;
result.body = response.body;
return result;
}), catchError((error) => {
this.loading = false;
return this.handleRequestError(error);
}));
}
/**
* @deprecated since v9.5.0
*
* Processes JSON-LD returned by Knora.
* Expands Iris and creates an empty context object.
*
* @param {ApiServiceResult} resourceResponse
*/
processJSONLD(resourceResponse) {
const resPromises = jsonld.promises;
// compact JSON-LD using an empty context: expands all Iris
const resPromise = resPromises.compact(resourceResponse.body, {});
// convert promise to Observable and return it
// https://www.learnrxjs.io/operators/creation/frompromise.html
return from(resPromise);
}
/**
* @deprecated since v9.5.0
*
* POST
*
* @param {string} path
* @param {any} body
* @returns Observable of any
*/
httpPost(path, body) {
this.loading = true;
const headers = this.setHeaders();
return this.http.post(this.knoraApiConfig.apiUrl + path, body, { headers: headers, observe: 'response' }).pipe(map((response) => {
this.loading = false;
const result = new ApiServiceResult();
result.header = { 'server': response.headers.get('Server') };
this.compareVersion(result.header.server);
result.status = response.status;
result.statusText = response.statusText;
result.url = path;
result.body = response.body;
return result;
}), catchError((error) => {
this.loading = false;
// console.error(error);
return this.handleRequestError(error);
}));
}
/**
* @deprecated since v9.5.0
*
* PUT
*
* @param {string} path
* @param {any} body
* @returns Observable of any
*/
httpPut(path, body) {
this.loading = true;
const headers = this.setHeaders();
return this.http.put(this.knoraApiConfig.apiUrl + path, body, { headers: headers, observe: 'response' }).pipe(map((response) => {
this.loading = false;
// console.log(response);
const result = new ApiServiceResult();
result.header = { 'server': response.headers.get('Server') };
this.compareVersion(result.header.server);
result.status = response.status;
result.statusText = response.statusText;
result.url = path;
result.body = response.body;
return result;
}), catchError((error) => {
this.loading = false;
// console.error(error);
return this.handleRequestError(error);
}));
}
/**
* @deprecated since v9.5.0
*
* DELETE
*
* @param {string} path
* @returns Observable of any
*/
httpDelete(path) {
this.loading = true;
const headers = this.setHeaders();
return this.http.delete(this.knoraApiConfig.apiUrl + path, { headers: headers, observe: 'response' }).pipe(map((response) => {
this.loading = false;
// console.log(response);
const result = new ApiServiceResult();
result.header = { 'server': response.headers.get('Server') };
this.compareVersion(result.header.server);
result.status = response.status;
result.statusText = response.statusText;
result.url = path;
result.body = response.body;
return result;
}), catchError((error) => {
this.loading = false;
// console.error(error);
return this.handleRequestError(error);
}));
}
/**
* handle request error in case of server error
*
* @param {HttpErrorResponse} error
* @returns Observable of ApiServiceError
*/
handleRequestError(error) {
// console.error(error);
const serviceError = new ApiServiceError();
serviceError.header = { 'server': error.headers.get('Server') };
serviceError.status = error.status;
serviceError.statusText = error.statusText;
serviceError.errorInfo = error.message;
serviceError.url = error.url;
return throwError(serviceError);
}
/**
* handle json error in case of type error in json response (json2typescript)
*
* @param {any} error
* @returns Observable of ApiServiceError
*/
handleJsonError(error) {
if (error instanceof ApiServiceError)
return throwError(error);
const serviceError = new ApiServiceError();
serviceError.header = { 'server': error.headers.get('Server') };
serviceError.status = -1;
serviceError.statusText = 'Invalid JSON';
serviceError.errorInfo = error;
serviceError.url = '';
return throwError(serviceError);
}
/**
* @deprecated since v9.5.0
*
* @param {string} server
*/
compareVersion(server) {
// expected knora api version
const expected = KnoraConstants.KnoraVersion;
// existing knora api version
if (server) {
const versions = server.split(' ');
const existing = versions[0].split('/')[1];
// compare the two versions: expected vs existing
if (semver.diff(existing, expected) === 'major') {
console.warn('The version of the @knora/core module works with Knora v' + expected + ', but you are using it with Knora v' + existing);
}
}
else {
// console.warn('No server information from headers response');
}
}
/**
* Set headers to authorise http requests
*
* This method was replaced by interceptor. But since the implementation
* of new knora-api-js-lib services the interceptor is redundant.
* As long we not all services are replaced by knora-api-js-lib
* we have to use this setHeaders "hack" for the two services left.
*
* @returns HttpHeaders
*/
setHeaders() {
const session = JSON.parse(localStorage.getItem('session'));
if (session && session !== null) {
return new HttpHeaders({
'Authorization': `Bearer ${session.user.jwt}`
});
}
else {
return new HttpHeaders();
}
}
};
ApiService.ctorParameters = () => [
{ type: HttpClient },
{ type: KnoraApiConfig, decorators: [{ type: Inject, args: [KnoraApiConfigToken,] }] }
];
ApiService.ngInjectableDef = ɵɵdefineInjectable({ factory: function ApiService_Factory() { return new ApiService(ɵɵinject(HttpClient), ɵɵinject(KnoraApiConfigToken)); }, token: ApiService, providedIn: "root" });
ApiService = __decorate([
Injectable({
providedIn: 'root',
}),
__param(1, Inject(KnoraApiConfigToken)),
__metadata("design:paramtypes", [HttpClient,
KnoraApiConfig])
], ApiService);
/**
* @deprecated since v10.0.0
*
* Will be replaced by `@knora/api` (github:knora-api-js-lib)
* Requests ontology information from Knora.
*/
let OntologyService = class OntologyService extends ApiService {
// ------------------------------------------------------------------------
// GET list of ontologies
// ------------------------------------------------------------------------
/**
* @deprecated: Use **getAllOntologies()** instead
*
* Requests the metadata about all existing ontologies from Knora's ontologies route.
*
* @returns Observable<ApiServiceResult> - the metadata of all ontologies.
*/
getOntologiesMetadata() {
return this.httpGet('/v2/ontologies/metadata');
}
/**
* Requests the metadata about all existing ontologies from Knora's ontologies route.
*
* @returns Observable<ApiServiceResult> - the metadata of all ontologies.
*/
getAllOntologies() {
return this.httpGet('/v2/ontologies/metadata');
}
/**
* Requests the ontologies of a specific project
*
* @param projectIri
* @returns Observable<ApiServiceResult> - the metadata of project ontologies.
*/
getProjectOntologies(projectIri) {
return this.httpGet('/v2/ontologies/metadata/' + encodeURIComponent(projectIri));
}
// ------------------------------------------------------------------------
// GET ontology
// ------------------------------------------------------------------------
/**
* Requests all entity definitions for the given ontologies from Knora's ontologies route.
*
* @param {string} ontologyIri the Iris of the named graphs whose resource classes are to be returned.
* @returns Observable<ApiServiceResult> - the requested ontology.
*/
getAllEntityDefinitionsForOntologies(ontologyIri) {
return this.httpGet('/v2/ontologies/allentities/' + encodeURIComponent(ontologyIri));
}
/**
* Requests information about the given resource classes from Knora's ontologies route.
*
* @param {string[]} resourceClassIris the Iris of the resource classes to be queried.
* @returns Observable<ApiServiceResult> - the requested resource class definitions.
*/
getResourceClasses(resourceClassIris) {
if (resourceClassIris.length === 0) {
// no resource class Iris are given to query for, return a failed Observer
return Observable.create(observer => observer.error('No resource class Iris given for call of OntologyService.getResourceClasses'));
}
let resClassUriEnc = '';
resourceClassIris.forEach(function (resClassIri) {
resClassUriEnc = resClassUriEnc + '/' + encodeURIComponent(resClassIri.toString());
});
return this.httpGet('/v2/ontologies/classes' + resClassUriEnc);
}
/**
* Requests properties from Knora's ontologies route.
*
* @param {string[]} propertyIris the Iris of the properties to be queried.
* @returns Observable<ApiServiceResult> - the requested properties.
*/
getProperties(propertyIris) {
if (propertyIris.length === 0) {
// no resource class Iris are given to query for, return a failed Observer
return Observable.create(observer => observer.error('No property Iris given for call of OntologyService.getProperties'));
}
let propertiesUriEnc = '';
propertyIris.forEach(function (resClassIri) {
propertiesUriEnc = propertiesUriEnc + '/' + encodeURIComponent(resClassIri.toString());
});
return this.httpGet('/v2/ontologies/properties' + propertiesUriEnc);
}
// ------------------------------------------------------------------------
// POST
// ------------------------------------------------------------------------
/**
* Create new ontology.
*
* @param {NewOntology} data Data contains: projectIri, name, label
* @returns Observable<ApiServiceResult> incl. ontolog iri and knora-api:lastModificationDate
*/
createOntology(data) {
const path = '/v2/ontologies';
const ontology = {
'knora-api:ontologyName': data.name,
'knora-api:attachedToProject': {
'@id': data.projectIri,
},
'rdfs:label': data.label,
'@context': {
'rdfs': Constants.Rdfs + Constants.Delimiter,
'knora-api': Constants.KnoraApiV2 + Constants.Delimiter
}
};
return this.httpPost(path, ontology).pipe(map((result) => result.body), catchError(this.handleJsonError));
}
createResourceClass(data) {
const path = '/v2/ontologies/classes';
// TODO: add the following values to parameter
let onto_iri;
let onto_name;
let last_onto_date;
const resourceClass = {
'@id': onto_iri,
'@type': 'owl:Ontology',
'knora-api:lastModificationDate': last_onto_date,
'@graph': [{
'@id': onto_name + ':' + data.name,
'@type': 'owl:Class',
'rdfs:label': data.labels,
'rdfs:comment': data.comments,
'rdfs:subClassOf': {
'@id': data.subClassOf
}
}],
'@context': {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'knora-api': 'http://api.knora.org/ontology/knora-api/v2#',
'owl': 'http://www.w3.org/2002/07/owl#',
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
'xsd': 'http://www.w3.org/2001/XMLSchema#',
onto_name: onto_iri + '#'
}
};
return this.httpPost(path, resourceClass).pipe(map((result) => result.body), catchError(this.handleJsonError));
}
createProperty(data) {
const path = '/v2/ontologies/properties';
// TODO: add the following values to parameter
let onto_iri;
let onto_name;
let last_onto_date;
const graph = [];
for (const prop of data) {
const prop_obj = {
'@id': onto_name + ':' + prop.name,
'@type': 'owl:ObjectProperty',
'rdfs:label': prop.labels,
'rdfs:comment': prop.comments,
'rdfs:subPropertyOf': prop.subPropertyOf,
'salsah-gui:guiElement': {
'@id': prop.guiElement
}
};
graph.push(prop_obj);
}
const property = {
'@id': onto_iri,
'@type': 'owl:Ontology',
'knora-api:lastModificationDate': last_onto_date,
'@graph': [
graph
],
'@context': {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'knora-api': 'http://api.knora.org/ontology/knora-api/v2#',
'salsah-gui': 'http://api.knora.org/ontology/salsah-gui/v2#',
'owl': 'http://www.w3.org/2002/07/owl#',
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
'xsd': 'http://www.w3.org/2001/XMLSchema#',
onto_name: onto_iri + '#'
}
};
return this.httpPost(path, property).pipe(map((result) => result.body), catchError(this.handleJsonError));
}
setCardinality(data) {
const path = '/v2/ontologies/cardinalities';
// TODO: add the following values to parameter
let class_iri;
let prop_iri;
let onto_iri;
let onto_name;
let last_onto_date;
// TODO: find a way with typescript for the following python construct
/*
let switcher = {
'1': ('owl:cardinality', 1),
'0-1': ('owl:maxCardinality', 1),
'0-n': ('owl:minCardinality', 0),
'1-n': ('owl:minCardinality', 1)
};
let occurrence: any = switcher.get(data.occurrence);
*/
const cardinality = {
'@id': onto_iri,
'@type': 'owl:Ontology',
'knora-api:lastModificationDate': last_onto_date,
'@graph': [{
'@id': class_iri,
'@type': 'owl:Class',
'rdfs:subClassOf': {
'@type': 'owl:Restriction',
// occurrence[0]: occurrence[1],
'owl:onProperty': {
'@id': prop_iri
}
}
}],
'@context': {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'knora-api': 'http://api.knora.org/ontology/knora-api/v2#',
'owl': 'http://www.w3.org/2002/07/owl#',
'rdfs': 'http://www.w3.org/2000/01/rdf-sc