#6 Using default implementations for mapping collection types

This commit is contained in:
Gunnar Morling 2013-04-30 23:57:18 +02:00
parent 5ef53878f4
commit b11fa30200
11 changed files with 361 additions and 21 deletions

View File

@ -15,9 +15,14 @@
*/
package org.mapstruct.ap.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Represents the type of a bean property, parameter etc.
@ -30,10 +35,19 @@ public class Type {
Arrays.asList( "boolean", "char", "byte", "short", "int", "long", "float", "double" )
);
private final static ConcurrentMap<String, Type> defaultCollectionImplementationTypes = new ConcurrentHashMap<String, Type>();
static {
defaultCollectionImplementationTypes.put( List.class.getName(), forClass( ArrayList.class ) );
defaultCollectionImplementationTypes.put( Set.class.getName(), forClass( HashSet.class ) );
defaultCollectionImplementationTypes.put( Collection.class.getName(), forClass( ArrayList.class ) );
}
private final String packageName;
private final String name;
private final Type elementType;
private final boolean isEnumType;
private final Type implementingType;
public static Type forClass(Class<?> clazz) {
Package pakkage = clazz.getPackage();
@ -50,15 +64,12 @@ public class Type {
this( null, name, null, false );
}
public Type(String packageName, String name) {
this( packageName, name, null, false );
}
public Type(String packageName, String name, Type elementType, boolean isEnumType) {
this.packageName = packageName;
this.name = name;
this.elementType = elementType;
this.isEnumType = isEnumType;
implementingType = defaultCollectionImplementationTypes.get( packageName + "." + name );
}
public String getPackageName() {
@ -81,6 +92,10 @@ public class Type {
return isEnumType;
}
public Type getImplementingType() {
return implementingType;
}
@Override
public String toString() {
if ( packageName == null ) {

View File

@ -18,7 +18,10 @@
package ${packageName};
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Generated;
import java.util.Date;
@ -41,7 +44,7 @@ public class ${implementationName} implements ${interfaceName} {
return null;
}
${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>();
${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new <#if beanMapping.targetType.implementingType??>${beanMapping.targetType.implementingType.name}<#else>${beanMapping.targetType.name}</#if><${beanMapping.targetType.elementType.name}>();
for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) {
${beanMapping.targetType.name?uncap_first}.add( ${beanMapping.mappingMethod.elementMappingMethod.name}( ${beanMapping.sourceType.elementType.name?uncap_first} ) );
@ -90,7 +93,7 @@ public class ${implementationName} implements ${interfaceName} {
return null;
}
${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>();
${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new <#if beanMapping.sourceType.implementingType??>${beanMapping.sourceType.implementingType.name}<#else>${beanMapping.sourceType.name}</#if><${beanMapping.sourceType.elementType.name}>();
for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) {
${beanMapping.sourceType.name?uncap_first}.add( ${beanMapping.reverseMappingMethod.elementMappingMethod.name}( ${beanMapping.targetType.elementType.name?uncap_first} ) );

View File

@ -0,0 +1,73 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.MapperTestBase;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
public class DefaultCollectionImplementationTest extends MapperTestBase {
@Override
protected List<Class<?>> getTestClasses() {
return Arrays.<Class<?>>asList(
Source.class,
SourceFoo.class,
Target.class,
TargetFoo.class,
SourceTargetMapper.class
);
}
@Test
@IssueKey("6")
public void shouldUseDefaultImplementationForList() {
Source source = new Source();
source.setFooList( Arrays.asList( new SourceFoo( "Bob" ), new SourceFoo( "Alice" ) ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFooList() ).containsExactly( new TargetFoo( "Bob" ), new TargetFoo( "Alice" ) );
}
@Test
@IssueKey("6")
public void shouldUseDefaultImplementationForSet() {
Source source = new Source();
source.setFooSet( new HashSet<SourceFoo>( Arrays.asList( new SourceFoo( "Bob" ), new SourceFoo( "Alice" ) ) ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFooSet() ).containsOnly( new TargetFoo( "Bob" ), new TargetFoo( "Alice" ) );
}
@Test
@IssueKey("6")
public void shouldUseDefaultImplementationForCollection() {
Source source = new Source();
source.setFooCollection( Arrays.asList( new SourceFoo( "Bob" ), new SourceFoo( "Alice" ) ) );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFooCollection() ).containsOnly( new TargetFoo( "Bob" ), new TargetFoo( "Alice" ) );
}
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class Source {
private List<SourceFoo> fooList;
private Set<SourceFoo> fooSet;
private Collection<SourceFoo> fooCollection;
public List<SourceFoo> getFooList() {
return fooList;
}
public void setFooList(List<SourceFoo> fooList) {
this.fooList = fooList;
}
public Set<SourceFoo> getFooSet() {
return fooSet;
}
public void setFooSet(Set<SourceFoo> fooSet) {
this.fooSet = fooSet;
}
public Collection<SourceFoo> getFooCollection() {
return fooCollection;
}
public void setFooCollection(Collection<SourceFoo> fooCollection) {
this.fooCollection = fooCollection;
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
public class SourceFoo {
private String name;
public SourceFoo() {
}
public SourceFoo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,40 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.mapstruct.Mapper;
import org.mapstruct.Mappers;
@Mapper
public interface SourceTargetMapper {
public static SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
Target sourceToTarget(Source source);
TargetFoo sourceFooToTargetFoo(SourceFoo sourceFoo);
List<TargetFoo> sourceFoosToTargetFoos(List<SourceFoo> foos);
Set<TargetFoo> sourceFoosToTargetFoos(Set<SourceFoo> foos);
Collection<TargetFoo> sourceFoosToTargetFoos(Collection<SourceFoo> foos);
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class Target {
private List<TargetFoo> fooList;
private Set<TargetFoo> fooSet;
private Collection<TargetFoo> fooCollection;
public List<TargetFoo> getFooList() {
return fooList;
}
public void setFooList(List<TargetFoo> fooList) {
this.fooList = fooList;
}
public Set<TargetFoo> getFooSet() {
return fooSet;
}
public void setFooSet(Set<TargetFoo> fooSet) {
this.fooSet = fooSet;
}
public Collection<TargetFoo> getFooCollection() {
return fooCollection;
}
public void setFooCollection(Collection<TargetFoo> fooCollection) {
this.fooCollection = fooCollection;
}
}

View File

@ -0,0 +1,67 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.collection.defaultimplementation;
public class TargetFoo {
private String name;
public TargetFoo() {
}
public TargetFoo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
return result;
}
@Override
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
TargetFoo other = (TargetFoo) obj;
if ( name == null ) {
if ( other.name != null ) {
return false;
}
}
else if ( !name.equals( other.name ) ) {
return false;
}
return true;
}
}

View File

@ -15,8 +15,8 @@
*/
package org.mapstruct.ap.test.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Car {
@ -24,14 +24,14 @@ public class Car {
private int numberOfSeats;
private Date manufacturingDate;
private Person driver;
private ArrayList<Person> passengers;
private List<Person> passengers;
private int price;
private Category category;
public Car() {
}
public Car(String make, int numberOfSeats, Date manufacturingDate, Person driver, ArrayList<Person> passengers) {
public Car(String make, int numberOfSeats, Date manufacturingDate, Person driver, List<Person> passengers) {
this.make = make;
this.numberOfSeats = numberOfSeats;
this.manufacturingDate = manufacturingDate;
@ -71,11 +71,11 @@ public class Car {
this.driver = driver;
}
public ArrayList<Person> getPassengers() {
public List<Person> getPassengers() {
return passengers;
}
public void setPassengers(ArrayList<Person> passengers) {
public void setPassengers(List<Person> passengers) {
this.passengers = passengers;
}

View File

@ -15,7 +15,7 @@
*/
package org.mapstruct.ap.test.model;
import java.util.ArrayList;
import java.util.List;
public class CarDto {
@ -23,14 +23,14 @@ public class CarDto {
private int seatCount;
private String manufacturingYear;
private PersonDto driver;
private ArrayList<PersonDto> passengers;
private List<PersonDto> passengers;
private Long price;
private String category;
public CarDto() {
}
public CarDto(String make, int seatCount, String manufacturingYear, PersonDto driver, ArrayList<PersonDto> passengers) {
public CarDto(String make, int seatCount, String manufacturingYear, PersonDto driver, List<PersonDto> passengers) {
this.make = make;
this.seatCount = seatCount;
this.manufacturingYear = manufacturingYear;
@ -70,11 +70,11 @@ public class CarDto {
this.driver = driver;
}
public ArrayList<PersonDto> getPassengers() {
public List<PersonDto> getPassengers() {
return passengers;
}
public void setPassengers(ArrayList<PersonDto> passengers) {
public void setPassengers(List<PersonDto> passengers) {
this.passengers = passengers;
}

View File

@ -15,7 +15,7 @@
*/
package org.mapstruct.ap.test.model;
import java.util.ArrayList;
import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mappers;
@ -35,15 +35,15 @@ public interface CarMapper {
Car carDtoToCar(CarDto carDto);
ArrayList<CarDto> carsToCarDtos(ArrayList<Car> cars);
List<CarDto> carsToCarDtos(List<Car> cars);
ArrayList<Car> carDtosToCars(ArrayList<CarDto> carDtos);
List<Car> carDtosToCars(List<CarDto> carDtos);
PersonDto personToPersonDto(Person person);
Person personDtoToPerson(PersonDto personDto);
ArrayList<PersonDto> personsToPersonDtos(ArrayList<Person> persons);
List<PersonDto> personsToPersonDtos(List<Person> persons);
ArrayList<Person> personDtosToPersons(ArrayList<PersonDto> personDtos);
List<Person> personDtosToPersons(List<PersonDto> personDtos);
}