Skip to content

Commit

Permalink
fix: do nto allow duplications in inherited type maps
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantha committed Sep 20, 2019
1 parent 7273ad0 commit d6951f5
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/configuration/mapping-expression-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export abstract class MappingExpressionBase<TSource, TDestination> implements

mapSubtype(pair: MappingPair<TSource, TDestination>, discriminatorCondition: (source: TSource) => boolean): this {
this.typeMapActions.push(tm => tm.addPolymorphicMap(discriminatorCondition, pair));
this.include(pair);
return this;
}
}
2 changes: 1 addition & 1 deletion src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export interface IConfigurationProvider {
*/
findTypeMapFor(pair: MappingPair<any, any>): TypeMap | undefined;

getIncludedTypeMaps(includedTypes: ReadonlyArray<MappingPair<any, any>>): ReadonlyArray<TypeMap>;
getIncludedTypeMaps(includedTypes: ReadonlySet<MappingPair<any, any>>): ReadonlyArray<TypeMap>;
}

export interface IMemberConfigurationExpression<TSource, TDestination, TMember> {
Expand Down
4 changes: 2 additions & 2 deletions src/mapper-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class MapperConfiguration implements IConfigurationProvider {
return this.typeMapRegistry.get(pair);
}

getIncludedTypeMaps(includedTypes: MappingPair<any, any>[]): ReadonlyArray<TypeMap> {
return includedTypes.map(pair => {
getIncludedTypeMaps(includedTypes: ReadonlySet<MappingPair<any, any>>): ReadonlyArray<TypeMap> {
return Array.from(includedTypes).map(pair => {
const typeMap = this.findTypeMapFor(pair);

if (typeMap) {
Expand Down
22 changes: 10 additions & 12 deletions src/type-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export class TypeMap {
get subtypeMaps(): ReadonlyArray<ISubtypeMap> { return this._subtypeMaps; }
get mapFunction(): MapperFunction<any, any> { return this._mapFunction; }
get valueTransformers(): ReadonlyArray<ValueTransformer> { return this._valueTransformers; }
get includedBaseTypes(): ReadonlyArray<MappingPair<any, any>> { return this._includedBaseTypes; }
get includedDerivedTypes(): ReadonlyArray<MappingPair<any, any>> { return this._includedDerivedTypes; }
get includedBaseTypes(): ReadonlySet<MappingPair<any, any>> { return this._includedBaseTypes; }
get includedDerivedTypes(): ReadonlySet<MappingPair<any, any>> { return this._includedDerivedTypes; }
get hasDerivedTypesToInclude(): boolean {
return this._includedDerivedTypes.length > 0 || this.destinationTypeOverride != null;
return this._includedDerivedTypes.size > 0 || this.destinationTypeOverride != null;
}
get sourceMemberConfigs(): ReadonlyMap<MemberInfo, SourceMemberConfig> { return this._sourceMemberConfigs; }

Expand All @@ -40,9 +40,9 @@ export class TypeMap {

private readonly _propertyMaps = new Map<MemberInfo, PropertyMap>();
private readonly _valueTransformers: ValueTransformer[] = [];
private readonly _includedBaseTypes: MappingPair<any, any>[] = [];
private readonly _includedDerivedTypes: MappingPair<any, any>[] = [];
private readonly _inheritedTypeMaps: TypeMap[] = [];
private readonly _includedBaseTypes = new Set<MappingPair<any, any>>();
private readonly _includedDerivedTypes = new Set<MappingPair<any, any>>();
private readonly _inheritedTypeMaps = new Set<TypeMap>();
private readonly _sourceMemberConfigs = new Map<MemberInfo, SourceMemberConfig>();
private readonly _subtypeMaps: ISubtypeMap[] = [];
private _mapFunction: MapperFunction<any, any>;
Expand All @@ -60,23 +60,23 @@ export class TypeMap {
throw new Error('You cannot include a type map into itself.');
}

this._includedBaseTypes.push(basePair);
this._includedBaseTypes.add(basePair);
}

includeDerivedPair(derivedPair: MappingPair<any, any>): void {
if (this.types === derivedPair) {
throw new Error('You cannot include a type map into itself.');
}

this._includedDerivedTypes.push(derivedPair);
this._includedDerivedTypes.add(derivedPair);
}

addPolymorphicMap(condition: (source: any) => boolean, pair: MappingPair<any, any>): void {
this._subtypeMaps.push({ condition, pair });
}

addInheritedMap(inheritedTypeMap: TypeMap): void {
this._inheritedTypeMaps.push(inheritedTypeMap);
this._inheritedTypeMaps.add(inheritedTypeMap);
}

seal(configurationProvider: IConfigurationProvider): void {
Expand All @@ -86,9 +86,7 @@ export class TypeMap {

this.sealed = true;

for (const inheritedTypeMap of this._inheritedTypeMaps) {
this.applyInheritedTypeMap(inheritedTypeMap);
}
this._inheritedTypeMaps.forEach(inheritedTypeMap => this.applyInheritedTypeMap(inheritedTypeMap));

this._mapFunction = new TypeMapPlanBuilder(configurationProvider, this).createMapper();
}
Expand Down
45 changes: 45 additions & 0 deletions test/bugs/transform-duplication-on-inheritance.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { MapperConfiguration, MappingPair } from '../../src';

describe('Transform duplication on inheritance', () => {
class Entity {
name: string;
}

class FooEntity extends Entity {
}

class BarEntity extends Entity {
}

class Dto {
name: string;
}

class FooDto extends Dto {}

class BarDto extends Dto {}

const EntityToDto = new MappingPair(Entity, Dto);
const FooEntityToDto = new MappingPair(FooEntity, FooDto);
const BarEntityToDto = new MappingPair(BarEntity, BarDto);

const mapper = new MapperConfiguration(cfg => {
cfg.createAutoMap(EntityToDto, {
name: opt => opt.addTransform(d => d + ', transformed!'),
})
.include(FooEntityToDto)
.include(BarEntityToDto);

cfg.createAutoMap(FooEntityToDto, {});

cfg.createAutoMap(BarEntityToDto, {});
}).createMapper();

it('should map FooDto from base mapping pair', () => {
const source = new FooEntity();
source.name = 'John';

const destination = mapper.map(FooEntityToDto, source) as FooDto;
expect(destination.name).toBe('John, transformed!');
});
});
4 changes: 2 additions & 2 deletions test/polymorphic-map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ describe('Polymorphic mapping', () => {

cfg.createAutoMap(FooEntityToDto, {
fooProperty: opt => opt.mapFrom(src => parseInt(src.property1))
}).includeBase(EntityToDto);
});

cfg.createAutoMap(BarEntityToDto, {
barProperty: opt => opt.mapFrom(src => parseInt(src.property1))
}).includeBase(EntityToDto);
});
}).createMapper();

it('should map FooDto from base mapping pair', () => {
Expand Down

0 comments on commit d6951f5

Please sign in to comment.