#32 Loading model element processors via service loader

This commit is contained in:
Gunnar Morling 2013-06-29 13:51:37 +02:00
parent 502780c441
commit 53597469ad
8 changed files with 113 additions and 13 deletions

View File

@ -18,7 +18,12 @@
*/ */
package org.mapstruct.ap; 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 java.util.Set;
import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.ProcessingEnvironment;
@ -39,11 +44,7 @@ import org.mapstruct.Mappings;
import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.Options; import org.mapstruct.ap.model.Options;
import org.mapstruct.ap.model.ReportingPolicy; import org.mapstruct.ap.model.ReportingPolicy;
import org.mapstruct.ap.processor.CdiComponentProcessor;
import org.mapstruct.ap.processor.DefaultModelElementProcessorContext; 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;
import org.mapstruct.ap.processor.ModelElementProcessor.ProcessorContext; import org.mapstruct.ap.processor.ModelElementProcessor.ProcessorContext;
@ -142,14 +143,31 @@ public class MappingProcessor extends AbstractProcessor {
return processor.process( context, mapperTypeElement, sourceElement ); 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<ModelElementProcessor<?, ?>> getProcessors() { private Iterable<ModelElementProcessor<?, ?>> getProcessors() {
return Arrays.<ModelElementProcessor<?, ?>>asList( // TODO Re-consider which class loader to use in case processors are
new MethodRetrievalProcessor(), // loaded from other modules, too
new MapperCreationProcessor(), @SuppressWarnings("rawtypes")
new CdiComponentProcessor(), Iterator<ModelElementProcessor> processorIterator = ServiceLoader.load(
new MapperRenderingProcessor() ModelElementProcessor.class,
); MappingProcessor.class.getClassLoader()
)
.iterator();
List<ModelElementProcessor<?, ?>> processors = new ArrayList<ModelElementProcessor<?, ?>>();
while ( processorIterator.hasNext() ) {
processors.add( processorIterator.next() );
}
Collections.sort( processors, new ProcessorComparator() );
return processors;
} }
private TypeElement asTypeElement(Element element) { private TypeElement asTypeElement(Element element) {
@ -163,4 +181,15 @@ public class MappingProcessor extends AbstractProcessor {
}, null }, null
); );
} }
private static class ProcessorComparator implements Comparator<ModelElementProcessor<?, ?>> {
@Override
public int compare(ModelElementProcessor<?, ?> o1, ModelElementProcessor<?, ?> o2) {
return
o1.getPriority() < o2.getPriority() ? -1 :
o1.getPriority() == o2.getPriority() ? 0 :
1;
}
}
} }

View File

@ -56,4 +56,9 @@ public class CdiComponentProcessor implements ModelElementProcessor<Mapper, Mapp
return mapper; return mapper;
} }
@Override
public int getPriority() {
return 1100;
}
} }

View File

@ -93,6 +93,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
return getMapper( mapperTypeElement, sourceElement ); return getMapper( mapperTypeElement, sourceElement );
} }
@Override
public int getPriority() {
return 1000;
}
private Mapper getMapper(TypeElement element, List<Method> methods) { private Mapper getMapper(TypeElement element, List<Method> methods) {
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element ); ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
List<MappingMethod> mappingMethods = getMappingMethods( methods, unmappedTargetPolicy ); List<MappingMethod> mappingMethods = getMappingMethods( methods, unmappedTargetPolicy );

View File

@ -55,4 +55,9 @@ public class MapperRenderingProcessor implements ModelElementProcessor<Mapper, V
new ModelWriter().writeModel( sourceFile, model ); new ModelWriter().writeModel( sourceFile, model );
} }
@Override
public int getPriority() {
return 10000;
}
} }

View File

@ -68,6 +68,11 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<TypeEleme
return retrieveMethods( mapperTypeElement, true ); return retrieveMethods( mapperTypeElement, true );
} }
@Override
public int getPriority() {
return 1;
}
/** /**
* Retrieves the mapping methods declared by the given mapper type. * Retrieves the mapping methods declared by the given mapper type.
* *

View File

@ -77,4 +77,16 @@ public interface ModelElementProcessor<P, R> {
* generates the resulting Java source file. * generates the resulting Java source file.
*/ */
R process(ProcessorContext context, TypeElement mapperTypeElement, P sourceElement); 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();
} }

View File

@ -1 +1,18 @@
org.mapstruct.ap.MappingProcessor # 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

View File

@ -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