Repository: solid/community-server
Pull request #152 (2020-09-11 15:29:14)

refactor: Make URI constants consistent
This stores all our URI constants in 1 file now. They are stored as strings and not as named nodes so they can be used in the objectmap of the RepresentationMetadata constructor. This PR does also add some helper functions to cache the named nodes we generate from them to prevent having to do that all the time.


Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 71cc119cc..394e2ef49 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -33,6 +33,7 @@ module.exports = {
     'dot-location': ['error', 'property'],
     'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }],
     'max-len': ['error', { code: 120, ignoreUrls: true }],
+    'new-cap': 'off', // used for RDF constants
     'no-param-reassign': 'off', // necessary in constructor overloading
     'no-underscore-dangle': 'off', // conflicts with external libraries
     'padding-line-between-statements': 'off',
diff --git a/src/authorization/AclConstants.ts b/src/authorization/AclConstants.ts
deleted file mode 100644
index 43751e55b..000000000
--- a/src/authorization/AclConstants.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-const ACL_PREFIX = 'http://www.w3.org/ns/auth/acl#';
-const FOAF_PREFIX = 'http://xmlns.com/foaf/0.1/';
-
-export const ACL = {
-  accessTo: `${ACL_PREFIX}accessTo`,
-  agent: `${ACL_PREFIX}agent`,
-  agentClass: `${ACL_PREFIX}agentClass`,
-  default: `${ACL_PREFIX}default`,
-  mode: `${ACL_PREFIX}mode`,
-
-  Write: `${ACL_PREFIX}Write`,
-  Read: `${ACL_PREFIX}Read`,
-  Append: `${ACL_PREFIX}Append`,
-  Control: `${ACL_PREFIX}Control`,
-};
-
-export const FOAF = {
-  Agent: `${FOAF_PREFIX}Agent`,
-  AuthenticatedAgent: `${FOAF_PREFIX}AuthenticatedAgent`,
-};
diff --git a/src/authorization/WebAclAuthorizer.ts b/src/authorization/WebAclAuthorizer.ts
index dee626e0d..bc5958614 100644
--- a/src/authorization/WebAclAuthorizer.ts
+++ b/src/authorization/WebAclAuthorizer.ts
@@ -9,7 +9,7 @@ import { INTERNAL_QUADS } from '../util/ContentTypes';
 import { ForbiddenHttpError } from '../util/errors/ForbiddenHttpError';
 import { NotFoundHttpError } from '../util/errors/NotFoundHttpError';
 import { UnauthorizedHttpError } from '../util/errors/UnauthorizedHttpError';
-import { ACL, FOAF } from './AclConstants';
+import { ACL, FOAF } from '../util/UriConstants';
 import { AclManager } from './AclManager';
 import { Authorizer, AuthorizerArgs } from './Authorizer';
 
diff --git a/src/init/Setup.ts b/src/init/Setup.ts
index f04829583..4a98b2901 100644
--- a/src/init/Setup.ts
+++ b/src/init/Setup.ts
@@ -4,7 +4,7 @@ import { RepresentationMetadata } from '../ldp/representation/RepresentationMeta
 import { ExpressHttpServer } from '../server/ExpressHttpServer';
 import { ResourceStore } from '../storage/ResourceStore';
 import { TEXT_TURTLE } from '../util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../util/MetadataTypes';
+import { CONTENT_TYPE } from '../util/UriConstants';
 
 /**
  * Invokes all logic to setup a server.
@@ -51,7 +51,7 @@ export class Setup {
     acl:accessTo    <${this.base}>;
     acl:default     <${this.base}>.`;
       const baseAclId = await this.aclManager.getAcl({ path: this.base });
-      const metadata = new RepresentationMetadata(baseAclId.path, { [MA_CONTENT_TYPE]: TEXT_TURTLE });
+      const metadata = new RepresentationMetadata(baseAclId.path, { [CONTENT_TYPE]: TEXT_TURTLE });
       await this.store.setRepresentation(
         baseAclId,
         {
diff --git a/src/ldp/http/RawBodyParser.ts b/src/ldp/http/RawBodyParser.ts
index f1456708f..7636f3fdb 100644
--- a/src/ldp/http/RawBodyParser.ts
+++ b/src/ldp/http/RawBodyParser.ts
@@ -1,6 +1,6 @@
 import { HttpRequest } from '../../server/HttpRequest';
 import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
-import { HTTP_SLUG, RDF_TYPE, MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE, HTTP, RDF } from '../../util/UriConstants';
 import { Representation } from '../representation/Representation';
 import { RepresentationMetadata } from '../representation/RepresentationMetadata';
 import { BodyParser } from './BodyParser';
@@ -40,7 +40,7 @@ export class RawBodyParser extends BodyParser {
   private parseMetadata(input: HttpRequest): RepresentationMetadata {
     const contentType = /^[^;]*/u.exec(input.headers['content-type']!)![0];
 
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: contentType });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: contentType });
 
     const { link, slug } = input.headers;
 
@@ -48,7 +48,7 @@ export class RawBodyParser extends BodyParser {
       if (Array.isArray(slug)) {
         throw new UnsupportedHttpError('At most 1 slug header is allowed.');
       }
-      metadata.set(HTTP_SLUG, slug);
+      metadata.set(HTTP.slug, slug);
     }
 
     // There are similarities here to Accept header parsing so that library should become more generic probably
@@ -61,7 +61,7 @@ export class RawBodyParser extends BodyParser {
       });
       for (const entry of parsedLinks) {
         if (entry.rel === 'type') {
-          metadata.set(RDF_TYPE, entry.url);
+          metadata.set(RDF.type, entry.url);
           break;
         }
       }
diff --git a/src/ldp/http/SparqlUpdateBodyParser.ts b/src/ldp/http/SparqlUpdateBodyParser.ts
index c10fe1622..5d66a32b8 100644
--- a/src/ldp/http/SparqlUpdateBodyParser.ts
+++ b/src/ldp/http/SparqlUpdateBodyParser.ts
@@ -3,7 +3,7 @@ import { translate } from 'sparqlalgebrajs';
 import { HttpRequest } from '../../server/HttpRequest';
 import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
 import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMediaTypeHttpError';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { readableToString } from '../../util/Util';
 import { RepresentationMetadata } from '../representation/RepresentationMetadata';
 import { BodyParser } from './BodyParser';
@@ -35,7 +35,7 @@ export class SparqlUpdateBodyParser extends BodyParser {
       const sparql = await readableToString(toAlgebraStream);
       const algebra = translate(sparql, { quads: true });
 
-      const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'application/sparql-update' });
+      const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'application/sparql-update' });
 
       // Prevent body from being requested again
       return {
diff --git a/src/ldp/representation/MetadataUtil.ts b/src/ldp/representation/MetadataUtil.ts
deleted file mode 100644
index 95a34c99f..000000000
--- a/src/ldp/representation/MetadataUtil.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { literal, namedNode } from '@rdfjs/data-model';
-import type { Literal, NamedNode, Term } from 'rdf-js';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
-
-// Shorthands for commonly used predicates
-const shorthands: { [id: string]: NamedNode } = {
-  contentType: namedNode(MA_CONTENT_TYPE),
-};
-
-// Caches named node conversions
-const termMap: { [id: string]: NamedNode } = {};
-
-/**
- * @param input - Checks if this is a {@link Term}.
- */
-export const isTerm = (input?: any): input is Term => input?.termType;
-
-/**
- * Converts the incoming predicate to a named node.
- * In case of string, first checks if it is a shorthand, if not a new named node gets made.
- * @param predicate - Predicate to potentially transform.
- */
-export const getPredicateTerm = (predicate: NamedNode | string): NamedNode => {
-  if (typeof predicate === 'string') {
-    if (shorthands[predicate]) {
-      return shorthands[predicate];
-    }
-    if (!termMap[predicate]) {
-      termMap[predicate] = namedNode(predicate);
-    }
-    return termMap[predicate];
-  }
-  return predicate;
-};
-
-/**
- * Converts an object to a literal when needed.
- * @param object - Object to potentially transform.
- */
-export const getObjectTerm = (object: NamedNode | Literal | string): NamedNode | Literal =>
-  typeof object === 'string' ? literal(object) : object;
diff --git a/src/ldp/representation/RepresentationMetadata.ts b/src/ldp/representation/RepresentationMetadata.ts
index 74e5cbcce..88cb286f2 100644
--- a/src/ldp/representation/RepresentationMetadata.ts
+++ b/src/ldp/representation/RepresentationMetadata.ts
@@ -1,7 +1,6 @@
-import { quad as createQuad, namedNode } from '@rdfjs/data-model';
-import { Store } from 'n3';
+import { DataFactory, Store } from 'n3';
 import type { BlankNode, Literal, NamedNode, Quad, Term } from 'rdf-js';
-import { getObjectTerm, getPredicateTerm, isTerm } from './MetadataUtil';
+import { getObjectTerm, getNamedNode, isTerm } from '../../util/UriUtil';
 
 export type MetadataOverrideValue = NamedNode | Literal | string | (NamedNode | Literal | string)[];
 
@@ -41,7 +40,7 @@ export class RepresentationMetadata {
   ) {
     this.store = new Store();
     if (typeof input === 'string') {
-      this.id = namedNode(input);
+      this.id = DataFactory.namedNode(input);
     } else if (isTerm(input)) {
       this.id = input;
     } else if (input instanceof RepresentationMetadata) {
@@ -59,7 +58,7 @@ export class RepresentationMetadata {
 
   private setOverrides(overrides: { [pred: string]: MetadataOverrideValue}): void {
     for (const predicate of Object.keys(overrides)) {
-      const namedPredicate = getPredicateTerm(predicate);
+      const namedPredicate = getNamedNode(predicate);
       this.removeAll(namedPredicate);
 
       let objects = overrides[predicate];
@@ -92,10 +91,10 @@ export class RepresentationMetadata {
       // Convert all instances of the old identifier to the new identifier in the stored quads
       const quads = this.quads().map((quad): Quad => {
         if (quad.subject.equals(this.id)) {
-          return createQuad(id, quad.predicate, quad.object, quad.graph);
+          return DataFactory.quad(id, quad.predicate, quad.object, quad.graph);
         }
         if (quad.object.equals(this.id)) {
-          return createQuad(quad.subject, quad.predicate, id, quad.graph);
+          return DataFactory.quad(quad.subject, quad.predicate, id, quad.graph);
         }
         return quad;
       });
@@ -137,7 +136,7 @@ export class RepresentationMetadata {
    * @param object - Value to add.
    */
   public add(predicate: NamedNode | string, object: NamedNode | Literal | string): this {
-    this.store.addQuad(this.id, getPredicateTerm(predicate), getObjectTerm(object));
+    this.store.addQuad(this.id, getNamedNode(predicate), getObjectTerm(object));
     return this;
   }
 
@@ -147,7 +146,7 @@ export class RepresentationMetadata {
    * @param object - Value to remove.
    */
   public remove(predicate: NamedNode | string, object: NamedNode | Literal | string): this {
-    this.store.removeQuad(this.id, getPredicateTerm(predicate), getObjectTerm(object));
+    this.store.removeQuad(this.id, getNamedNode(predicate), getObjectTerm(object));
     return this;
   }
 
@@ -156,7 +155,7 @@ export class RepresentationMetadata {
    * @param predicate - Predicate to remove.
    */
   public removeAll(predicate: NamedNode | string): this {
-    this.removeQuads(this.store.getQuads(this.id, getPredicateTerm(predicate), null, null));
+    this.removeQuads(this.store.getQuads(this.id, getNamedNode(predicate), null, null));
     return this;
   }
 
@@ -167,7 +166,7 @@ export class RepresentationMetadata {
    * @returns An array with all matches.
    */
   public getAll(predicate: NamedNode | string): Term[] {
-    return this.store.getQuads(this.id, getPredicateTerm(predicate), null, null)
+    return this.store.getQuads(this.id, getNamedNode(predicate), null, null)
       .map((quad): Term => quad.object);
   }
 
@@ -210,10 +209,10 @@ export class RepresentationMetadata {
    * Shorthand for the CONTENT_TYPE predicate.
    */
   public get contentType(): string | undefined {
-    return this.get(getPredicateTerm('contentType'))?.value;
+    return this.get(getNamedNode('contentType'))?.value;
   }
 
   public set contentType(input) {
-    this.set(getPredicateTerm('contentType'), input);
+    this.set(getNamedNode('contentType'), input);
   }
 }
diff --git a/src/storage/FileResourceStore.ts b/src/storage/FileResourceStore.ts
index 06749fb7f..d005583c5 100644
--- a/src/storage/FileResourceStore.ts
+++ b/src/storage/FileResourceStore.ts
@@ -14,15 +14,8 @@ import { NotFoundHttpError } from '../util/errors/NotFoundHttpError';
 import { UnsupportedMediaTypeHttpError } from '../util/errors/UnsupportedMediaTypeHttpError';
 import { InteractionController } from '../util/InteractionController';
 import { MetadataController } from '../util/MetadataController';
-import {
-  HTTP_BYTE_SIZE,
-  HTTP_LAST_CHANGED,
-  HTTP_SLUG,
-  MA_CONTENT_TYPE,
-  RDF_TYPE,
-  XSD_DATE_TIME,
-  XSD_INTEGER,
-} from '../util/MetadataTypes';
+import { CONTENT_TYPE, DCTERMS, HTTP, POSIX, RDF, XSD } from '../util/UriConstants';
+import { getTypedLiteral } from '../util/UriUtil';
 import { ensureTrailingSlash } from '../util/Util';
 import { ExtensionBasedMapper } from './ExtensionBasedMapper';
 import { ResourceStore } from './ResourceStore';
@@ -65,8 +58,8 @@ export class FileResourceStore implements ResourceStore {
 
     // Get the path from the request URI, all metadata triples if any, and the Slug and Link header values.
     const path = this.resourceMapper.getRelativePath(container);
-    const slug = representation.metadata.get(HTTP_SLUG)?.value;
-    const types = representation.metadata.getAll(RDF_TYPE);
+    const slug = representation.metadata.get(HTTP.slug)?.value;
+    const types = representation.metadata.getAll(RDF.type);
 
     // Create a new container or resource in the parent container with a specific name based on the incoming headers.
     const isContainer = this.interactionController.isContainer(slug, types);
@@ -162,7 +155,7 @@ export class FileResourceStore implements ResourceStore {
     // eslint-disable-next-line no-param-reassign
     representation.metadata.identifier = DataFactory.namedNode(identifier.path);
     const raw = representation.metadata.quads();
-    const types = representation.metadata.getAll(RDF_TYPE);
+    const types = representation.metadata.getAll(RDF.type);
     let metadata: Readable | undefined;
     if (raw.length > 0) {
       metadata = this.metadataController.serializeQuads(raw);
@@ -231,8 +224,8 @@ export class FileResourceStore implements ResourceStore {
       // Metadata file doesn't exist so lets keep `rawMetaData` an empty array.
     }
     const metadata = new RepresentationMetadata(this.resourceMapper.mapFilePathToUrl(path)).addQuads(rawMetadata)
-      .set(HTTP_LAST_CHANGED, DataFactory.literal(stats.mtime.toISOString(), XSD_DATE_TIME))
-      .set(HTTP_BYTE_SIZE, DataFactory.literal(stats.size, XSD_INTEGER));
+      .set(DCTERMS.modified, getTypedLiteral(stats.mtime.toISOString(), XSD.dateTime))
+      .set(POSIX.size, getTypedLiteral(stats.size, XSD.integer));
     metadata.contentType = contentType;
     return { metadata, data: readStream, binary: true };
   }
@@ -265,8 +258,8 @@ export class FileResourceStore implements ResourceStore {
     }
 
     const metadata = new RepresentationMetadata(containerURI).addQuads(rawMetadata)
-      .set(HTTP_LAST_CHANGED, DataFactory.literal(stats.mtime.toISOString(), XSD_DATE_TIME))
-      .set(MA_CONTENT_TYPE, INTERNAL_QUADS);
+      .set(DCTERMS.modified, getTypedLiteral(stats.mtime.toISOString(), XSD.dateTime))
+      .set(CONTENT_TYPE, INTERNAL_QUADS);
 
     return {
       binary: false,
@@ -285,6 +278,7 @@ export class FileResourceStore implements ResourceStore {
    */
   private async getDirChildrenQuadRepresentation(files: string[], path: string, containerURI: string): Promise<Quad[]> {
     const quads: Quad[] = [];
+    const childURIs: string[] = [];
     for (const childName of files) {
       try {
         const childURI = this.resourceMapper.mapFilePathToUrl(joinPath(path, childName));
@@ -293,13 +287,16 @@ export class FileResourceStore implements ResourceStore {
           continue;
         }
 
-        quads.push(this.metadataController.generateContainerContainsResourceQuad(containerURI, childURI));
         quads.push(...this.metadataController.generateResourceQuads(childURI, childStats));
+        childURIs.push(childURI);
       } catch (_) {
         // Skip the child if there is an error.
       }
     }
-    return quads;
+
+    const containsQuads = this.metadataController.generateContainerContainsResourceQuads(containerURI, childURIs);
+
+    return quads.concat(containsQuads);
   }
 
   /**
diff --git a/src/storage/InMemoryResourceStore.ts b/src/storage/InMemoryResourceStore.ts
index 599b14379..1d67f9752 100644
--- a/src/storage/InMemoryResourceStore.ts
+++ b/src/storage/InMemoryResourceStore.ts
@@ -6,7 +6,7 @@ import { RepresentationMetadata } from '../ldp/representation/RepresentationMeta
 import { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
 import { TEXT_TURTLE } from '../util/ContentTypes';
 import { NotFoundHttpError } from '../util/errors/NotFoundHttpError';
-import { MA_CONTENT_TYPE } from '../util/MetadataTypes';
+import { CONTENT_TYPE } from '../util/UriConstants';
 import { ensureTrailingSlash } from '../util/Util';
 import { ResourceStore } from './ResourceStore';
 
@@ -26,7 +26,7 @@ export class InMemoryResourceStore implements ResourceStore {
   public constructor(base: string) {
     this.base = ensureTrailingSlash(base);
 
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: TEXT_TURTLE });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: TEXT_TURTLE });
     this.store = {
       // Default root entry (what you get when the identifier is equal to the base)
       '': {
diff --git a/src/storage/conversion/ChainedConverter.ts b/src/storage/conversion/ChainedConverter.ts
index d0e0bd7d6..21538d081 100644
--- a/src/storage/conversion/ChainedConverter.ts
+++ b/src/storage/conversion/ChainedConverter.ts
@@ -1,7 +1,7 @@
 import { Representation } from '../../ldp/representation/Representation';
 import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
 import { RepresentationPreferences } from '../../ldp/representation/RepresentationPreferences';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { matchingMediaType } from '../../util/Util';
 import { RepresentationConverterArgs } from './RepresentationConverter';
 import { TypedRepresentationConverter } from './TypedRepresentationConverter';
@@ -53,7 +53,7 @@ export class ChainedConverter extends TypedRepresentationConverter {
     const idx = this.converters.length - 1;
     const lastChain = await this.getMatchingType(this.converters[idx - 1], this.converters[idx]);
     const oldMeta = input.representation.metadata;
-    const metadata = new RepresentationMetadata(oldMeta, { [MA_CONTENT_TYPE]: lastChain });
+    const metadata = new RepresentationMetadata(oldMeta, { [CONTENT_TYPE]: lastChain });
     const representation: Representation = { ...input.representation, metadata };
     await this.last.canHandle({ ...input, representation });
   }
diff --git a/src/storage/conversion/QuadToRdfConverter.ts b/src/storage/conversion/QuadToRdfConverter.ts
index 0d064a793..b6cbcc29a 100644
--- a/src/storage/conversion/QuadToRdfConverter.ts
+++ b/src/storage/conversion/QuadToRdfConverter.ts
@@ -4,7 +4,7 @@ import { Representation } from '../../ldp/representation/Representation';
 import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
 import { RepresentationPreferences } from '../../ldp/representation/RepresentationPreferences';
 import { INTERNAL_QUADS } from '../../util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { checkRequest, matchingTypes } from './ConversionUtil';
 import { RepresentationConverterArgs } from './RepresentationConverter';
 import { TypedRepresentationConverter } from './TypedRepresentationConverter';
@@ -31,7 +31,7 @@ export class QuadToRdfConverter extends TypedRepresentationConverter {
 
   private async quadsToRdf(quads: Representation, preferences: RepresentationPreferences): Promise<Representation> {
     const contentType = matchingTypes(preferences, await rdfSerializer.getContentTypes())[0].value;
-    const metadata = new RepresentationMetadata(quads.metadata, { [MA_CONTENT_TYPE]: contentType });
+    const metadata = new RepresentationMetadata(quads.metadata, { [CONTENT_TYPE]: contentType });
     return {
       binary: true,
       data: rdfSerializer.serialize(quads.data, { contentType }) as Readable,
diff --git a/src/storage/conversion/QuadToTurtleConverter.ts b/src/storage/conversion/QuadToTurtleConverter.ts
index 718b4ece3..d99524123 100644
--- a/src/storage/conversion/QuadToTurtleConverter.ts
+++ b/src/storage/conversion/QuadToTurtleConverter.ts
@@ -2,7 +2,7 @@ import { StreamWriter } from 'n3';
 import { Representation } from '../../ldp/representation/Representation';
 import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
 import { INTERNAL_QUADS, TEXT_TURTLE } from '../../util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { checkRequest } from './ConversionUtil';
 import { RepresentationConverter, RepresentationConverterArgs } from './RepresentationConverter';
 
@@ -19,7 +19,7 @@ export class QuadToTurtleConverter extends RepresentationConverter {
   }
 
   private quadsToTurtle(quads: Representation): Representation {
-    const metadata = new RepresentationMetadata(quads.metadata, { [MA_CONTENT_TYPE]: TEXT_TURTLE });
+    const metadata = new RepresentationMetadata(quads.metadata, { [CONTENT_TYPE]: TEXT_TURTLE });
     return {
       binary: true,
       data: quads.data.pipe(new StreamWriter({ format: TEXT_TURTLE })),
diff --git a/src/storage/conversion/RdfToQuadConverter.ts b/src/storage/conversion/RdfToQuadConverter.ts
index 4a751605c..bf7db1eb5 100644
--- a/src/storage/conversion/RdfToQuadConverter.ts
+++ b/src/storage/conversion/RdfToQuadConverter.ts
@@ -3,7 +3,7 @@ import rdfParser from 'rdf-parse';
 import { Representation } from '../../ldp/representation/Representation';
 import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
 import { INTERNAL_QUADS } from '../../util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { pipeStreamsAndErrors } from '../../util/Util';
 import { checkRequest } from './ConversionUtil';
 import { RepresentationConverterArgs } from './RepresentationConverter';
@@ -30,7 +30,7 @@ export class RdfToQuadConverter extends TypedRepresentationConverter {
   }
 
   private rdfToQuads(representation: Representation, baseIRI: string): Representation {
-    const metadata = new RepresentationMetadata(representation.metadata, { [MA_CONTENT_TYPE]: INTERNAL_QUADS });
+    const metadata = new RepresentationMetadata(representation.metadata, { [CONTENT_TYPE]: INTERNAL_QUADS });
     const rawQuads = rdfParser.parse(representation.data, {
       contentType: representation.metadata.contentType!,
       baseIRI,
diff --git a/src/storage/conversion/TurtleToQuadConverter.ts b/src/storage/conversion/TurtleToQuadConverter.ts
index 83c25baa4..983c61020 100644
--- a/src/storage/conversion/TurtleToQuadConverter.ts
+++ b/src/storage/conversion/TurtleToQuadConverter.ts
@@ -4,7 +4,7 @@ import { Representation } from '../../ldp/representation/Representation';
 import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
 import { TEXT_TURTLE, INTERNAL_QUADS } from '../../util/ContentTypes';
 import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { checkRequest } from './ConversionUtil';
 import { RepresentationConverter, RepresentationConverterArgs } from './RepresentationConverter';
 
@@ -21,7 +21,7 @@ export class TurtleToQuadConverter extends RepresentationConverter {
   }
 
   private turtleToQuads(turtle: Representation, baseIRI: string): Representation {
-    const metadata = new RepresentationMetadata(turtle.metadata, { [MA_CONTENT_TYPE]: INTERNAL_QUADS });
+    const metadata = new RepresentationMetadata(turtle.metadata, { [CONTENT_TYPE]: INTERNAL_QUADS });
 
     // Catch parsing errors and emit correct error
     // Node 10 requires both writableObjectMode and readableObjectMode
diff --git a/src/storage/patch/SparqlUpdatePatchHandler.ts b/src/storage/patch/SparqlUpdatePatchHandler.ts
index 98cf9516c..f458aadd7 100644
--- a/src/storage/patch/SparqlUpdatePatchHandler.ts
+++ b/src/storage/patch/SparqlUpdatePatchHandler.ts
@@ -10,7 +10,7 @@ import { RepresentationMetadata } from '../../ldp/representation/RepresentationM
 import { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
 import { INTERNAL_QUADS } from '../../util/ContentTypes';
 import { UnsupportedHttpError } from '../../util/errors/UnsupportedHttpError';
-import { MA_CONTENT_TYPE } from '../../util/MetadataTypes';
+import { CONTENT_TYPE } from '../../util/UriConstants';
 import { ResourceLocker } from '../ResourceLocker';
 import { ResourceStore } from '../ResourceStore';
 import { PatchHandler } from './PatchHandler';
@@ -67,7 +67,7 @@ export class SparqlUpdatePatchHandler extends PatchHandler {
     });
     store.removeQuads(deletes);
     store.addQuads(inserts);
-    const metadata = new RepresentationMetadata(input.identifier.path, { [MA_CONTENT_TYPE]: INTERNAL_QUADS });
+    const metadata = new RepresentationMetadata(input.identifier.path, { [CONTENT_TYPE]: INTERNAL_QUADS });
     const representation: Representation = {
       binary: false,
       data: store.match() as Readable,
diff --git a/src/util/InteractionController.ts b/src/util/InteractionController.ts
index cd154ad8a..290e08d7c 100644
--- a/src/util/InteractionController.ts
+++ b/src/util/InteractionController.ts
@@ -1,6 +1,6 @@
 import type { Term } from 'rdf-js';
 import { v4 as uuid } from 'uuid';
-import { LINK_TYPE_LDP_BC, LINK_TYPE_LDPC } from './LinkTypes';
+import { LDP } from './UriConstants';
 import { trimTrailingSlashes } from './Util';
 
 export class InteractionController {
@@ -11,7 +11,7 @@ export class InteractionController {
    */
   public isContainer(slug?: string, types?: Term[]): boolean {
     if (types && types.length > 0) {
-      return types.some((type): boolean => type.value === LINK_TYPE_LDPC || type.value === LINK_TYPE_LDP_BC);
+      return types.some((type): boolean => type.value === LDP.Container || type.value === LDP.BasicContainer);
     }
     return Boolean(slug?.endsWith('/'));
   }
diff --git a/src/util/LinkTypes.ts b/src/util/LinkTypes.ts
deleted file mode 100644
index 2ff1d414e..000000000
--- a/src/util/LinkTypes.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const LINK_TYPE_LDPC = 'http://www.w3.org/ns/ldp#Container';
-export const LINK_TYPE_LDP_BC = 'http://www.w3.org/ns/ldp#BasicContainer';
-export const LINK_TYPE_LDPR = 'http://www.w3.org/ns/ldp#Resource';
diff --git a/src/util/MetadataController.ts b/src/util/MetadataController.ts
index cccb13fdc..89c76223d 100644
--- a/src/util/MetadataController.ts
+++ b/src/util/MetadataController.ts
@@ -2,23 +2,14 @@ import { Stats } from 'fs';
 import { Readable } from 'stream';
 import arrayifyStream from 'arrayify-stream';
 import { DataFactory, StreamParser, StreamWriter } from 'n3';
-import type { NamedNode, Quad } from 'rdf-js';
+import type { Quad } from 'rdf-js';
 import streamifyArray from 'streamify-array';
+import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
 import { TEXT_TURTLE } from './ContentTypes';
-import { LDP, RDF, STAT, TERMS, XML } from './Prefixes';
+import { DCTERMS, LDP, POSIX, RDF, XSD } from './UriConstants';
+import { getNamedNode, getTypedLiteral } from './UriUtil';
 import { pipeStreamsAndErrors } from './Util';
 
-export const TYPE_PREDICATE = DataFactory.namedNode(`${RDF}type`);
-export const MODIFIED_PREDICATE = DataFactory.namedNode(`${TERMS}modified`);
-export const CONTAINS_PREDICATE = DataFactory.namedNode(`${LDP}contains`);
-export const MTIME_PREDICATE = DataFactory.namedNode(`${STAT}mtime`);
-export const SIZE_PREDICATE = DataFactory.namedNode(`${STAT}size`);
-
-export const CONTAINER_OBJECT = DataFactory.namedNode(`${LDP}Container`);
-export const BASIC_CONTAINER_OBJECT = DataFactory.namedNode(`${LDP}BasicContainer`);
-export const RESOURCE_OBJECT = DataFactory.namedNode(`${LDP}Resource`);
-export const DATETIME_OBJECT = DataFactory.namedNode(`${XML}dateTime`);
-
 export class MetadataController {
   /**
    * Helper function to generate quads for a Container or Resource.
@@ -28,40 +19,28 @@ export class MetadataController {
    * @returns The generated quads.
    */
   public generateResourceQuads(URI: string, stats: Stats): Quad[] {
-    const subject: NamedNode = DataFactory.namedNode(URI);
-    const quads: Quad[] = [];
-
+    const metadata = new RepresentationMetadata(URI);
     if (stats.isDirectory()) {
-      quads.push(DataFactory.quad(subject, TYPE_PREDICATE, CONTAINER_OBJECT));
-      quads.push(DataFactory.quad(subject, TYPE_PREDICATE, BASIC_CONTAINER_OBJECT));
+      metadata.add(RDF.type, getNamedNode(LDP.Container));
+      metadata.add(RDF.type, getNamedNode(LDP.BasicContainer));
     }
-    quads.push(DataFactory.quad(subject, TYPE_PREDICATE, RESOURCE_OBJECT));
-    quads.push(DataFactory.quad(subject, SIZE_PREDICATE, DataFactory.literal(stats.size)));
-    quads.push(DataFactory.quad(
-      subject,
-      MODIFIED_PREDICATE,
-      DataFactory.literal(stats.mtime.toUTCString(), DATETIME_OBJECT),
-    ));
-    quads.push(DataFactory.quad(
-      subject,
-      MTIME_PREDICATE,
-      DataFactory.literal(stats.mtime.getTime() / 100),
-    ));
+    metadata.add(RDF.type, getNamedNode(LDP.Resource));
+    metadata.add(POSIX.size, getTypedLiteral(stats.size, XSD.integer));
+    metadata.add(DCTERMS.modified, getTypedLiteral(stats.mtime.toISOString(), XSD.dateTime));
+    metadata.add(POSIX.mtime, getTypedLiteral(Math.floor(stats.mtime.getTime() / 1000), XSD.integer));
 
-    return quads;
+    return metadata.quads();
   }
 
   /**
-   * Helper function to generate the quad describing that the resource URI is a child of the container URI.
+   * Helper function to generate the quads describing that the resource URIs are children of the container URI.
    * @param containerURI - The URI of the container.
-   * @param childURI - The URI of the child resource.
+   * @param childURIs - The URI of the child resources.
    *
-   * @returns The generated quad.
+   * @returns The generated quads.
    */
-  public generateContainerContainsResourceQuad(containerURI: string, childURI: string): Quad {
-    return DataFactory.quad(DataFactory.namedNode(containerURI), CONTAINS_PREDICATE, DataFactory.namedNode(
-      childURI,
-    ));
+  public generateContainerContainsResourceQuads(containerURI: string, childURIs: string[]): Quad[] {
+    return new RepresentationMetadata(containerURI, { [LDP.contains]: childURIs.map(DataFactory.namedNode) }).quads();
   }
 
   /**
diff --git a/src/util/MetadataTypes.ts b/src/util/MetadataTypes.ts
deleted file mode 100644
index 2ff7fbc0f..000000000
--- a/src/util/MetadataTypes.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export const RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
-
-export const ACL_RESOURCE = 'urn:solid:acl:resource';
-
-export const MA_CONTENT_TYPE = 'http://www.w3.org/ns/ma-ont#format';
-export const HTTP_SLUG = 'urn:solid:http:slug';
-export const HTTP_LAST_CHANGED = 'urn:solid:http:lastChanged';
-export const HTTP_BYTE_SIZE = 'urn:solid:http:byteSize';
-
-export const XSD_DATE_TIME = 'http://www.w3.org/2001/XMLSchema#dateTime';
-export const XSD_INTEGER = 'http://www.w3.org/2001/XMLSchema#integer';
diff --git a/src/util/Prefixes.ts b/src/util/Prefixes.ts
deleted file mode 100644
index cce6f80aa..000000000
--- a/src/util/Prefixes.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
-export const LDP = 'http://www.w3.org/ns/ldp#';
-export const TERMS = 'http://purl.org/dc/terms/';
-export const XML = 'http://www.w3.org/2001/XMLSchema#';
-export const STAT = 'http://www.w3.org/ns/posix/stat#';
diff --git a/src/util/UriConstants.ts b/src/util/UriConstants.ts
new file mode 100644
index 000000000..fe9653fe2
--- /dev/null
+++ b/src/util/UriConstants.ts
@@ -0,0 +1,65 @@
+const createSuffixFn = (prefix: string): any => (suffix: string): string => `${prefix}${suffix}`;
+
+const ACL_PREFIX = createSuffixFn('http://www.w3.org/ns/auth/acl#');
+export const ACL = {
+  accessTo: ACL_PREFIX('accessTo'),
+  agent: ACL_PREFIX('agent'),
+  agentClass: ACL_PREFIX('agentClass'),
+  default: ACL_PREFIX('default'),
+  mode: ACL_PREFIX('mode'),
+
+  Write: ACL_PREFIX('Write'),
+  Read: ACL_PREFIX('Read'),
+  Append: ACL_PREFIX('Append'),
+  Control: ACL_PREFIX('Control'),
+};
+
+const DCTERMS_PREFIX = createSuffixFn('http://purl.org/dc/terms/');
+export const DCTERMS = {
+  modified: DCTERMS_PREFIX('modified'),
+};
+
+const FOAF_PREFIX = createSuffixFn('http://xmlns.com/foaf/0.1/');
+export const FOAF = {
+  Agent: FOAF_PREFIX('Agent'),
+  AuthenticatedAgent: FOAF_PREFIX('AuthenticatedAgent'),
+};
+
+const HTTP_PREFIX = createSuffixFn('urn:solid:http:');
+export const HTTP = {
+  slug: HTTP_PREFIX('slug'),
+};
+
+const LDP_PREFIX = createSuffixFn('http://www.w3.org/ns/ldp#');
+export const LDP = {
+  contains: LDP_PREFIX('contains'),
+
+  BasicContainer: LDP_PREFIX('BasicContainer'),
+  Container: LDP_PREFIX('Container'),
+  Resource: LDP_PREFIX('Resource'),
+};
+
+const MA_PREFIX = createSuffixFn('http://www.w3.org/ns/ma-ont#');
+export const MA = {
+  format: MA_PREFIX('format'),
+};
+
+const POSIX_PREFIX = createSuffixFn('http://www.w3.org/ns/posix/stat#');
+export const POSIX = {
+  mtime: POSIX_PREFIX('mtime'),
+  size: POSIX_PREFIX('size'),
+};
+
+const RDF_PREFIX = createSuffixFn('http://www.w3.org/1999/02/22-rdf-syntax-ns#');
+export const RDF = {
+  type: RDF_PREFIX('type'),
+};
+
+const XSD_PREFIX = createSuffixFn('http://www.w3.org/2001/XMLSchema#');
+export const XSD = {
+  dateTime: XSD_PREFIX('dateTime'),
+  integer: XSD_PREFIX('integer'),
+};
+
+// Alias for most commonly used URI
+export const CONTENT_TYPE = MA.format;
diff --git a/src/util/UriUtil.ts b/src/util/UriUtil.ts
new file mode 100644
index 000000000..a1c4b9cb3
--- /dev/null
+++ b/src/util/UriUtil.ts
@@ -0,0 +1,51 @@
+import { DataFactory } from 'n3';
+import type { Literal, NamedNode, Term } from 'rdf-js';
+import { CONTENT_TYPE } from './UriConstants';
+
+// Shorthands for commonly used predicates
+const shorthands: { [id: string]: NamedNode } = {
+  contentType: DataFactory.namedNode(CONTENT_TYPE),
+};
+
+// Caches named node conversions
+const termMap: { [id: string]: NamedNode } = {};
+
+/**
+ * @param input - Checks if this is a {@link Term}.
+ */
+export const isTerm = (input?: any): input is Term => input?.termType;
+
+/**
+ * Converts the incoming name to a named node if needed.
+ * In case of string, first checks if it is a shorthand, if not a new named node gets made.
+ * The generated terms get cached to prevent the amount of named nodes that get created,
+ * so only use this for internal constants!
+ * @param name - Predicate to potentially transform.
+ */
+export const getNamedNode = (name: NamedNode | string): NamedNode => {
+  if (typeof name === 'string') {
+    if (shorthands[name]) {
+      return shorthands[name];
+    }
+    if (!termMap[name]) {
+      termMap[name] = DataFactory.namedNode(name);
+    }
+    return termMap[name];
+  }
+  return name;
+};
+
+/**
+ * Converts an object to a literal when needed.
+ * @param object - Object to potentially transform.
+ */
+export const getObjectTerm = (object: NamedNode | Literal | string): NamedNode | Literal =>
+  typeof object === 'string' ? DataFactory.literal(object) : object;
+
+/**
+ * Creates a literal by first converting the dataType string to a named node.
+ * @param object - Object value.
+ * @param dataType - Object data type (as string).
+ */
+export const getTypedLiteral = (object: string | number, dataType: string): Literal =>
+  DataFactory.literal(object, getNamedNode(dataType));


Test patch:
diff --git a/test/integration/FileResourceStore.test.ts b/test/integration/FileResourceStore.test.ts
index 3b3adce9e..f7e8452ca 100644
--- a/test/integration/FileResourceStore.test.ts
+++ b/test/integration/FileResourceStore.test.ts
@@ -155,8 +155,8 @@ describe('A server using a FileResourceStore', (): void => {
       response = await fileHelper.getFolder(folderId);
       expect(response.statusCode).toBe(200);
       expect(response._getHeaders().location).toBe(folderId);
-      expect(response._getBuffer().toString()).toContain('<http://www.w3.org/ns/ldp#contains> <http://test.com/testfolder3/subfolder0>.');
-      expect(response._getBuffer().toString()).toContain('<http://www.w3.org/ns/ldp#contains> <http://test.com/testfolder3/testfile0.txt>.');
+      expect(response._getBuffer().toString()).toContain('<http://www.w3.org/ns/ldp#contains> <http://test.com/testfolder3/subfolder0> .');
+      expect(response._getBuffer().toString()).toContain('<http://www.w3.org/ns/ldp#contains> <http://test.com/testfolder3/testfile0.txt> .');
 
       // DELETE
       await fileHelper.deleteFile(fileId);
diff --git a/test/integration/RepresentationConverter.test.ts b/test/integration/RepresentationConverter.test.ts
index 9b342ff6b..620332b7f 100644
--- a/test/integration/RepresentationConverter.test.ts
+++ b/test/integration/RepresentationConverter.test.ts
@@ -4,7 +4,7 @@ import { RepresentationMetadata } from '../../src/ldp/representation/Representat
 import { ChainedConverter } from '../../src/storage/conversion/ChainedConverter';
 import { QuadToRdfConverter } from '../../src/storage/conversion/QuadToRdfConverter';
 import { RdfToQuadConverter } from '../../src/storage/conversion/RdfToQuadConverter';
-import { MA_CONTENT_TYPE } from '../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../src/util/UriConstants';
 import { readableToString } from '../../src/util/Util';
 
 describe('A ChainedConverter', (): void => {
@@ -15,7 +15,7 @@ describe('A ChainedConverter', (): void => {
   const converter = new ChainedConverter(converters);
 
   it('can convert from JSON-LD to turtle.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'application/ld+json' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'application/ld+json' });
     const representation: Representation = {
       binary: true,
       data: streamifyArray([ '{"@id": "http://test.com/s", "http://test.com/p": { "@id": "http://test.com/o" }}' ]),
@@ -33,7 +33,7 @@ describe('A ChainedConverter', (): void => {
   });
 
   it('can convert from turtle to JSON-LD.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     const representation: Representation = {
       binary: true,
       data: streamifyArray([ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ]),
diff --git a/test/unit/ldp/http/BasicResponseWriter.test.ts b/test/unit/ldp/http/BasicResponseWriter.test.ts
index a584a4ae6..693c7d7a8 100644
--- a/test/unit/ldp/http/BasicResponseWriter.test.ts
+++ b/test/unit/ldp/http/BasicResponseWriter.test.ts
@@ -5,7 +5,7 @@ import { BasicResponseWriter } from '../../../../src/ldp/http/BasicResponseWrite
 import { ResponseDescription } from '../../../../src/ldp/operations/ResponseDescription';
 import { RepresentationMetadata } from '../../../../src/ldp/representation/RepresentationMetadata';
 import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A BasicResponseWriter', (): void => {
   const writer = new BasicResponseWriter();
@@ -48,7 +48,7 @@ describe('A BasicResponseWriter', (): void => {
   });
 
   it('responds with a content-type if the metadata has it.', async(done): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     const body = {
       binary: true,
       data: streamifyArray([ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ]),
diff --git a/test/unit/ldp/http/RawBodyParser.test.ts b/test/unit/ldp/http/RawBodyParser.test.ts
index 3bad403cc..9ed9ef30a 100644
--- a/test/unit/ldp/http/RawBodyParser.test.ts
+++ b/test/unit/ldp/http/RawBodyParser.test.ts
@@ -5,7 +5,7 @@ import { RepresentationMetadata } from '../../../../src/ldp/representation/Repre
 import { HttpRequest } from '../../../../src/server/HttpRequest';
 import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError';
 import 'jest-rdf';
-import { HTTP_SLUG, RDF_TYPE } from '../../../../src/util/MetadataTypes';
+import { HTTP, RDF } from '../../../../src/util/UriConstants';
 
 describe('A RawBodyparser', (): void => {
   const bodyParser = new RawBodyParser();
@@ -54,7 +54,7 @@ describe('A RawBodyparser', (): void => {
     input.headers = { 'transfer-encoding': 'chunked', 'content-type': 'text/turtle', slug: 'slugText' };
     const result = (await bodyParser.handle(input))!;
     expect(result.metadata.contentType).toEqual('text/turtle');
-    expect(result.metadata.get(HTTP_SLUG)?.value).toEqual('slugText');
+    expect(result.metadata.get(HTTP.slug)?.value).toEqual('slugText');
   });
 
   it('errors if there are multiple slugs.', async(): Promise<void> => {
@@ -72,7 +72,7 @@ describe('A RawBodyparser', (): void => {
       link: '<http://www.w3.org/ns/ldp#Container>; rel="type"' };
     const result = (await bodyParser.handle(input))!;
     expect(result.metadata.contentType).toEqual('text/turtle');
-    expect(result.metadata.get(RDF_TYPE)?.value).toEqual('http://www.w3.org/ns/ldp#Container');
+    expect(result.metadata.get(RDF.type)?.value).toEqual('http://www.w3.org/ns/ldp#Container');
   });
 
   it('ignores unknown link headers.', async(): Promise<void> => {
diff --git a/test/unit/ldp/representation/RepresentationMetadata.test.ts b/test/unit/ldp/representation/RepresentationMetadata.test.ts
index fb1422007..ee36cdf46 100644
--- a/test/unit/ldp/representation/RepresentationMetadata.test.ts
+++ b/test/unit/ldp/representation/RepresentationMetadata.test.ts
@@ -1,7 +1,7 @@
 import { literal, namedNode, quad } from '@rdfjs/data-model';
 import type { Literal, NamedNode, Quad } from 'rdf-js';
 import { RepresentationMetadata } from '../../../../src/ldp/representation/RepresentationMetadata';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A RepresentationMetadata', (): void => {
   let metadata: RepresentationMetadata;
@@ -180,15 +180,15 @@ describe('A RepresentationMetadata', (): void => {
     it('has a shorthand for content-type.', async(): Promise<void> => {
       expect(metadata.contentType).toBeUndefined();
       metadata.contentType = 'a/b';
-      expect(metadata.get(MA_CONTENT_TYPE)).toEqualRdfTerm(literal('a/b'));
+      expect(metadata.get(CONTENT_TYPE)).toEqualRdfTerm(literal('a/b'));
       expect(metadata.contentType).toEqual('a/b');
       metadata.contentType = undefined;
       expect(metadata.contentType).toBeUndefined();
     });
 
     it('errors if a shorthand has multiple values.', async(): Promise<void> => {
-      metadata.add(MA_CONTENT_TYPE, 'a/b');
-      metadata.add(MA_CONTENT_TYPE, 'c/d');
+      metadata.add(CONTENT_TYPE, 'a/b');
+      metadata.add(CONTENT_TYPE, 'c/d');
       expect((): any => metadata.contentType).toThrow();
     });
   });
diff --git a/test/unit/storage/FileResourceStore.test.ts b/test/unit/storage/FileResourceStore.test.ts
index 972a5e8f7..4e02add46 100644
--- a/test/unit/storage/FileResourceStore.test.ts
+++ b/test/unit/storage/FileResourceStore.test.ts
@@ -15,10 +15,8 @@ import { MethodNotAllowedHttpError } from '../../../src/util/errors/MethodNotAll
 import { NotFoundHttpError } from '../../../src/util/errors/NotFoundHttpError';
 import { UnsupportedMediaTypeHttpError } from '../../../src/util/errors/UnsupportedMediaTypeHttpError';
 import { InteractionController } from '../../../src/util/InteractionController';
-import { LINK_TYPE_LDP_BC, LINK_TYPE_LDPR } from '../../../src/util/LinkTypes';
 import { MetadataController } from '../../../src/util/MetadataController';
-import { HTTP_BYTE_SIZE, HTTP_LAST_CHANGED, HTTP_SLUG, RDF_TYPE } from '../../../src/util/MetadataTypes';
-import { LDP, RDF, STAT, TERMS, XML } from '../../../src/util/Prefixes';
+import { DCTERMS, HTTP, LDP, POSIX, RDF, XSD } from '../../../src/util/UriConstants';
 
 const { join: joinPath } = posix;
 
@@ -133,8 +131,8 @@ describe('A FileResourceStore', (): void => {
     (fs.createReadStream as jest.Mock).mockImplementationOnce((): any => new Error('Metadata file does not exist.'));
 
     // Write container (POST)
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
-    representation.metadata.add(HTTP_SLUG, 'myContainer/');
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
+    representation.metadata.add(HTTP.slug, 'myContainer/');
     const identifier = await store.addResource({ path: base }, representation);
     expect(fsPromises.mkdir as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'myContainer/'), { recursive: true });
     expect(identifier.path).toBe(`${base}myContainer/`);
@@ -146,7 +144,7 @@ describe('A FileResourceStore', (): void => {
       data: expect.any(Readable),
       metadata: expect.any(RepresentationMetadata),
     });
-    expect(result.metadata.get(HTTP_LAST_CHANGED)?.value).toEqual(stats.mtime.toISOString());
+    expect(result.metadata.get(DCTERMS.modified)?.value).toEqual(stats.mtime.toISOString());
     expect(result.metadata.contentType).toEqual(INTERNAL_QUADS);
     await expect(arrayifyStream(result.data)).resolves.toBeDefined();
   });
@@ -156,8 +154,8 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.lstat as jest.Mock).mockReturnValueOnce(stats);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
-    representation.metadata.add(HTTP_SLUG, 'myContainer/');
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
+    representation.metadata.add(HTTP.slug, 'myContainer/');
     await expect(store.addResource({ path: `${base}foo` }, representation)).rejects.toThrow(MethodNotAllowedHttpError);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo'));
   });
@@ -173,19 +171,19 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.lstat as jest.Mock).mockReturnValueOnce(stats);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
-    representation.metadata.add(HTTP_SLUG, 'myContainer/');
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
+    representation.metadata.add(HTTP.slug, 'myContainer/');
     await expect(store.addResource({ path: `${base}doesnotexist` }, representation))
       .rejects.toThrow(MethodNotAllowedHttpError);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'doesnotexist'));
 
-    representation.metadata.set(RDF_TYPE, LINK_TYPE_LDPR);
-    representation.metadata.set(HTTP_SLUG, 'file.txt');
+    representation.metadata.set(RDF.type, LDP.Resource);
+    representation.metadata.set(HTTP.slug, 'file.txt');
     await expect(store.addResource({ path: `${base}doesnotexist` }, representation))
       .rejects.toThrow(MethodNotAllowedHttpError);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'doesnotexist'));
 
-    representation.metadata.removeAll(RDF_TYPE);
+    representation.metadata.removeAll(RDF.type);
     await expect(store.addResource({ path: `${base}existingresource` }, representation))
       .rejects.toThrow(MethodNotAllowedHttpError);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'existingresource'));
@@ -217,8 +215,8 @@ describe('A FileResourceStore', (): void => {
       data: expect.any(Readable),
       metadata: expect.any(RepresentationMetadata),
     });
-    expect(result.metadata.get(HTTP_LAST_CHANGED)?.value).toEqual(stats.mtime.toISOString());
-    expect(result.metadata.get(HTTP_BYTE_SIZE)?.value).toEqual(`${stats.size}`);
+    expect(result.metadata.get(DCTERMS.modified)?.value).toEqual(stats.mtime.toISOString());
+    expect(result.metadata.get(POSIX.size)?.value).toEqual(`${stats.size}`);
     expect(result.metadata.contentType).toEqual('text/plain');
     await expect(arrayifyStream(result.data)).resolves.toEqual([ rawData ]);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'file.txt'));
@@ -254,8 +252,8 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.lstat as jest.Mock).mockReturnValueOnce(stats);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDPR);
-    representation.metadata.add(HTTP_SLUG, 'file.txt');
+    representation.metadata.add(RDF.type, LDP.Resource);
+    representation.metadata.add(HTTP.slug, 'file.txt');
     const identifier = await store.addResource({ path: `${base}doesnotexistyet/` }, representation);
     expect(identifier.path).toBe(`${base}doesnotexistyet/file.txt`);
     expect(fsPromises.mkdir as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'doesnotexistyet/'),
@@ -280,7 +278,7 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.lstat as jest.Mock).mockReturnValueOnce(stats);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDPR);
+    representation.metadata.add(RDF.type, LDP.Resource);
     representation.data = readableMock;
     await store.addResource({ path: `${base}foo/` }, representation);
     expect(fsPromises.mkdir as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo/'), { recursive: true });
@@ -350,17 +348,17 @@ describe('A FileResourceStore', (): void => {
     const containerNode = namedNode(`${base}foo/`);
     const fileNode = namedNode(`${base}foo/file.txt`);
     const quads = [
-      quadRDF(containerNode, namedNode(`${RDF}type`), namedNode(`${LDP}Container`)),
-      quadRDF(containerNode, namedNode(`${RDF}type`), namedNode(`${LDP}BasicContainer`)),
-      quadRDF(containerNode, namedNode(`${RDF}type`), namedNode(`${LDP}Resource`)),
-      quadRDF(containerNode, namedNode(`${STAT}size`), DataFactory.literal(stats.size)),
-      quadRDF(containerNode, namedNode(`${TERMS}modified`), literal(stats.mtime.toUTCString(), `${XML}dateTime`)),
-      quadRDF(containerNode, namedNode(`${STAT}mtime`), DataFactory.literal(stats.mtime.getTime() / 100)),
-      quadRDF(containerNode, namedNode(`${LDP}contains`), fileNode),
-      quadRDF(fileNode, namedNode(`${RDF}type`), namedNode(`${LDP}Resource`)),
-      quadRDF(fileNode, namedNode(`${STAT}size`), DataFactory.literal(stats.size)),
-      quadRDF(fileNode, namedNode(`${TERMS}modified`), literal(stats.mtime.toUTCString(), `${XML}dateTime`)),
-      quadRDF(fileNode, namedNode(`${STAT}mtime`), DataFactory.literal(stats.mtime.getTime() / 100)),
+      quadRDF(containerNode, namedNode(RDF.type), namedNode(LDP.Container)),
+      quadRDF(containerNode, namedNode(RDF.type), namedNode(LDP.BasicContainer)),
+      quadRDF(containerNode, namedNode(RDF.type), namedNode(LDP.Resource)),
+      quadRDF(containerNode, namedNode(POSIX.size), DataFactory.literal(stats.size)),
+      quadRDF(containerNode, namedNode(DCTERMS.modified), literal(stats.mtime.toISOString(), namedNode(XSD.dateTime))),
+      quadRDF(containerNode, namedNode(POSIX.mtime), DataFactory.literal(Math.floor(stats.mtime.getTime() / 1000))),
+      quadRDF(containerNode, namedNode(LDP.contains), fileNode),
+      quadRDF(fileNode, namedNode(RDF.type), namedNode(LDP.Resource)),
+      quadRDF(fileNode, namedNode(POSIX.size), DataFactory.literal(stats.size)),
+      quadRDF(fileNode, namedNode(DCTERMS.modified), literal(stats.mtime.toISOString(), namedNode(XSD.dateTime))),
+      quadRDF(fileNode, namedNode(POSIX.mtime), DataFactory.literal(Math.floor(stats.mtime.getTime() / 1000))),
     ];
     const result = await store.getRepresentation({ path: `${base}foo/` });
     expect(result).toEqual({
@@ -368,9 +366,9 @@ describe('A FileResourceStore', (): void => {
       data: expect.any(Readable),
       metadata: expect.any(RepresentationMetadata),
     });
-    expect(result.metadata.get(HTTP_LAST_CHANGED)?.value).toEqual(stats.mtime.toISOString());
+    expect(result.metadata.get(DCTERMS.modified)?.value).toEqual(stats.mtime.toISOString());
     expect(result.metadata.contentType).toEqual(INTERNAL_QUADS);
-    await expect(arrayifyStream(result.data)).resolves.toEqualRdfQuadArray(quads);
+    await expect(arrayifyStream(result.data)).resolves.toBeRdfIsomorphic(quads);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo/'));
     expect(fsPromises.readdir as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo/'));
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo', 'file.txt'));
@@ -387,7 +385,7 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.lstat as jest.Mock).mockReturnValueOnce(stats);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDPR);
+    representation.metadata.add(RDF.type, LDP.Resource);
     await store.setRepresentation({ path: `${base}alreadyexists.txt` }, representation);
     expect(fs.createWriteStream as jest.Mock).toBeCalledTimes(2);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'alreadyexists.txt'));
@@ -403,7 +401,7 @@ describe('A FileResourceStore', (): void => {
     await expect(store.setRepresentation({ path: `${base}alreadyexists` }, representation)).rejects
       .toThrow(ConflictHttpError);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'alreadyexists'));
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
     await expect(store.setRepresentation({ path: `${base}alreadyexists/` }, representation)).rejects
       .toThrow(ConflictHttpError);
     expect(fsPromises.access as jest.Mock).toBeCalledTimes(1);
@@ -417,7 +415,7 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.mkdir as jest.Mock).mockReturnValueOnce(true);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
     await store.setRepresentation({ path: `${base}foo/` }, representation);
     expect(fsPromises.mkdir as jest.Mock).toBeCalledTimes(1);
     expect(fsPromises.access as jest.Mock).toBeCalledTimes(1);
@@ -435,8 +433,8 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.unlink as jest.Mock).mockReturnValueOnce(true);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDPR);
-    representation.metadata.add(HTTP_SLUG, 'file.txt');
+    representation.metadata.add(RDF.type, LDP.Resource);
+    representation.metadata.add(HTTP.slug, 'file.txt');
     await expect(store.addResource({ path: base }, representation)).rejects.toThrow(Error);
     expect(fs.createWriteStream as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'file.txt.metadata'));
     expect(fs.createWriteStream as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'file.txt'));
@@ -452,8 +450,8 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.rmdir as jest.Mock).mockReturnValueOnce(true);
 
     // Tests
-    representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
-    representation.metadata.add(HTTP_SLUG, 'foo/');
+    representation.metadata.add(RDF.type, LDP.BasicContainer);
+    representation.metadata.add(HTTP.slug, 'foo/');
     await expect(store.addResource({ path: base }, representation)).rejects.toThrow(Error);
     expect(fsPromises.rmdir as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo/'));
   });
@@ -464,7 +462,7 @@ describe('A FileResourceStore', (): void => {
     (fsPromises.mkdir as jest.Mock).mockReturnValueOnce(true);
 
     // Tests
-    representation.metadata.add(HTTP_SLUG, 'myContainer/');
+    representation.metadata.add(HTTP.slug, 'myContainer/');
     const identifier = await store.addResource({ path: base }, representation);
     expect(identifier.path).toBe(`${base}myContainer/`);
     expect(fsPromises.mkdir as jest.Mock).toBeCalledTimes(1);
@@ -485,8 +483,8 @@ describe('A FileResourceStore', (): void => {
       metadata: expect.any(RepresentationMetadata),
     });
     expect(result.metadata.contentType).toEqual('application/octet-stream');
-    expect(result.metadata.get(HTTP_LAST_CHANGED)?.value).toEqual(stats.mtime.toISOString());
-    expect(result.metadata.get(HTTP_BYTE_SIZE)?.value).toEqual(`${stats.size}`);
+    expect(result.metadata.get(DCTERMS.modified)?.value).toEqual(stats.mtime.toISOString());
+    expect(result.metadata.get(POSIX.size)?.value).toEqual(`${stats.size}`);
   });
 
   it('errors when performing a PUT on the root path.', async(): Promise<void> => {
@@ -519,8 +517,8 @@ describe('A FileResourceStore', (): void => {
       (fsPromises.mkdir as jest.Mock).mockReturnValue(true);
 
       // Tests
-      representation.metadata.add(RDF_TYPE, LINK_TYPE_LDP_BC);
-      representation.metadata.add(HTTP_SLUG, 'bar');
+      representation.metadata.add(RDF.type, LDP.BasicContainer);
+      representation.metadata.add(HTTP.slug, 'bar');
       const identifier = await store.addResource({ path: `${base}foo` }, representation);
       expect(identifier.path).toBe(`${base}foo/bar/`);
       expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, 'foo'));
@@ -552,8 +550,8 @@ describe('A FileResourceStore', (): void => {
       data: expect.any(Readable),
       metadata: expect.any(RepresentationMetadata),
     });
-    expect(result.metadata.get(HTTP_LAST_CHANGED)?.value).toEqual(stats.mtime.toISOString());
-    expect(result.metadata.get(HTTP_BYTE_SIZE)?.value).toEqual(`${stats.size}`);
+    expect(result.metadata.get(DCTERMS.modified)?.value).toEqual(stats.mtime.toISOString());
+    expect(result.metadata.get(POSIX.size)?.value).toEqual(`${stats.size}`);
     await expect(arrayifyStream(result.data)).resolves.toEqual([ rawData ]);
     expect(fsPromises.lstat as jest.Mock).toBeCalledWith(joinPath(rootFilepath, name));
     expect(fs.createReadStream as jest.Mock).toBeCalledWith(joinPath(rootFilepath, name));
diff --git a/test/unit/storage/RepresentationConvertingStore.test.ts b/test/unit/storage/RepresentationConvertingStore.test.ts
index 321942791..0e395222f 100644
--- a/test/unit/storage/RepresentationConvertingStore.test.ts
+++ b/test/unit/storage/RepresentationConvertingStore.test.ts
@@ -2,14 +2,14 @@ import { RepresentationMetadata } from '../../../src/ldp/representation/Represen
 import { RepresentationConverter } from '../../../src/storage/conversion/RepresentationConverter';
 import { RepresentationConvertingStore } from '../../../src/storage/RepresentationConvertingStore';
 import { ResourceStore } from '../../../src/storage/ResourceStore';
-import { MA_CONTENT_TYPE } from '../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../src/util/UriConstants';
 
 describe('A RepresentationConvertingStore', (): void => {
   let store: RepresentationConvertingStore;
   let source: ResourceStore;
   let handleSafeFn: jest.Mock<Promise<void>, []>;
   let converter: RepresentationConverter;
-  const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+  const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
 
   beforeEach(async(): Promise<void> => {
     source = {
diff --git a/test/unit/storage/conversion/ChainedConverter.test.ts b/test/unit/storage/conversion/ChainedConverter.test.ts
index 5f8d2956b..ffd100ba2 100644
--- a/test/unit/storage/conversion/ChainedConverter.test.ts
+++ b/test/unit/storage/conversion/ChainedConverter.test.ts
@@ -5,7 +5,7 @@ import { ChainedConverter } from '../../../../src/storage/conversion/ChainedConv
 import { checkRequest } from '../../../../src/storage/conversion/ConversionUtil';
 import { RepresentationConverterArgs } from '../../../../src/storage/conversion/RepresentationConverter';
 import { TypedRepresentationConverter } from '../../../../src/storage/conversion/TypedRepresentationConverter';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 class DummyConverter extends TypedRepresentationConverter {
   private readonly inTypes: { [contentType: string]: number };
@@ -31,7 +31,7 @@ class DummyConverter extends TypedRepresentationConverter {
 
   public async handle(input: RepresentationConverterArgs): Promise<Representation> {
     const metadata = new RepresentationMetadata(input.representation.metadata,
-      { [MA_CONTENT_TYPE]: input.preferences.type![0].value });
+      { [CONTENT_TYPE]: input.preferences.type![0].value });
     return { ...input.representation, metadata };
   }
 }
@@ -51,7 +51,7 @@ describe('A ChainedConverter', (): void => {
     ];
     converter = new ChainedConverter(converters);
 
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     representation = { metadata } as Representation;
     preferences = { type: [{ value: 'internal/quads', weight: 1 }]};
     args = { representation, preferences, identifier: { path: 'path' }};
diff --git a/test/unit/storage/conversion/QuadToRdfConverter.test.ts b/test/unit/storage/conversion/QuadToRdfConverter.test.ts
index d9d0c3f5e..518746c62 100644
--- a/test/unit/storage/conversion/QuadToRdfConverter.test.ts
+++ b/test/unit/storage/conversion/QuadToRdfConverter.test.ts
@@ -8,12 +8,12 @@ import { RepresentationPreferences } from '../../../../src/ldp/representation/Re
 import { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceIdentifier';
 import { QuadToRdfConverter } from '../../../../src/storage/conversion/QuadToRdfConverter';
 import { INTERNAL_QUADS } from '../../../../src/util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A QuadToRdfConverter', (): void => {
   const converter = new QuadToRdfConverter();
   const identifier: ResourceIdentifier = { path: 'path' };
-  const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: INTERNAL_QUADS });
+  const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: INTERNAL_QUADS });
 
   it('supports parsing quads.', async(): Promise<void> => {
     await expect(converter.getInputTypes()).resolves.toEqual({ [INTERNAL_QUADS]: 1 });
diff --git a/test/unit/storage/conversion/QuadToTurtleConverter.test.ts b/test/unit/storage/conversion/QuadToTurtleConverter.test.ts
index fe70504b8..1e2281d31 100644
--- a/test/unit/storage/conversion/QuadToTurtleConverter.test.ts
+++ b/test/unit/storage/conversion/QuadToTurtleConverter.test.ts
@@ -7,12 +7,12 @@ import { RepresentationPreferences } from '../../../../src/ldp/representation/Re
 import { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceIdentifier';
 import { QuadToTurtleConverter } from '../../../../src/storage/conversion/QuadToTurtleConverter';
 import { INTERNAL_QUADS } from '../../../../src/util/ContentTypes';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A QuadToTurtleConverter', (): void => {
   const converter = new QuadToTurtleConverter();
   const identifier: ResourceIdentifier = { path: 'path' };
-  const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: INTERNAL_QUADS });
+  const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: INTERNAL_QUADS });
 
   it('can handle quad to turtle conversions.', async(): Promise<void> => {
     const representation = { metadata } as Representation;
diff --git a/test/unit/storage/conversion/RdfToQuadConverter.test.ts b/test/unit/storage/conversion/RdfToQuadConverter.test.ts
index c842b0f07..66b64762f 100644
--- a/test/unit/storage/conversion/RdfToQuadConverter.test.ts
+++ b/test/unit/storage/conversion/RdfToQuadConverter.test.ts
@@ -10,7 +10,7 @@ import { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceI
 import { RdfToQuadConverter } from '../../../../src/storage/conversion/RdfToQuadConverter';
 import { INTERNAL_QUADS } from '../../../../src/util/ContentTypes';
 import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A RdfToQuadConverter.test.ts', (): void => {
   const converter = new RdfToQuadConverter();
@@ -25,21 +25,21 @@ describe('A RdfToQuadConverter.test.ts', (): void => {
   });
 
   it('can handle turtle to quad conversions.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     const representation = { metadata } as Representation;
     const preferences: RepresentationPreferences = { type: [{ value: INTERNAL_QUADS, weight: 1 }]};
     await expect(converter.canHandle({ identifier, representation, preferences })).resolves.toBeUndefined();
   });
 
   it('can handle JSON-LD to quad conversions.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'application/ld+json' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'application/ld+json' });
     const representation = { metadata } as Representation;
     const preferences: RepresentationPreferences = { type: [{ value: INTERNAL_QUADS, weight: 1 }]};
     await expect(converter.canHandle({ identifier, representation, preferences })).resolves.toBeUndefined();
   });
 
   it('converts turtle to quads.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     const representation = {
       data: streamifyArray([ '<http://test.com/s> <http://test.com/p> <http://test.com/o>.' ]),
       metadata,
@@ -60,7 +60,7 @@ describe('A RdfToQuadConverter.test.ts', (): void => {
   });
 
   it('converts JSON-LD to quads.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'application/ld+json' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'application/ld+json' });
     const representation = {
       data: streamifyArray([ '{"@id": "http://test.com/s", "http://test.com/p": { "@id": "http://test.com/o" }}' ]),
       metadata,
@@ -81,7 +81,7 @@ describe('A RdfToQuadConverter.test.ts', (): void => {
   });
 
   it('throws an UnsupportedHttpError on invalid triple data.', async(): Promise<void> => {
-    const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+    const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
     const representation = {
       data: streamifyArray([ '<http://test.com/s> <http://test.com/p> <http://test.co' ]),
       metadata,
diff --git a/test/unit/storage/conversion/TurtleToQuadConverter.test.ts b/test/unit/storage/conversion/TurtleToQuadConverter.test.ts
index c708248d5..86c532ea1 100644
--- a/test/unit/storage/conversion/TurtleToQuadConverter.test.ts
+++ b/test/unit/storage/conversion/TurtleToQuadConverter.test.ts
@@ -9,12 +9,12 @@ import { ResourceIdentifier } from '../../../../src/ldp/representation/ResourceI
 import { TurtleToQuadConverter } from '../../../../src/storage/conversion/TurtleToQuadConverter';
 import { INTERNAL_QUADS } from '../../../../src/util/ContentTypes';
 import { UnsupportedHttpError } from '../../../../src/util/errors/UnsupportedHttpError';
-import { MA_CONTENT_TYPE } from '../../../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../../../src/util/UriConstants';
 
 describe('A TurtleToQuadConverter', (): void => {
   const converter = new TurtleToQuadConverter();
   const identifier: ResourceIdentifier = { path: 'path' };
-  const metadata = new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' });
+  const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' });
 
   it('can handle turtle to quad conversions.', async(): Promise<void> => {
     const representation = { metadata } as Representation;
diff --git a/test/unit/util/UriUtil.test.ts b/test/unit/util/UriUtil.test.ts
new file mode 100644
index 000000000..cdd483e4f
--- /dev/null
+++ b/test/unit/util/UriUtil.test.ts
@@ -0,0 +1,56 @@
+import { literal, namedNode } from '@rdfjs/data-model';
+import { CONTENT_TYPE, XSD } from '../../../src/util/UriConstants';
+import { getNamedNode, getObjectTerm, getTypedLiteral, isTerm } from '../../../src/util/UriUtil';
+
+describe('An UriUtil', (): void => {
+  describe('isTerm function', (): void => {
+    it('checks if any input is a Term.', async(): Promise<void> => {
+      expect(isTerm(namedNode('name'))).toBeTruthy();
+      expect(isTerm(literal('value'))).toBeTruthy();
+      expect(isTerm('notATerm')).toBeFalsy();
+      expect(isTerm({})).toBeFalsy();
+      expect(isTerm()).toBeFalsy();
+    });
+  });
+
+  describe('getNamedNode function', (): void => {
+    it('returns the input if it was a named node.', async(): Promise<void> => {
+      const term = namedNode('name');
+      expect(getNamedNode(term)).toBe(term);
+    });
+
+    it('returns a named node when a string is used.', async(): Promise<void> => {
+      expect(getNamedNode('name')).toEqualRdfTerm(namedNode('name'));
+    });
+
+    it('caches generated named nodes.', async(): Promise<void> => {
+      const result = getNamedNode('name');
+      expect(result).toEqualRdfTerm(namedNode('name'));
+      expect(getNamedNode('name')).toBe(result);
+    });
+
+    it('supports URI shorthands.', async(): Promise<void> => {
+      expect(getNamedNode('contentType')).toEqualRdfTerm(namedNode(CONTENT_TYPE));
+    });
+  });
+
+  describe('getObjectTerm function', (): void => {
+    it('returns the input if it was a term.', async(): Promise<void> => {
+      const nn = namedNode('name');
+      const lit = literal('lit');
+      expect(getObjectTerm(nn)).toBe(nn);
+      expect(getObjectTerm(lit)).toBe(lit);
+    });
+
+    it('returns a literal when a string is used.', async(): Promise<void> => {
+      expect(getObjectTerm('lit')).toEqualRdfTerm(literal('lit'));
+    });
+  });
+
+  describe('getTypedLiteral function', (): void => {
+    it('converts the input to a valid literal with the given type.', async(): Promise<void> => {
+      const expected = literal('5', namedNode(XSD.integer));
+      expect(getTypedLiteral(5, XSD.integer)).toEqualRdfTerm(expected);
+    });
+  });
+});
diff --git a/test/util/TestHelpers.ts b/test/util/TestHelpers.ts
index fc1367609..c6b88217f 100644
--- a/test/util/TestHelpers.ts
+++ b/test/util/TestHelpers.ts
@@ -9,7 +9,7 @@ import { RepresentationMetadata, ResourceStore } from '../../index';
 import { PermissionSet } from '../../src/ldp/permissions/PermissionSet';
 import { HttpHandler } from '../../src/server/HttpHandler';
 import { HttpRequest } from '../../src/server/HttpRequest';
-import { MA_CONTENT_TYPE } from '../../src/util/MetadataTypes';
+import { CONTENT_TYPE } from '../../src/util/UriConstants';
 import { call } from './Util';
 
 export class AclTestHelper {
@@ -50,7 +50,7 @@ export class AclTestHelper {
     const representation = {
       binary: true,
       data: streamifyArray(acl),
-      metadata: new RepresentationMetadata({ [MA_CONTENT_TYPE]: 'text/turtle' }),
+      metadata: new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' }),
     };
 
     return this.store.setRepresentation(
@@ -184,7 +184,8 @@ export class FileTestHelper {
   public async getFolder(requestUrl: string): Promise<MockResponse<any>> {
     const getUrl = new URL(requestUrl);
 
-    return await this.simpleCall(getUrl, 'GET', { accept: 'text/turtle' });
+    // `n-quads` allow for easy testing if a triple is present
+    return await this.simpleCall(getUrl, 'GET', { accept: 'application/n-quads' });
   }
 
   public async deleteFolder(requestUrl: string): Promise<MockResponse<any>> {