Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | 17x 17x 1x 6x 7x 7x 2x 2x 2x 5x 5x 1x 1x 1x 4x 2x 2x 2x 2x 2x 5183x 1x 1x 4x 7x 3x 3x 3x 2x 2x 1x 3x 1x 1x 2x 2x 4x 4x 4x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 2x 1x 1x 3x 1x 2x 2x | import * as vscode from 'vscode';
import { IDocumentContextService } from '@src/services/document';
import { NamespaceMap } from '@src/utilities';
import { DEFAULT_PREFIXES } from '@src/services/document/prefix-downloader-service';
import { WorkspaceUri } from '@src/providers/workspace-uri';
import { getConfig } from '@src/utilities/vscode/config';
/**
* A service for looking up prefixes in the project.
*/
export class PrefixLookupService {
constructor(
private readonly extensionContext: vscode.ExtensionContext,
private readonly contextService: IDocumentContextService
) { }
/**
* Get the a namespace map for the standard W3C prefix definitions used in inference graphs.
* @returns A map of standard prefixes.
*/
getInferencePrefixes(): NamespaceMap {
return {
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'rdfs': 'http://www.w3.org/2000/01/rdf-schema#',
'owl': 'http://www.w3.org/2002/07/owl#',
'skos': 'http://www.w3.org/2004/02/skos/core#',
'shacl': 'http://www.w3.org/ns/shacl#'
}
}
/**
* Get the default prefixes from the Mentor extension configuration.
* @returns A map of default prefixes.
*/
getDefaultPrefixes(): NamespaceMap {
return this.extensionContext.globalState.get('defaultPrefixes', DEFAULT_PREFIXES).prefixes;
}
/**
* Get the prefix for a given namespace IRI.
* @param documentUri The URI of the document where the IRI is used.
* @param namespaceIri A namespace IRI to look up.
* @param defaultValue A default value to return if the prefix is not found.
* @returns A prefix for the given IRI if it is declared in the project. A default value otherwise.
*/
getPrefixForIri(documentUri: string, namespaceIri: string, defaultValue: string) {
// 1. Try to find the prefix in the document.
const documentContext = this.contextService.contexts[documentUri];
if (documentContext) {
for (const [prefix, iri] of Object.entries(documentContext.namespaces)) {
Eif (iri === namespaceIri) {
// Here we do _not_ check if the prefix is empty because it is a valid prefix within the document.
return prefix;
}
}
}
// 2. Try to find the prefix in the project configuration. We need to ensure that the prefix
// is not empty because empty prefixes are usually specific for documents.
const projectPrefixes = getConfig().get<{ defaultPrefix: string, uri: string }[]>('namespaces');
if (Array.isArray(projectPrefixes)) {
const prefix = projectPrefixes.find(namespace => namespace.uri === namespaceIri)?.defaultPrefix;
Eif (prefix) {
return this._ensureNonEmptyPrefix(prefix, defaultValue);
}
}
// 3. Try to find the prefix in any of the other documents in the workspace.
for (const context of Object.values(this.contextService.contexts)) {
for (const [prefix, iri] of Object.entries(context.namespaces)) {
Eif (iri === namespaceIri) {
return this._ensureNonEmptyPrefix(prefix, defaultValue);
}
}
}
// 4. Try to find the prefix in the default prefixes.
const defaultPrefixes = this.getDefaultPrefixes();
for (const prefix in defaultPrefixes) {
if (defaultPrefixes[prefix] === namespaceIri) {
return this._ensureNonEmptyPrefix(prefix, defaultValue);
}
}
return defaultValue;
}
/**
* Ensure that the prefix is not empty. If the prefix is empty, return the default value instead.
* @param prefix The prefix to check.
* @param defaultValue A default value to return if the prefix is empty.
* @returns The given prefix if it is not empty. The default value otherwise.
*/
private _ensureNonEmptyPrefix(prefix: string, defaultValue: string): string {
return prefix === '' ? defaultValue : prefix;
}
/**
* Get the most frequently used URI for a given prefix.
* @param documentUri The URI of the document where the prefix is used.
* @param prefix A prefix to look up.
* @returns A URI for the given prefix if it is declared in the project. An empty string otherwise.
*/
getUriForPrefix(documentUri: string, prefix: string): string {
// The empty prefix is specific for the document and should not be resolved.
if (prefix === '') {
let uri = documentUri;
const scheme = documentUri.split(':')[0];
if (WorkspaceUri.supportedSchemes.has(scheme)) {
// Make supported URI schemes workspace relative.
const workspaceUri = WorkspaceUri.toWorkspaceUri(vscode.Uri.parse(documentUri));
if (workspaceUri) {
uri = workspaceUri.toString();
}
}
if (uri.includes('#')) {
const param = getConfig().get<string>('prefixes.queryParameterName');
return uri + '?' + param + '=';
} else if (!uri.endsWith('#')) {
return uri + '#';
} else E{
return uri;
}
}
let result: string | undefined = undefined;
// 1. Check if the prefix is declared in the project configuration as a default prefix.
const namespaces = getConfig().get<{ defaultPrefix: string, uri: string }[]>('namespaces');
if (Array.isArray(namespaces)) {
result = namespaces.find(namespace => namespace.defaultPrefix === prefix)?.uri;
Eif (result) {
return result;
}
}
// 2. Retrieve prefixes from declared in the documents of the workspace.
// Count the number of times each URI is used for the given prefix.
const uriCounts: { [uri: string]: number } = {};
for (let document of Object.values(this.contextService.contexts)) {
Eif (document.namespaces[prefix]) {
const uri = document.namespaces[prefix];
uriCounts[uri] = (uriCounts[uri] || 0) + 1;
}
}
let maxCount = 0;
for (let uri in uriCounts) {
// Return the URI that is used the most for the given prefix in local documents.
if (uriCounts[uri] > maxCount) {
maxCount = uriCounts[uri];
result = uri;
}
}
if (result) {
return result;
}
// 3. Alternatively use the default prefixes if the prefix is not declared in the project.
const defaultPrefixes = this.getDefaultPrefixes();
// Returning an empty string will produce empty URI declarations which will trigger
// a diagnostic error in the document so users can enter it manually.
return defaultPrefixes[prefix] ?? '';
}
} |