From 53597469ad82f006cd9361e6962fce03d61e6474 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Sat, 29 Jun 2013 13:51:37 +0200 Subject: [PATCH] #32 Loading model element processors via service loader --- .../org/mapstruct/ap/MappingProcessor.java | 53 ++++++++++++++----- .../ap/processor/CdiComponentProcessor.java | 5 ++ .../ap/processor/MapperCreationProcessor.java | 6 +++ .../processor/MapperRenderingProcessor.java | 5 ++ .../processor/MethodRetrievalProcessor.java | 5 ++ .../ap/processor/ModelElementProcessor.java | 12 +++++ .../javax.annotation.processing.Processor | 19 ++++++- ...pstruct.ap.processor.ModelElementProcessor | 21 ++++++++ 8 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor diff --git a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java index 81886f1ea..cbdd113f3 100644 --- a/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/MappingProcessor.java @@ -18,7 +18,12 @@ */ package org.mapstruct.ap; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; @@ -39,11 +44,7 @@ import org.mapstruct.Mappings; import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.Options; import org.mapstruct.ap.model.ReportingPolicy; -import org.mapstruct.ap.processor.CdiComponentProcessor; import org.mapstruct.ap.processor.DefaultModelElementProcessorContext; -import org.mapstruct.ap.processor.MapperCreationProcessor; -import org.mapstruct.ap.processor.MapperRenderingProcessor; -import org.mapstruct.ap.processor.MethodRetrievalProcessor; import org.mapstruct.ap.processor.ModelElementProcessor; import org.mapstruct.ap.processor.ModelElementProcessor.ProcessorContext; @@ -142,14 +143,31 @@ public class MappingProcessor extends AbstractProcessor { return processor.process( context, mapperTypeElement, sourceElement ); } - //TODO Retrieve via service loader + /** + * Retrieves all model element processors, ordered by their priority value + * (with the method retrieval processor having the lowest priority value (1) + * and the code generation processor the highest priority value. + * + * @return A list with all model element processors. + */ private Iterable> getProcessors() { - return Arrays.>asList( - new MethodRetrievalProcessor(), - new MapperCreationProcessor(), - new CdiComponentProcessor(), - new MapperRenderingProcessor() - ); + // TODO Re-consider which class loader to use in case processors are + // loaded from other modules, too + @SuppressWarnings("rawtypes") + Iterator processorIterator = ServiceLoader.load( + ModelElementProcessor.class, + MappingProcessor.class.getClassLoader() + ) + .iterator(); + List> processors = new ArrayList>(); + + while ( processorIterator.hasNext() ) { + processors.add( processorIterator.next() ); + } + + Collections.sort( processors, new ProcessorComparator() ); + + return processors; } private TypeElement asTypeElement(Element element) { @@ -163,4 +181,15 @@ public class MappingProcessor extends AbstractProcessor { }, null ); } + + private static class ProcessorComparator implements Comparator> { + + @Override + public int compare(ModelElementProcessor o1, ModelElementProcessor o2) { + return + o1.getPriority() < o2.getPriority() ? -1 : + o1.getPriority() == o2.getPriority() ? 0 : + 1; + } + } } 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 39577fdda..4a02c6466 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/CdiComponentProcessor.java @@ -56,4 +56,9 @@ public class CdiComponentProcessor implements ModelElementProcessor methods) { ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element ); List mappingMethods = getMappingMethods( methods, unmappedTargetPolicy ); diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperRenderingProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperRenderingProcessor.java index 34056dbdb..bdf092c9e 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperRenderingProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperRenderingProcessor.java @@ -55,4 +55,9 @@ public class MapperRenderingProcessor implements ModelElementProcessor { * generates the resulting Java source file. */ R process(ProcessorContext context, TypeElement mapperTypeElement, P sourceElement); + + /** + * Returns the priority value of this processor which must be between 1 + * (highest priority) and 10000 (lowest priority). Processors are invoked in + * order from highest to lowest priority, starting with the mapping method + * retrieval processor (priority 1) and finishing with the code generation + * processor (priority 10000). Processors working on the built + * {@code Mapper} model must have a priority > 1000. + * + * @return The priority value of this processor. + */ + int getPriority(); } diff --git a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor index f619d80a9..621253fc4 100644 --- a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1,18 @@ -org.mapstruct.ap.MappingProcessor \ No newline at end of file +# 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. + +org.mapstruct.ap.MappingProcessor 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 new file mode 100644 index 000000000..a23eeb31e --- /dev/null +++ b/processor/src/main/resources/META-INF/services/org.mapstruct.ap.processor.ModelElementProcessor @@ -0,0 +1,21 @@ +# 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. + +org.mapstruct.ap.processor.CdiComponentProcessor +org.mapstruct.ap.processor.MapperCreationProcessor +org.mapstruct.ap.processor.MapperRenderingProcessor +org.mapstruct.ap.processor.MethodRetrievalProcessor