From 3eac74bcdce74d4d9930522fafea7be235fdf3cb Mon Sep 17 00:00:00 2001 From: Alex Dik Date: Sun, 19 Jun 2016 21:41:57 +0200 Subject: [PATCH] Implement better HalResource types configuration --- .../hal-resource-types-storage.service.ts | 16 ++- .../hal-resource-types.config.ts | 22 ++-- .../hal-resource-types.service.test.ts | 111 ++++++++++++------ .../hal-resource-types.service.ts | 34 ++++-- .../hal-resource.service.test.ts | 5 +- 5 files changed, 122 insertions(+), 66 deletions(-) diff --git a/frontend/app/components/api/api-v3/hal-resource-types-storage/hal-resource-types-storage.service.ts b/frontend/app/components/api/api-v3/hal-resource-types-storage/hal-resource-types-storage.service.ts index 8d3ee88040..be7881ba11 100644 --- a/frontend/app/components/api/api-v3/hal-resource-types-storage/hal-resource-types-storage.service.ts +++ b/frontend/app/components/api/api-v3/hal-resource-types-storage/hal-resource-types-storage.service.ts @@ -34,21 +34,29 @@ export class HalResourceTypesStorageService { private config:any = {}; public get defaultClass() { - return this.config.__default__; + return this.config.__default__.cls; } public set defaultClass(cls:typeof HalResource) { - this.addTypeConfig('__default__', cls); + this.setResourceType('__default__', cls); } - public addTypeConfig(typeName:string, cls:typeof HalResource, attrCls = {}) { + public setResourceType(typeName:string, cls:typeof HalResource) { cls._type = typeName; this.config[typeName] = { cls: cls, - attrCls: attrCls + attrCls: {} }; } + public setResourceTypeAttributes(typeName:string, attrTypes) { + Object.keys(attrTypes).forEach(attrName => { + attrTypes[attrName] = this.getResourceClassOfType(attrTypes[attrName]); + }); + + this.config[typeName].attrCls = attrTypes; + } + public getResourceClassOfType(type:string) { return this.getTypeConfig(type).cls; } diff --git a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.config.ts b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.config.ts index 09116977dc..b2834887e1 100644 --- a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.config.ts +++ b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.config.ts @@ -30,21 +30,17 @@ import {opApiModule} from '../../../../angular-modules'; import {HalResourceTypesService} from './hal-resource-types.service'; function halResourceTypesStorage(halResourceTypes:HalResourceTypesService) { - halResourceTypes - .addType('WorkPackage', { + halResourceTypes.setResourceTypeConfig({ + WorkPackage: { className: 'WorkPackageResource', - - attr: { - parent: 'WorkPackageResource', - children: 'WorkPackageResource' + attrTypes: { + parent: 'WorkPackage', + children: 'WorkPackage' } - }) - .addType('Error', { - className: 'ErrorResource' - }) - .addType('Collection', { - className: 'CollectionResource' - }); + }, + Error: 'ErrorResource', + Collection: 'CollectionResource' + }); } opApiModule.run(halResourceTypesStorage); diff --git a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.test.ts b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.test.ts index c369243f72..8e4f828c98 100644 --- a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.test.ts +++ b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.test.ts @@ -35,72 +35,105 @@ const expect = chai.expect; describe('halResourceTypes service', () => { var halResourceTypes:HalResourceTypesService; var halResourceTypesStorage:HalResourceTypesStorageService; + var config:any; + var compareCls:typeof HalResource; class HalResource { } class OtherResource { } + class FooResource { + } beforeEach(angular.mock.module(opApiModule.name, $provide => { $provide.value('HalResource', HalResource); $provide.value('OtherResource', OtherResource); + $provide.value('FooResource', FooResource); })); beforeEach(angular.mock.inject((_halResourceTypes_, _halResourceTypesStorage_) => { [halResourceTypes, halResourceTypesStorage] = arguments; })); + const expectResourceClassAdded = () => { + it('should add the respective class object to the storage', () => { + const cls = halResourceTypesStorage.getResourceClassOfType('Other'); + expect(cls).to.equal(compareCls); + }); + }; + + const expectAttributeClassAdded = () => { + it('should add the attribute type config to the storage', () => { + const cls = halResourceTypesStorage.getResourceClassOfAttribute('Other', 'attr'); + expect(cls).to.equal(compareCls); + }); + }; + it('should exist', () => { expect(halResourceTypes).to.exist; }); + it('should have added HalResource as the default type', () => { + expect(halResourceTypesStorage.defaultClass).to.equal(HalResource); + }); - describe('when adding configuration', () => { - var chained; - var commonTests = () => { - it('should return itself', () => { - expect(chained).to.equal(halResourceTypes); - }); - - it('should add the attribute type config', () => { - const resource = halResourceTypesStorage - .getResourceClassOfAttribute('Other', 'someResource'); - - expect(resource).to.equal(OtherResource); - }); - }; - - describe('when no class name is provided and attributes are configured', () => { - beforeEach(() => { - chained = halResourceTypes.addType('Other', { - attr: { - someResource: 'OtherResource' + describe('when configuring the type with class and attributes', () => { + beforeEach(() => { + compareCls = OtherResource; + config = { + Other: { + className: 'OtherResource', + attrTypes: { + attr: 'Other' } - }); - }); + } + }; + halResourceTypes.setResourceTypeConfig(config); + }); - it('should add the respective class object', () => { - expect(halResourceTypesStorage.getResourceClassOfType('Other')).to.equal(HalResource); - }); + expectResourceClassAdded(); + expectAttributeClassAdded(); + }); - commonTests(); + describe('when configuring the type with the class name as value', () => { + beforeEach(() => { + compareCls = OtherResource; + config = { + Other: 'OtherResource' + }; + halResourceTypes.setResourceTypeConfig(config); }); - describe('when a class name is provided and attribute types are configured', () => { - beforeEach(() => { - chained = halResourceTypes.addType('Other', { - className: 'OtherResource', - attr: { - someResource: 'OtherResource' - } - }); - }); + expectResourceClassAdded(); + }); - it('should have the default type', () => { - expect(halResourceTypesStorage.getResourceClassOfType('Other')).to.equal(OtherResource); - }); + describe('when configuring the type with only the attribute types', () => { + beforeEach(() => { + compareCls = halResourceTypesStorage.defaultClass; + config = { + Other: { + attr: 'Other' + } + }; + halResourceTypes.setResourceTypeConfig(config); + }); + + expectResourceClassAdded(); + expectAttributeClassAdded(); + }); - commonTests(); + describe('when an attribute has a type, that defined later in the config', () => { + beforeEach(() => { + compareCls = FooResource; + config = { + Other: { + attr: 'Foo' + }, + Foo: 'FooResource', + }; + halResourceTypes.setResourceTypeConfig(config); }); + + expectAttributeClassAdded(); }); }); diff --git a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.ts b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.ts index fb369abf1d..3518451b39 100644 --- a/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.ts +++ b/frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.ts @@ -36,18 +36,36 @@ export class HalResourceTypesService { halResourceTypesStorage.defaultClass = HalResource; } - public addType(typeName:string, config = {}) { - var {className = 'HalResource', attr = {}} = config; - const attrCls = {}; + public setResourceTypeConfig(config) { + const types = Object.keys(config).map(typeName => { + const value = config[typeName]; + const result = { + typeName: typeName, + className: value.className || this.halResourceTypesStorage.defaultClass.name, + attrTypes: value.attrTypes || {} + }; - Object.keys(attr).forEach(attrName => { - const className = attr[attrName]; - attrCls[attrName] = this.$injector.get(className); + if (angular.isString(value)) { + result.className = value; + } + + if (!value.className && angular.isObject(value)) { + result.attrTypes = value; + } + + return result; }); - this.halResourceTypesStorage.addTypeConfig(typeName, this.$injector.get(className), attrCls); + types.forEach(typeConfig => { + this.halResourceTypesStorage + .setResourceType(typeConfig.typeName, this.$injector.get(typeConfig.className)); + }); - return this; + types + .map(typeConfig => [typeConfig.typeName, typeConfig.attrTypes]) + .forEach(typeAttrConfig => { + this.halResourceTypesStorage.setResourceTypeAttributes(...typeAttrConfig); + }); } } diff --git a/frontend/app/components/api/api-v3/hal-resources/hal-resource.service.test.ts b/frontend/app/components/api/api-v3/hal-resources/hal-resource.service.test.ts index 5ab9083d80..b50a0cdee8 100644 --- a/frontend/app/components/api/api-v3/hal-resources/hal-resource.service.test.ts +++ b/frontend/app/components/api/api-v3/hal-resources/hal-resource.service.test.ts @@ -90,8 +90,9 @@ describe('HalResource service', () => { } }; - halResourceTypesStorage.addTypeConfig('Other', OtherResource, { - someResource: OtherResource + halResourceTypesStorage.setResourceType('Other', OtherResource); + halResourceTypesStorage.setResourceTypeAttributes('Other', { + someResource: 'Other' }); resource = HalResource.create(source);