diff --git a/core/src/main/java/org/mapstruct/Mapper.java b/core/src/main/java/org/mapstruct/Mapper.java
index 8d438d261..011feb38b 100644
--- a/core/src/main/java/org/mapstruct/Mapper.java
+++ b/core/src/main/java/org/mapstruct/Mapper.java
@@ -57,6 +57,9 @@ public @interface Mapper {
*
* {@code cdi}: the generated mapper is an application-scoped CDI bean and
* can be retrieved via {@code @Inject}
+ *
+ * {@code spring}: the generated mapper is a Spring bean and
+ * can be retrieved via {@code @Autowired}
*
*
* @return The component model for the generated mapper.
diff --git a/integrationtest/pom.xml b/integrationtest/pom.xml
index 3a320144f..6b41d9da0 100644
--- a/integrationtest/pom.xml
+++ b/integrationtest/pom.xml
@@ -70,6 +70,21 @@
weld-core
test
+
+
+
+ org.springframework
+ spring-test
+ test
+
+
+ org.springframework
+ spring-beans
+
+
+ org.springframework
+ spring-context
+
diff --git a/integrationtest/src/main/java/org/mapstruct/itest/spring/Source.java b/integrationtest/src/main/java/org/mapstruct/itest/spring/Source.java
new file mode 100644
index 000000000..e91f6b546
--- /dev/null
+++ b/integrationtest/src/main/java/org/mapstruct/itest/spring/Source.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.itest.spring;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+public class Source {
+
+ private int foo = 42;
+
+ private Date date = new GregorianCalendar( 1980, 0, 1 ).getTime();
+
+ public int getFoo() {
+ return foo;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+}
diff --git a/integrationtest/src/main/java/org/mapstruct/itest/spring/SourceTargetMapper.java b/integrationtest/src/main/java/org/mapstruct/itest/spring/SourceTargetMapper.java
new file mode 100644
index 000000000..3df122650
--- /dev/null
+++ b/integrationtest/src/main/java/org/mapstruct/itest/spring/SourceTargetMapper.java
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.itest.spring;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.itest.spring.other.DateMapper;
+
+@Mapper(componentModel = "spring", uses = DateMapper.class)
+public interface SourceTargetMapper {
+
+ Target sourceToTarget(Source source);
+}
diff --git a/integrationtest/src/main/java/org/mapstruct/itest/spring/Target.java b/integrationtest/src/main/java/org/mapstruct/itest/spring/Target.java
new file mode 100644
index 000000000..5a037aae6
--- /dev/null
+++ b/integrationtest/src/main/java/org/mapstruct/itest/spring/Target.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.itest.spring;
+
+public class Target {
+
+ private Long foo;
+
+ private String date;
+
+ public void setFoo(Long foo) {
+ this.foo = foo;
+ }
+
+ public Long getFoo() {
+ return foo;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public void setDate(String date) {
+ this.date = date;
+ }
+}
diff --git a/integrationtest/src/main/java/org/mapstruct/itest/spring/other/DateMapper.java b/integrationtest/src/main/java/org/mapstruct/itest/spring/other/DateMapper.java
new file mode 100644
index 000000000..f41ba630e
--- /dev/null
+++ b/integrationtest/src/main/java/org/mapstruct/itest/spring/other/DateMapper.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.itest.spring.other;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class DateMapper {
+
+ public String asString(Date date) {
+ return date != null ? new SimpleDateFormat( "yyyy" ).format( date ) : null;
+ }
+
+ public Date asDate(String date) {
+ try {
+ return date != null ? new SimpleDateFormat( "yyyy" ).parse( date ) : null;
+ }
+ catch ( ParseException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+}
diff --git a/integrationtest/src/test/java/org/mapstruct/itest/spring/SpringBasedMapperTest.java b/integrationtest/src/test/java/org/mapstruct/itest/spring/SpringBasedMapperTest.java
new file mode 100644
index 000000000..649bcd421
--- /dev/null
+++ b/integrationtest/src/test/java/org/mapstruct/itest/spring/SpringBasedMapperTest.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.itest.spring;
+
+import org.mapstruct.itest.spring.SpringBasedMapperTest.SpringTestConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.annotations.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * Test for generation of Spring-based Mapper implementations
+ *
+ * @author Andreas Gudian
+ */
+@ContextConfiguration(classes = SpringTestConfig.class )
+public class SpringBasedMapperTest extends AbstractTestNGSpringContextTests {
+ @Configuration
+ @ComponentScan(basePackageClasses = SpringBasedMapperTest.class)
+ public static class SpringTestConfig {
+ }
+
+ @Autowired
+ private SourceTargetMapper mapper;
+
+
+ @Test
+ public void shouldCreateSpringBasedMapper() {
+ Source source = new Source();
+
+ Target target = mapper.sourceToTarget( source );
+
+ assertThat( target ).isNotNull();
+ assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) );
+ assertThat( target.getDate() ).isEqualTo( "1980" );
+ }
+}
diff --git a/parent/pom.xml b/parent/pom.xml
index e084fa4eb..444f851e5 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -43,6 +43,7 @@
UTF-8
1.0.0
1.2
+ 3.2.3.RELEASE
@@ -142,6 +143,23 @@
1.1.5.Final
+
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-beans
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
${project.groupId}
diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
index 212b5b4ec..810f3e55e 100644
--- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java
@@ -76,7 +76,11 @@ import org.mapstruct.ap.processor.ModelElementProcessor.ProcessorContext;
@GeneratePrism(value = Mappings.class, publicAccess = true),
@GeneratePrism(value = IterableMapping.class, publicAccess = true)
})
-@SupportedOptions({ MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP, MappingProcessor.UNMAPPED_TARGET_POLICY })
+@SupportedOptions({
+ MappingProcessor.SUPPRESS_GENERATOR_TIMESTAMP,
+ MappingProcessor.UNMAPPED_TARGET_POLICY,
+ MappingProcessor.DEFAULT_COMPONENT_MODEL
+})
public class MappingProcessor extends AbstractProcessor {
/**
@@ -86,6 +90,7 @@ public class MappingProcessor extends AbstractProcessor {
protected static final String SUPPRESS_GENERATOR_TIMESTAMP = "suppressGeneratorTimestamp";
protected static final String UNMAPPED_TARGET_POLICY = "unmappedTargetPolicy";
+ protected static final String DEFAULT_COMPONENT_MODEL = "defaultComponentModel";
private Options options;
@@ -101,7 +106,8 @@ public class MappingProcessor extends AbstractProcessor {
return new Options(
Boolean.valueOf( processingEnv.getOptions().get( SUPPRESS_GENERATOR_TIMESTAMP ) ),
- unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy ) : null
+ unmappedTargetPolicy != null ? ReportingPolicy.valueOf( unmappedTargetPolicy ) : null,
+ processingEnv.getOptions().get( DEFAULT_COMPONENT_MODEL )
);
}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/Options.java b/processor/src/main/java/org/mapstruct/ap/model/Options.java
index 12b3ad205..6af2b2084 100644
--- a/processor/src/main/java/org/mapstruct/ap/model/Options.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/Options.java
@@ -27,10 +27,13 @@ package org.mapstruct.ap.model;
public class Options {
private final boolean suppressGeneratorTimestamp;
private final ReportingPolicy unmappedTargetPolicy;
+ private final String defaultComponentModel;
- public Options(boolean suppressGeneratorTimestamp, ReportingPolicy unmappedTargetPolicy) {
+ public Options(boolean suppressGeneratorTimestamp, ReportingPolicy unmappedTargetPolicy,
+ String defaultComponentModel) {
this.suppressGeneratorTimestamp = suppressGeneratorTimestamp;
this.unmappedTargetPolicy = unmappedTargetPolicy;
+ this.defaultComponentModel = defaultComponentModel;
}
public boolean isSuppressGeneratorTimestamp() {
@@ -40,4 +43,8 @@ public class Options {
public ReportingPolicy getUnmappedTargetPolicy() {
return unmappedTargetPolicy;
}
+
+ public String getDefaultComponentModel() {
+ return defaultComponentModel;
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/SpringMapperReference.java b/processor/src/main/java/org/mapstruct/ap/model/SpringMapperReference.java
new file mode 100644
index 000000000..4a298f789
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/model/SpringMapperReference.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.model;
+
+import java.util.Set;
+
+import org.mapstruct.ap.util.Collections;
+
+/**
+ * Mapper reference which is retrieved via Spring-based dependency injection.
+ * method. Used if "spring" is specified as component model via
+ * {@code Mapper#uses()}.
+ *
+ * @author Gunnar Morling
+ * @author Andreas Gudian
+ */
+public class SpringMapperReference extends AbstractModelElement implements MapperReference {
+
+ private Type type;
+
+ public SpringMapperReference(Type type) {
+ this.type = type;
+ }
+
+ @Override
+ public Type getMapperType() {
+ return type;
+ }
+
+ @Override
+ public Set getImportTypes() {
+ return Collections.asSet( type, new Type( "org.springframework.beans.factory.annotation", "Autowired" ) );
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java
index 4a02c6466..23f32a4e6 100644
--- a/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java
+++ b/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java
@@ -27,6 +27,7 @@ import org.mapstruct.ap.model.CdiMapperReference;
import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.MapperReference;
import org.mapstruct.ap.model.Type;
+import org.mapstruct.ap.util.OptionsHelper;
/**
* A {@link ModelElementProcessor} which converts the given {@link Mapper}
@@ -40,8 +41,12 @@ public class CdiComponentProcessor implements ModelElementProcessor {
+
+ @Override
+ public Mapper process(ProcessorContext context, TypeElement mapperTypeElement, Mapper mapper) {
+ String componentModel = MapperPrism.getInstanceOn( mapperTypeElement ).componentModel();
+ String effectiveComponentModel = OptionsHelper.getEffectiveComponentModel(
+ context.getOptions(),
+ componentModel
+ );
+
+ if ( !"spring".equalsIgnoreCase( effectiveComponentModel ) ) {
+ return mapper;
+ }
+
+ mapper.addAnnotation( new Annotation( new Type( "org.springframework.stereotype", "Component" ) ) );
+
+ ListIterator iterator = mapper.getReferencedMappers().listIterator();
+ while ( iterator.hasNext() ) {
+ MapperReference reference = iterator.next();
+ iterator.remove();
+ iterator.add( new SpringMapperReference( reference.getMapperType() ) );
+ }
+
+ return mapper;
+ }
+
+ @Override
+ public int getPriority() {
+ return 1105;
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/util/OptionsHelper.java b/processor/src/main/java/org/mapstruct/ap/util/OptionsHelper.java
new file mode 100644
index 000000000..fa441e3ee
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/util/OptionsHelper.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * 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.util;
+
+import org.mapstruct.ap.model.Options;
+
+/**
+ * Helper class for dealing with {@link Options}.
+ *
+ * @author Andreas Gudian
+ */
+public class OptionsHelper {
+
+ private OptionsHelper() {
+ }
+
+ /**
+ * @param options the options
+ * @param locallyDeclaredComponentModel the locally declared component model
+ *
+ * @return the effective component model to be used
+ */
+ public static String getEffectiveComponentModel(Options options, String locallyDeclaredComponentModel) {
+ if ( "default".equals( locallyDeclaredComponentModel ) ) {
+ return options.getDefaultComponentModel();
+ }
+
+ return locallyDeclaredComponentModel;
+ }
+}
diff --git a/processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor b/processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor
index a23eeb31e..0cf4e38f6 100644
--- a/processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor
+++ b/processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor
@@ -19,3 +19,4 @@ org.mapstruct.ap.processor.CdiComponentProcessor
org.mapstruct.ap.processor.MapperCreationProcessor
org.mapstruct.ap.processor.MapperRenderingProcessor
org.mapstruct.ap.processor.MethodRetrievalProcessor
+org.mapstruct.ap.processor.SpringComponentProcessor
diff --git a/processor/src/main/resources/org.mapstruct.ap.model.SpringMapperReference.ftl b/processor/src/main/resources/org.mapstruct.ap.model.SpringMapperReference.ftl
new file mode 100644
index 000000000..11ad209b2
--- /dev/null
+++ b/processor/src/main/resources/org.mapstruct.ap.model.SpringMapperReference.ftl
@@ -0,0 +1,22 @@
+<#--
+
+ Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
+ and/or other contributors as indicated by the @authors tag. See the
+ copyright.txt file in the distribution for a full listing of all
+ contributors.
+
+ 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.
+
+-->
+ @Autowired
+ private ${mapperType.name} ${mapperType.name?uncap_first};
\ No newline at end of file