mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
refactor: Simplify resource metadata generation
This commit is contained in:
parent
cae9d54fac
commit
96a07e4853
@ -1,4 +1,3 @@
|
||||
import { DataFactory } from 'n3';
|
||||
import { BasicRepresentation } from '../ldp/representation/BasicRepresentation';
|
||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
|
||||
@ -6,10 +5,9 @@ import { getLoggerFor } from '../logging/LogUtil';
|
||||
import type { ResourceStore } from '../storage/ResourceStore';
|
||||
import { TEXT_TURTLE } from '../util/ContentTypes';
|
||||
import { ensureTrailingSlash } from '../util/PathUtil';
|
||||
import { generateResourceQuads } from '../util/ResourceUtil';
|
||||
import { addResourceMetadata } from '../util/ResourceUtil';
|
||||
import { PIM, RDF } from '../util/Vocabularies';
|
||||
import { Initializer } from './Initializer';
|
||||
import namedNode = DataFactory.namedNode;
|
||||
|
||||
/**
|
||||
* Initializes ResourceStores by creating a root container if it didn't exist yet.
|
||||
@ -43,7 +41,7 @@ export class RootContainerInitializer extends Initializer {
|
||||
*/
|
||||
protected async createRootContainer(): Promise<void> {
|
||||
const metadata = new RepresentationMetadata(this.baseId, TEXT_TURTLE);
|
||||
metadata.addQuads(generateResourceQuads(namedNode(this.baseId.path), true));
|
||||
addResourceMetadata(metadata, true);
|
||||
|
||||
// Make sure the root container is a pim:Storage
|
||||
// This prevents deletion of the root container as storage root containers can not be deleted
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
toCanonicalUriPath,
|
||||
} from '../util/PathUtil';
|
||||
import { parseQuads } from '../util/QuadUtil';
|
||||
import { generateResourceQuads } from '../util/ResourceUtil';
|
||||
import { addResourceMetadata } from '../util/ResourceUtil';
|
||||
import { CONTENT_TYPE, DC, HTTP, LDP, POSIX, PIM, RDF, VANN, XSD } from '../util/Vocabularies';
|
||||
import type { DataAccessor } from './accessors/DataAccessor';
|
||||
import type { ResourceStore } from './ResourceStore';
|
||||
@ -293,7 +293,7 @@ export class DataAccessorBasedStore implements ResourceStore {
|
||||
// Need to do this before handling container data to have the correct identifier
|
||||
const { metadata } = representation;
|
||||
metadata.identifier = DataFactory.namedNode(identifier.path);
|
||||
metadata.addQuads(generateResourceQuads(metadata.identifier, isContainer));
|
||||
addResourceMetadata(metadata, isContainer);
|
||||
|
||||
// Validate container data
|
||||
if (isContainer) {
|
||||
|
@ -1,8 +1,7 @@
|
||||
import type { Stats } from 'fs';
|
||||
import { createWriteStream, createReadStream, promises as fsPromises } from 'fs';
|
||||
import type { Readable } from 'stream';
|
||||
import { DataFactory } from 'n3';
|
||||
import type { NamedNode, Quad } from 'rdf-js';
|
||||
import type { Quad } from 'rdf-js';
|
||||
import type { Representation } from '../../ldp/representation/Representation';
|
||||
import { RepresentationMetadata } from '../../ldp/representation/RepresentationMetadata';
|
||||
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
|
||||
@ -13,8 +12,8 @@ import { UnsupportedMediaTypeHttpError } from '../../util/errors/UnsupportedMedi
|
||||
import { guardStream } from '../../util/GuardedStream';
|
||||
import type { Guarded } from '../../util/GuardedStream';
|
||||
import { joinFilePath, isContainerIdentifier } from '../../util/PathUtil';
|
||||
import { parseQuads, pushQuad, serializeQuads } from '../../util/QuadUtil';
|
||||
import { generateResourceQuads } from '../../util/ResourceUtil';
|
||||
import { parseQuads, serializeQuads } from '../../util/QuadUtil';
|
||||
import { addResourceMetadata } from '../../util/ResourceUtil';
|
||||
import { toLiteral } from '../../util/TermUtil';
|
||||
import { CONTENT_TYPE, DC, LDP, POSIX, RDF, XSD } from '../../util/Vocabularies';
|
||||
import type { FileIdentifierMapper, ResourceLink } from '../mapping/FileIdentifierMapper';
|
||||
@ -251,8 +250,8 @@ export class FileDataAccessor implements DataAccessor {
|
||||
Promise<RepresentationMetadata> {
|
||||
const metadata = new RepresentationMetadata(link.identifier)
|
||||
.addQuads(await this.getRawMetadata(link.identifier));
|
||||
metadata.addQuads(generateResourceQuads(metadata.identifier as NamedNode, isContainer));
|
||||
metadata.addQuads(this.generatePosixQuads(metadata.identifier as NamedNode, stats));
|
||||
addResourceMetadata(metadata, isContainer);
|
||||
this.addPosixMetadata(metadata, stats);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@ -306,30 +305,25 @@ export class FileDataAccessor implements DataAccessor {
|
||||
.mapFilePathToUrl(joinFilePath(link.filePath, childName), entry.isDirectory());
|
||||
|
||||
// Generate metadata of this specific child
|
||||
const subject = DataFactory.namedNode(childLink.identifier.path);
|
||||
const childStats = await fsPromises.lstat(joinFilePath(link.filePath, childName));
|
||||
const quads: Quad[] = [];
|
||||
quads.push(...generateResourceQuads(subject, childStats.isDirectory()));
|
||||
quads.push(...this.generatePosixQuads(subject, childStats));
|
||||
yield new RepresentationMetadata(subject).addQuads(quads);
|
||||
const metadata = new RepresentationMetadata(childLink.identifier);
|
||||
addResourceMetadata(metadata, childStats.isDirectory());
|
||||
this.addPosixMetadata(metadata, childStats);
|
||||
yield metadata;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to add file system related metadata.
|
||||
* @param subject - Subject for the new quads.
|
||||
* @param metadata - metadata object to add to
|
||||
* @param stats - Stats of the file/directory corresponding to the resource.
|
||||
*/
|
||||
private generatePosixQuads(subject: NamedNode, stats: Stats): Quad[] {
|
||||
const quads: Quad[] = [];
|
||||
pushQuad(quads, subject, DC.terms.modified, toLiteral(stats.mtime.toISOString(), XSD.terms.dateTime));
|
||||
pushQuad(quads, subject, POSIX.terms.mtime, toLiteral(
|
||||
Math.floor(stats.mtime.getTime() / 1000), XSD.terms.integer,
|
||||
));
|
||||
private addPosixMetadata(metadata: RepresentationMetadata, stats: Stats): void {
|
||||
metadata.add(DC.terms.modified, toLiteral(stats.mtime.toISOString(), XSD.terms.dateTime));
|
||||
metadata.add(POSIX.terms.mtime, toLiteral(Math.floor(stats.mtime.getTime() / 1000), XSD.terms.integer));
|
||||
if (!stats.isDirectory()) {
|
||||
pushQuad(quads, subject, POSIX.terms.size, toLiteral(stats.size, XSD.terms.integer));
|
||||
metadata.add(POSIX.terms.size, toLiteral(stats.size, XSD.terms.integer));
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,32 +1,12 @@
|
||||
import type { Readable } from 'stream';
|
||||
import arrayifyStream from 'arrayify-stream';
|
||||
import type { ParserOptions } from 'n3';
|
||||
import { DataFactory, StreamParser, StreamWriter } from 'n3';
|
||||
import type { Literal, NamedNode, Quad } from 'rdf-js';
|
||||
import { StreamParser, StreamWriter } from 'n3';
|
||||
import type { Quad } from 'rdf-js';
|
||||
import streamifyArray from 'streamify-array';
|
||||
import type { Guarded } from './GuardedStream';
|
||||
import { pipeSafely } from './StreamUtil';
|
||||
import { toSubjectTerm, toPredicateTerm, toObjectTerm } from './TermUtil';
|
||||
|
||||
/**
|
||||
* Generates a quad with the given subject/predicate/object and pushes it to the given array.
|
||||
*/
|
||||
export function pushQuad(
|
||||
quads: Quad[] | Readable,
|
||||
subject: string | NamedNode,
|
||||
predicate: string | NamedNode,
|
||||
object: string | NamedNode | Literal,
|
||||
): void {
|
||||
quads.push(DataFactory.quad(toSubjectTerm(subject), toPredicateTerm(predicate), toObjectTerm(object)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for serializing an array of quads, with as result a Readable object.
|
||||
* @param quads - The array of quads.
|
||||
* @param contentType - The content-type to serialize to.
|
||||
*
|
||||
* @returns The Readable object.
|
||||
*/
|
||||
export function serializeQuads(quads: Quad[], contentType?: string): Guarded<Readable> {
|
||||
return pipeSafely(streamifyArray(quads), new StreamWriter({ format: contentType }));
|
||||
}
|
||||
|
@ -1,29 +1,24 @@
|
||||
import arrayifyStream from 'arrayify-stream';
|
||||
import type { NamedNode, Quad } from 'rdf-js';
|
||||
import { BasicRepresentation } from '../ldp/representation/BasicRepresentation';
|
||||
import type { Representation } from '../ldp/representation/Representation';
|
||||
import { RepresentationMetadata } from '../ldp/representation/RepresentationMetadata';
|
||||
import { pushQuad } from './QuadUtil';
|
||||
import { guardedStreamFrom } from './StreamUtil';
|
||||
|
||||
import { LDP, RDF } from './Vocabularies';
|
||||
|
||||
/**
|
||||
* Helper function to generate type quads for a Container or Resource.
|
||||
* @param subject - Subject for the new quads.
|
||||
* @param metadata - Metadata to add to.
|
||||
* @param isContainer - If the identifier corresponds to a container.
|
||||
*
|
||||
* @returns The generated quads.
|
||||
*/
|
||||
export function generateResourceQuads(subject: NamedNode, isContainer: boolean): Quad[] {
|
||||
const quads: Quad[] = [];
|
||||
export function addResourceMetadata(metadata: RepresentationMetadata, isContainer: boolean): void {
|
||||
if (isContainer) {
|
||||
pushQuad(quads, subject, RDF.terms.type, LDP.terms.Container);
|
||||
pushQuad(quads, subject, RDF.terms.type, LDP.terms.BasicContainer);
|
||||
metadata.add(RDF.terms.type, LDP.terms.Container);
|
||||
metadata.add(RDF.terms.type, LDP.terms.BasicContainer);
|
||||
}
|
||||
pushQuad(quads, subject, RDF.terms.type, LDP.terms.Resource);
|
||||
|
||||
return quads;
|
||||
metadata.add(RDF.terms.type, LDP.terms.Resource);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,28 +1,9 @@
|
||||
import 'jest-rdf';
|
||||
import { literal, namedNode, quad } from '@rdfjs/data-model';
|
||||
import type { Quad } from 'rdf-js';
|
||||
import { parseQuads, pushQuad, serializeQuads } from '../../../src/util/QuadUtil';
|
||||
import { parseQuads, serializeQuads } from '../../../src/util/QuadUtil';
|
||||
import { guardedStreamFrom, readableToString } from '../../../src/util/StreamUtil';
|
||||
|
||||
describe('QuadUtil', (): void => {
|
||||
describe('#pushQuad', (): void => {
|
||||
it('creates a quad and adds it to the given array.', async(): Promise<void> => {
|
||||
const quads: Quad[] = [];
|
||||
pushQuad(quads, namedNode('sub'), namedNode('pred'), literal('obj'));
|
||||
expect(quads).toEqualRdfQuadArray([
|
||||
quad(namedNode('sub'), namedNode('pred'), literal('obj')),
|
||||
]);
|
||||
});
|
||||
|
||||
it('creates a quad from strings and adds it to the given array.', async(): Promise<void> => {
|
||||
const quads: Quad[] = [];
|
||||
pushQuad(quads, 'sub', 'pred', 'obj');
|
||||
expect(quads).toEqualRdfQuadArray([
|
||||
quad(namedNode('sub'), namedNode('pred'), namedNode('obj')),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#serializeQuads', (): void => {
|
||||
it('converts quads to the requested format.', async(): Promise<void> => {
|
||||
const quads = [ quad(
|
||||
|
Loading…
x
Reference in New Issue
Block a user