Updated the rest of the code to fit the new ContextUtil

main
Jackson Morgan 2 years ago
parent 9b3632e177
commit 4b477559e2
  1. 37
      packages/jsonld-dataset-proxy/src/ContextUtil.ts
  2. 13
      packages/jsonld-dataset-proxy/src/ProxyContext.ts
  3. 12
      packages/jsonld-dataset-proxy/src/arrayProxy/modifyArray.ts
  4. 5
      packages/jsonld-dataset-proxy/src/graphOf.ts
  5. 7
      packages/jsonld-dataset-proxy/src/language/languagesOf.ts
  6. 7
      packages/jsonld-dataset-proxy/src/subjectProxy/createSubjectHandler.ts
  7. 4
      packages/jsonld-dataset-proxy/src/subjectProxy/deleteFromDataset.ts
  8. 13
      packages/jsonld-dataset-proxy/src/subjectProxy/getValueForKey.ts
  9. 14
      packages/jsonld-dataset-proxy/src/util/addObjectToDataset.ts
  10. 8
      packages/jsonld-dataset-proxy/src/util/getNodeFromRaw.ts
  11. 10
      packages/jsonld-dataset-proxy/test/ContextUtil.test.ts

@ -3,6 +3,7 @@ import type {
LdoJsonldContext, LdoJsonldContext,
LdoJsonldContextExpandedTermDefinition, LdoJsonldContextExpandedTermDefinition,
} from "./LdoJsonldContext"; } from "./LdoJsonldContext";
import type { NamedNode } from "@rdfjs/types";
// Create JSONLD Shorthands // Create JSONLD Shorthands
const shorthandToIriMap: Record<string, string> = { const shorthandToIriMap: Record<string, string> = {
@ -64,15 +65,18 @@ export class ContextUtil {
*/ */
private getRelevantContext( private getRelevantContext(
key: string, key: string,
typeName?: string, typeNames?: NamedNode[],
): ContextDefinition | LdoJsonldContext { ): ContextDefinition | LdoJsonldContext {
if ( if (!typeNames) return this.context;
typeName && for (const typeNameNode of typeNames) {
typeof this.context[typeName] === "object" && const typeName = this.iriToKey((typeNameNode as NamedNode).value, []);
this.context[typeName]?.["@context"] && if (
this.context[typeName]?.["@context"][key] typeof this.context[typeName] === "object" &&
) { this.context[typeName]?.["@context"] &&
return this.context[typeName]?.["@context"]; this.context[typeName]?.["@context"][key]
) {
return this.context[typeName]?.["@context"];
}
} }
return this.context; return this.context;
} }
@ -91,7 +95,7 @@ export class ContextUtil {
/** /**
* Converts a given JsonLd key into an RDF IRI * Converts a given JsonLd key into an RDF IRI
*/ */
public keyToIri(key: string, typeName: string): string { public keyToIri(key: string, typeName: NamedNode[]): string {
const relevantContext = this.getRelevantContext(key, typeName); const relevantContext = this.getRelevantContext(key, typeName);
if (!relevantContext[key]) { if (!relevantContext[key]) {
return key; return key;
@ -108,9 +112,12 @@ export class ContextUtil {
/** /**
* Converts a given RDF IRI into the JsonLd key * Converts a given RDF IRI into the JsonLd key
*/ */
public iriToKey(iri: string, typeName: string): string { public iriToKey(iri: string, typeNames: NamedNode[]): string {
const relevantMap = let relevantMap = this.iriToKeyMap;
this.typeNameToIriToKeyMap[typeName] || this.iriToKeyMap; for (const typeNameNode of typeNames) {
const typeName = this.iriToKey((typeNameNode as NamedNode).value, []);
relevantMap = this.typeNameToIriToKeyMap[typeName] || this.iriToKeyMap;
}
if (relevantMap[iri]) { if (relevantMap[iri]) {
return relevantMap[iri]; return relevantMap[iri];
} }
@ -120,7 +127,7 @@ export class ContextUtil {
/** /**
* Returns the IRI of a datatype of a specific object * Returns the IRI of a datatype of a specific object
*/ */
public getDataType(key: string, typeName: string): string { public getDataType(key: string, typeName: NamedNode[]): string {
const relevantContext = this.getRelevantContext(key, typeName); const relevantContext = this.getRelevantContext(key, typeName);
if ( if (
typeof relevantContext[key] === "object" && typeof relevantContext[key] === "object" &&
@ -136,7 +143,7 @@ export class ContextUtil {
/** /**
* Returns true if the object is a collection * Returns true if the object is a collection
*/ */
public isArray(key: string, typeName: string): boolean { public isArray(key: string, typeName: NamedNode[]): boolean {
const relevantContext = this.getRelevantContext(key, typeName); const relevantContext = this.getRelevantContext(key, typeName);
return !!( return !!(
relevantContext[key] && relevantContext[key] &&
@ -153,7 +160,7 @@ export class ContextUtil {
/** /**
* Returns true if the object is a language string * Returns true if the object is a language string
*/ */
public isLangString(key: string, typeName: string): boolean { public isLangString(key: string, typeName: NamedNode[]): boolean {
const relevantContext = this.getRelevantContext(key, typeName); const relevantContext = this.getRelevantContext(key, typeName);
return !!( return !!(
relevantContext[key] && relevantContext[key] &&

@ -1,4 +1,4 @@
import type { GraphNode, QuadMatch } from "@ldo/rdf-utils"; import type { GraphNode, QuadMatch, SubjectNode } from "@ldo/rdf-utils";
import type { BlankNode, Dataset, NamedNode } from "@rdfjs/types"; import type { BlankNode, Dataset, NamedNode } from "@rdfjs/types";
import type { ArrayProxyTarget } from "./arrayProxy/createArrayHandler"; import type { ArrayProxyTarget } from "./arrayProxy/createArrayHandler";
import { createArrayHandler } from "./arrayProxy/createArrayHandler"; import { createArrayHandler } from "./arrayProxy/createArrayHandler";
@ -8,6 +8,7 @@ import type { ArrayProxy } from "./arrayProxy/ArrayProxy";
import { _getUnderlyingArrayTarget } from "./types"; import { _getUnderlyingArrayTarget } from "./types";
import type { ContextUtil } from "./ContextUtil"; import type { ContextUtil } from "./ContextUtil";
import type { LanguageOrdering } from "./language/languageTypes"; import type { LanguageOrdering } from "./language/languageTypes";
import { namedNode } from "@rdfjs/data-model";
export interface ProxyContextOptions { export interface ProxyContextOptions {
dataset: Dataset; dataset: Dataset;
@ -18,6 +19,8 @@ export interface ProxyContextOptions {
state?: Record<string, unknown>; state?: Record<string, unknown>;
} }
const rdfType = namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
/** /**
* This file keeps track of the target objects used in the proxies. * This file keeps track of the target objects used in the proxies.
* The reason is so that JSON.stringify does not recurse inifinitely * The reason is so that JSON.stringify does not recurse inifinitely
@ -107,4 +110,12 @@ export class ProxyContext {
}; };
return new ProxyContext(fullOptions); return new ProxyContext(fullOptions);
} }
public getRdfType(subjectNode: SubjectNode): NamedNode[] {
return this.dataset
.match(subjectNode, rdfType)
.toArray()
.map((quad) => quad.object)
.filter((object): object is NamedNode => object.termType === "NamedNode");
}
} }

@ -114,7 +114,10 @@ export function modifyArray<ReturnType>(
addObjectToDataset( addObjectToDataset(
{ {
"@id": target[0][0], "@id": target[0][0],
[contextUtil.iriToKey(target[0][1].value)]: added, [contextUtil.iriToKey(
target[0][1].value,
proxyContext.getRdfType(target[0][0]),
)]: added,
} as RawObject, } as RawObject,
false, false,
proxyContext, proxyContext,
@ -123,7 +126,12 @@ export function modifyArray<ReturnType>(
const addedNodes = added const addedNodes = added
? (added ? (added
.map((addedValue) => { .map((addedValue) => {
return getNodeFromRawValue(key, addedValue, proxyContext); return getNodeFromRawValue(
key,
addedValue,
target[0][0] ? proxyContext.getRdfType(target[0][0]) : [],
proxyContext,
);
}) })
.filter((val) => val != undefined) as ObjectNode[]) .filter((val) => val != undefined) as ObjectNode[])
: []; : [];

@ -31,7 +31,10 @@ export function graphOf<Subject extends ObjectLike, Key extends keyof Subject>(
const proxyContext = subjectProxy[_proxyContext]; const proxyContext = subjectProxy[_proxyContext];
const subjectNode = subjectProxy[_getUnderlyingNode]; const subjectNode = subjectProxy[_getUnderlyingNode];
const predicateNode = namedNode( const predicateNode = namedNode(
proxyContext.contextUtil.keyToIri(predicate as string), proxyContext.contextUtil.keyToIri(
predicate as string,
proxyContext.getRdfType(subjectNode),
),
); );
let objectNode: ObjectNode | null; let objectNode: ObjectNode | null;
if (object == null) { if (object == null) {

@ -51,11 +51,14 @@ export function languagesOf<
const proxy = getSubjectProxyFromObject(subjectObject); const proxy = getSubjectProxyFromObject(subjectObject);
const proxyContext = proxy[_proxyContext]; const proxyContext = proxy[_proxyContext];
const subject = proxy[_getUnderlyingNode]; const subject = proxy[_getUnderlyingNode];
const predicate = namedNode(proxyContext.contextUtil.keyToIri(key as string)); const rdfTypes = proxyContext.getRdfType(subject);
const predicate = namedNode(
proxyContext.contextUtil.keyToIri(key as string, rdfTypes),
);
return createLanguageMapProxy<LanguageMap>( return createLanguageMapProxy<LanguageMap>(
subject, subject,
predicate, predicate,
proxyContext, proxyContext,
proxyContext.contextUtil.isArray(key as string), proxyContext.contextUtil.isArray(key as string, rdfTypes),
) as LanguageOfConditionalReturn<SubjectObject, Key>; ) as LanguageOfConditionalReturn<SubjectObject, Key>;
} }

@ -48,7 +48,12 @@ export function createSubjectHandler(
const tripleDataset = proxyContext.dataset.match(subject); const tripleDataset = proxyContext.dataset.match(subject);
const keys: Set<string> = new Set(["@id"]); const keys: Set<string> = new Set(["@id"]);
tripleDataset.toArray().forEach((quad) => { tripleDataset.toArray().forEach((quad) => {
keys.add(proxyContext.contextUtil.iriToKey(quad.predicate.value)); keys.add(
proxyContext.contextUtil.iriToKey(
quad.predicate.value,
proxyContext.getRdfType(subject),
),
);
}); });
return Array.from(keys); return Array.from(keys);
}, },

@ -19,7 +19,9 @@ export function deleteValueFromDataset(
return true; return true;
} }
const subject = target["@id"]; const subject = target["@id"];
const predicate = namedNode(proxyContext.contextUtil.keyToIri(key)); const predicate = namedNode(
proxyContext.contextUtil.keyToIri(key, proxyContext.getRdfType(subject)),
);
if (key === "@id") { if (key === "@id") {
nodesToRemove.push(target["@id"]); nodesToRemove.push(target["@id"]);
} else { } else {

@ -19,7 +19,9 @@ export function getValueForKey(
if (target["@id"].termType === "BlankNode") { if (target["@id"].termType === "BlankNode") {
return undefined; return undefined;
} }
return contextUtil.iriToKey(target["@id"].value); // Purposly don't provide a typeName because we don't want to use the nested
// context
return contextUtil.iriToKey(target["@id"].value, []);
} }
if (key === "toString" || key === Symbol.toStringTag) { if (key === "toString" || key === Symbol.toStringTag) {
// TODO: this toString method right now returns [object Object], // TODO: this toString method right now returns [object Object],
@ -31,18 +33,19 @@ export function getValueForKey(
return; return;
} }
const subject = target["@id"]; const subject = target["@id"];
const predicate = namedNode(contextUtil.keyToIri(key)); const rdfType = proxyContext.getRdfType(subject);
if (contextUtil.isArray(key)) { const predicate = namedNode(contextUtil.keyToIri(key, rdfType));
if (contextUtil.isArray(key, rdfType)) {
const arrayProxy = proxyContext.createArrayProxy( const arrayProxy = proxyContext.createArrayProxy(
[subject, predicate, null, null], [subject, predicate, null, null],
false, false,
undefined, undefined,
contextUtil.isLangString(key), contextUtil.isLangString(key, rdfType),
); );
return arrayProxy; return arrayProxy;
} }
let objectDataset = dataset.match(subject, predicate); let objectDataset = dataset.match(subject, predicate);
if (contextUtil.isLangString(key)) { if (contextUtil.isLangString(key, rdfType)) {
objectDataset = filterQuadsByLanguageOrdering( objectDataset = filterQuadsByLanguageOrdering(
objectDataset, objectDataset,
proxyContext.languageOrdering, proxyContext.languageOrdering,

@ -22,15 +22,16 @@ export function addRawValueToDatasetRecursive(
proxyContext: ProxyContext, proxyContext: ProxyContext,
): void { ): void {
const { dataset, contextUtil } = proxyContext; const { dataset, contextUtil } = proxyContext;
const predicate = namedNode(contextUtil.keyToIri(key)); const rdfType = proxyContext.getRdfType(subject);
const predicate = namedNode(contextUtil.keyToIri(key, rdfType));
// Get the Object Node // Get the Object Node
const object = getNodeFromRawValue(key, value, proxyContext); const object = getNodeFromRawValue(key, value, rdfType, proxyContext);
if (object == undefined) { if (object == undefined) {
dataset.deleteMatches(subject, predicate); dataset.deleteMatches(subject, predicate);
} else if (object.termType === "Literal") { } else if (object.termType === "Literal") {
let languageAppliedObject = object; let languageAppliedObject = object;
// Handle language use case // Handle language use case
if (contextUtil.isLangString(key)) { if (contextUtil.isLangString(key, rdfType)) {
const languageKey = getLanguageKeyForWriteOperation( const languageKey = getLanguageKeyForWriteOperation(
proxyContext.languageOrdering, proxyContext.languageOrdering,
); );
@ -81,6 +82,7 @@ export function addRawObjectToDatasetRecursive(
} }
const { dataset } = proxyContext; const { dataset } = proxyContext;
const subject = getNodeFromRawObject(item, proxyContext.contextUtil); const subject = getNodeFromRawObject(item, proxyContext.contextUtil);
const rdfType = proxyContext.getRdfType(subject);
if (visitedObjects.has(subject)) { if (visitedObjects.has(subject)) {
return proxyContext.createSubjectProxy(subject); return proxyContext.createSubjectProxy(subject);
} }
@ -89,9 +91,11 @@ export function addRawObjectToDatasetRecursive(
if (key === "@id") { if (key === "@id") {
return; return;
} }
const predicate = namedNode(proxyContext.contextUtil.keyToIri(key)); const predicate = namedNode(
proxyContext.contextUtil.keyToIri(key, rdfType),
);
if (shouldDeleteOldTriples) { if (shouldDeleteOldTriples) {
if (proxyContext.contextUtil.isLangString(key)) { if (proxyContext.contextUtil.isLangString(key, rdfType)) {
const languageKey = getLanguageKeyForWriteOperation( const languageKey = getLanguageKeyForWriteOperation(
proxyContext.languageOrdering, proxyContext.languageOrdering,
); );

@ -14,7 +14,9 @@ export function getNodeFromRawObject(
} else if (!item["@id"]) { } else if (!item["@id"]) {
return blankNode(); return blankNode();
} else if (typeof item["@id"] === "string") { } else if (typeof item["@id"] === "string") {
return namedNode(contextUtil.keyToIri(item["@id"])); // Purposly do not include typeName because we don't want to reference
// nested context
return namedNode(contextUtil.keyToIri(item["@id"], []));
} else { } else {
return item["@id"]; return item["@id"];
} }
@ -23,6 +25,7 @@ export function getNodeFromRawObject(
export function getNodeFromRawValue( export function getNodeFromRawValue(
key: string, key: string,
value: RawValue, value: RawValue,
rdfTypes: NamedNode[],
proxyContext: ProxyContext, proxyContext: ProxyContext,
): BlankNode | NamedNode | Literal | undefined { ): BlankNode | NamedNode | Literal | undefined {
// Get the Object Node // Get the Object Node
@ -33,7 +36,8 @@ export function getNodeFromRawValue(
typeof value === "boolean" || typeof value === "boolean" ||
typeof value === "number" typeof value === "number"
) { ) {
const datatype = proxyContext.contextUtil.getType(key); // PICKUP: figure out how to handle looking for the RDF Types of a raw value
const datatype = proxyContext.contextUtil.getDataType(key, rdfTypes);
if (datatype === "@id") { if (datatype === "@id") {
return namedNode(value.toString()); return namedNode(value.toString());
} else { } else {

@ -7,13 +7,13 @@ describe("ContextUtil", () => {
name: "http://hl7.org/fhir/name", name: "http://hl7.org/fhir/name",
}; };
const contextUtil = new ContextUtil(fakeContext); const contextUtil = new ContextUtil(fakeContext);
expect(contextUtil.keyToIri("name")).toBe("http://hl7.org/fhir/name"); expect(contextUtil.keyToIri("name", [])).toBe("http://hl7.org/fhir/name");
}); });
it("returns the given key if it is not in the context", () => { it("returns the given key if it is not in the context", () => {
const contextUtil = new ContextUtil({}); const contextUtil = new ContextUtil({});
expect(contextUtil.keyToIri("name")).toBe("name"); expect(contextUtil.keyToIri("name", [])).toBe("name");
expect(contextUtil.iriToKey("http://hl7.org/fhir/name")).toBe( expect(contextUtil.iriToKey("http://hl7.org/fhir/name", [])).toBe(
"http://hl7.org/fhir/name", "http://hl7.org/fhir/name",
); );
}); });
@ -22,7 +22,7 @@ describe("ContextUtil", () => {
const contextUtil = new ContextUtil({ const contextUtil = new ContextUtil({
name: { "@type": "http://www.w3.org/2001/XMLSchema#string" }, name: { "@type": "http://www.w3.org/2001/XMLSchema#string" },
}); });
expect(contextUtil.keyToIri("name")).toBe("name"); expect(contextUtil.keyToIri("name", [])).toBe("name");
}); });
}); });
@ -31,7 +31,7 @@ describe("ContextUtil", () => {
const contextUtil = new ContextUtil({ const contextUtil = new ContextUtil({
name: { "@id": "http://hl7.org/fhir/name" }, name: { "@id": "http://hl7.org/fhir/name" },
}); });
expect(contextUtil.getType("name")).toBe( expect(contextUtil.getDataType("name", [])).toBe(
"http://www.w3.org/2001/XMLSchema#string", "http://www.w3.org/2001/XMLSchema#string",
); );
}); });

Loading…
Cancel
Save