diff --git a/src/storage/RepresentationConvertingStore.ts b/src/storage/RepresentationConvertingStore.ts index 125e7aa2b..39e577d3a 100644 --- a/src/storage/RepresentationConvertingStore.ts +++ b/src/storage/RepresentationConvertingStore.ts @@ -84,16 +84,19 @@ export class RepresentationConvertingStore { - if (!converter || !args.preferences.type || this.matchesPreferences(args.representation, args.preferences)) { - return args.representation; + if (!converter || !input.preferences.type || this.matchesPreferences(input.representation, input.preferences)) { + return input.representation; } + this.logger.debug(`Conversion needed for ${input.identifier + .path} from ${input.representation.metadata.contentType} to satisfy ${input.preferences.type + .map((pref): string => `${pref.value};q=${pref.weight}`).join(', ')}`); - const typeStr = args.preferences.type.map((pref): string => `${pref.value};q=${pref.weight}`).join(', '); - this.logger.info(`Convert ${args.identifier.path} from ${args.representation.metadata.contentType} to ${typeStr}`); - - return converter.handleSafe(args); + const converted = await converter.handleSafe(input); + this.logger.info(`Converted representation for ${input.identifier + .path} from ${input.representation.metadata.contentType} to ${converted.metadata.contentType}`); + return converted; } /** diff --git a/src/storage/conversion/ConversionUtil.ts b/src/storage/conversion/ConversionUtil.ts index 0174d8aba..fc6163b9e 100644 --- a/src/storage/conversion/ConversionUtil.ts +++ b/src/storage/conversion/ConversionUtil.ts @@ -54,7 +54,10 @@ RepresentationPreference[] => { return { value: type, weight }; }); - return weightedSupported.filter((preference): boolean => preference.weight !== 0); + // Return all non-zero preferences in descending order of weight + return weightedSupported + .filter((pref): boolean => pref.weight !== 0) + .sort((prefA, prefB): number => prefB.weight - prefA.weight); }; /** diff --git a/test/unit/storage/RepresentationConvertingStore.test.ts b/test/unit/storage/RepresentationConvertingStore.test.ts index 5e105045d..fd25be264 100644 --- a/test/unit/storage/RepresentationConvertingStore.test.ts +++ b/test/unit/storage/RepresentationConvertingStore.test.ts @@ -11,6 +11,8 @@ describe('A RepresentationConvertingStore', (): void => { let source: ResourceStore; let inConverter: RepresentationConverter; let outConverter: RepresentationConverter; + const convertedIn = { metadata: {}}; + const convertedOut = { metadata: {}}; const inType = 'text/turtle'; const metadata = new RepresentationMetadata({ [CONTENT_TYPE]: 'text/turtle' }); let representation: Representation; @@ -22,8 +24,8 @@ describe('A RepresentationConvertingStore', (): void => { setRepresentation: jest.fn(), } as any; - inConverter = { handleSafe: jest.fn(async(): Promise => 'inConvert') } as any; - outConverter = { handleSafe: jest.fn(async(): Promise => 'outConvert') } as any; + inConverter = { handleSafe: jest.fn(async(): Promise => convertedIn) } as any; + outConverter = { handleSafe: jest.fn(async(): Promise => convertedOut) } as any; store = new RepresentationConvertingStore(source, { inType, inConverter, outConverter }); representation = { binary: true, data: 'data', metadata } as any; @@ -64,7 +66,7 @@ describe('A RepresentationConvertingStore', (): void => { it('calls the converter if another output is preferred.', async(): Promise => { await expect(store.getRepresentation({ path: 'path' }, { type: [ { value: 'text/plain', weight: 1 }, { value: 'text/turtle', weight: 0 }, - ]})).resolves.toEqual('outConvert'); + ]})).resolves.toEqual(convertedOut); expect(source.getRepresentation).toHaveBeenCalledTimes(1); expect(outConverter.handleSafe).toHaveBeenCalledTimes(1); expect(outConverter.handleSafe).toHaveBeenLastCalledWith({ @@ -95,11 +97,11 @@ describe('A RepresentationConvertingStore', (): void => { await expect(store.addResource(id, representation, 'conditions' as any)).resolves.toBeUndefined(); expect(inConverter.handleSafe).toHaveBeenCalledTimes(1); - expect(source.addResource).toHaveBeenLastCalledWith(id, 'inConvert', 'conditions'); + expect(source.addResource).toHaveBeenLastCalledWith(id, convertedIn, 'conditions'); await expect(store.setRepresentation(id, representation, 'conditions' as any)).resolves.toBeUndefined(); expect(inConverter.handleSafe).toHaveBeenCalledTimes(2); - expect(source.setRepresentation).toHaveBeenLastCalledWith(id, 'inConvert', 'conditions'); + expect(source.setRepresentation).toHaveBeenLastCalledWith(id, convertedIn, 'conditions'); }); it('throws an error if no content-type is provided.', async(): Promise => { diff --git a/test/unit/storage/conversion/ConversionUtil.test.ts b/test/unit/storage/conversion/ConversionUtil.test.ts index e7b33ef77..7981443df 100644 --- a/test/unit/storage/conversion/ConversionUtil.test.ts +++ b/test/unit/storage/conversion/ConversionUtil.test.ts @@ -62,6 +62,13 @@ describe('ConversionUtil', (): void => { expect(matchingMediaTypes(preferences, [ 'b/x', 'c/x' ])).toEqual([{ value: 'b/x', weight: 0.5 }]); }); + it('sorts by descending weight.', async(): Promise => { + const preferences: RepresentationPreferences = { type: + [{ value: 'a/x', weight: 1 }, { value: 'b/x', weight: 0.5 }, { value: 'c/x', weight: 0.8 }]}; + expect(matchingMediaTypes(preferences, [ 'a/x', 'b/x', 'c/x' ])) + .toEqual([{ value: 'a/x', weight: 1 }, { value: 'c/x', weight: 0.8 }, { value: 'b/x', weight: 0.5 }]); + }); + it('errors if there are duplicate preferences.', async(): Promise => { const preferences: RepresentationPreferences = { type: [{ value: 'b/x', weight: 1 }, { value: 'b/x', weight: 0 }]};