diff --git a/src/ldp/representation/RepresentationMetadata.ts b/src/ldp/representation/RepresentationMetadata.ts index 35e53b179..824a5f9b5 100644 --- a/src/ldp/representation/RepresentationMetadata.ts +++ b/src/ldp/representation/RepresentationMetadata.ts @@ -155,7 +155,9 @@ export class RepresentationMetadata { } /** - * @param quads - Quad to add to the metadata. + * @param subject - Subject of quad to add. + * @param predicate - Predicate of quad to add. + * @param object - Object of quad to add. */ public addQuad( subject: NamedNode | BlankNode | string, @@ -175,7 +177,9 @@ export class RepresentationMetadata { } /** - * @param quads - Quad to remove from the metadata. + * @param subject - Subject of quad to remove. + * @param predicate - Predicate of quad to remove. + * @param object - Object of quad to remove. */ public removeQuad( subject: NamedNode | BlankNode | string, @@ -197,19 +201,34 @@ export class RepresentationMetadata { /** * Adds a value linked to the identifier. Strings get converted to literals. * @param predicate - Predicate linking identifier to value. - * @param object - Value to add. + * @param object - Value(s) to add. */ - public add(predicate: NamedNode | string, object: NamedNode | Literal | string): this { - return this.addQuad(this.id, predicate, object); + public add(predicate: NamedNode | string, object: MetadataValue): this { + return this.forQuads(predicate, object, (pred, obj): any => this.addQuad(this.id, pred, obj)); } /** * Removes the given value from the metadata. Strings get converted to literals. * @param predicate - Predicate linking identifier to value. - * @param object - Value to remove. + * @param object - Value(s) to remove. */ - public remove(predicate: NamedNode | string, object: NamedNode | Literal | string): this { - return this.removeQuad(this.id, predicate, object); + public remove(predicate: NamedNode | string, object: MetadataValue): this { + return this.forQuads(predicate, object, (pred, obj): any => this.removeQuad(this.id, pred, obj)); + } + + // TODO: test all 3 + /** + * Helper function to simplify add/remove + * Runs the given function on all predicate/object pairs, but only converts the predicate to a named node once. + */ + private forQuads(predicate: NamedNode | string, object: MetadataValue, + forFn: (pred: NamedNode, obj: NamedNode | Literal) => void): this { + const predicateNode = toCachedNamedNode(predicate); + const objects = Array.isArray(object) ? object : [ object ]; + for (const obj of objects) { + forFn(predicateNode, toObjectTerm(obj, true)); + } + return this; } /** @@ -256,9 +275,9 @@ export class RepresentationMetadata { * Sets the value for the given predicate, removing all other instances. * In case the object is undefined this is identical to `removeAll(predicate)`. * @param predicate - Predicate linking to the value. - * @param object - Value to set. + * @param object - Value(s) to set. */ - public set(predicate: NamedNode | string, object?: NamedNode | Literal | string): this { + public set(predicate: NamedNode | string, object?: MetadataValue): this { this.removeAll(predicate); if (object) { this.add(predicate, object); diff --git a/test/unit/ldp/representation/RepresentationMetadata.test.ts b/test/unit/ldp/representation/RepresentationMetadata.test.ts index 5f9c1e487..f45dad09f 100644 --- a/test/unit/ldp/representation/RepresentationMetadata.test.ts +++ b/test/unit/ldp/representation/RepresentationMetadata.test.ts @@ -154,6 +154,15 @@ describe('A RepresentationMetadata', (): void => { expect(metadata.quads()).toBeRdfIsomorphic([ newQuad ].concat(inputQuads)); }); + it('can add multiple values for a predicate.', async(): Promise => { + const newQuads = [ + quad(identifier, namedNode('new'), namedNode('triple')), + quad(identifier, namedNode('new'), namedNode('triple2')), + ]; + metadata.add(namedNode('new'), [ namedNode('triple'), namedNode('triple2') ]); + expect(metadata.quads()).toBeRdfIsomorphic(newQuads.concat(inputQuads)); + }); + it('can remove a single value for a predicate.', async(): Promise => { metadata.remove(inputQuads[0].predicate as NamedNode, inputQuads[0].object as Literal); expect(metadata.quads()).toBeRdfIsomorphic(inputQuads.slice(1)); @@ -164,6 +173,11 @@ describe('A RepresentationMetadata', (): void => { expect(metadata.quads()).toBeRdfIsomorphic(inputQuads.slice(1)); }); + it('can remove multiple values for a predicate.', async(): Promise => { + metadata.remove(namedNode('has'), [ inputQuads[0].object, inputQuads[1].object ] as NamedNode[]); + expect(metadata.quads()).toBeRdfIsomorphic(inputQuads.slice(2)); + }); + it('can remove all values for a predicate.', async(): Promise => { const pred = namedNode('has'); metadata.removeAll(pred); @@ -194,6 +208,11 @@ describe('A RepresentationMetadata', (): void => { expect(metadata.get(namedNode('has'))).toEqualRdfTerm(literal('singleValue')); }); + it('can set multiple values of a predicate.', async(): Promise => { + metadata.set(namedNode('has'), [ literal('value1'), literal('value2') ]); + expect(metadata.getAll(namedNode('has'))).toEqualRdfTermArray([ literal('value1'), literal('value2') ]); + }); + it('has a shorthand for content-type.', async(): Promise => { expect(metadata.contentType).toBeUndefined(); metadata.contentType = 'a/b';