mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#365 Making Services factory agnostic of specific services
This commit is contained in:
parent
3ba4ded58c
commit
77298c750e
@ -20,12 +20,10 @@ package org.mapstruct.ap.model.assignment;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
import org.mapstruct.ap.model.common.Type;
|
||||
import org.mapstruct.ap.services.Services;
|
||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||
import org.mapstruct.ap.util.Executables;
|
||||
|
||||
/**
|
||||
* This wrapper handles the situation were an assignment is done via the setter.
|
||||
@ -49,11 +47,7 @@ public class SetterWrapperForCollectionsAndMaps extends AssignmentWrapper {
|
||||
Assignment newCollectionOrMapAssignment) {
|
||||
super( decoratedAssignment );
|
||||
|
||||
AccessorNamingStrategy accessorNamingStrategy = Services.getAccessorNamingStrategy();
|
||||
|
||||
this.targetGetterName = accessorNamingStrategy.getCollectionGetterName(
|
||||
accessorNamingStrategy.getPropertyName( targetSetter )
|
||||
);
|
||||
this.targetGetterName = Executables.getCollectionGetterName( targetSetter );
|
||||
this.newCollectionOrMapAssignment = newCollectionOrMapAssignment;
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.services;
|
||||
package org.mapstruct.ap.naming;
|
||||
|
||||
import java.beans.Introspector;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
@ -36,7 +35,7 @@ import org.mapstruct.ap.spi.MethodType;
|
||||
*
|
||||
* @author Christian Schuster
|
||||
*/
|
||||
class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
|
||||
@Override
|
||||
public MethodType getMethodType(ExecutableElement method) {
|
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright 2012-2015 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.
|
||||
*/
|
||||
/**
|
||||
* <p>
|
||||
* SPI (service provider interface) contracts to be implemented for advanced use cases.
|
||||
* </p>
|
||||
*/
|
||||
package org.mapstruct.ap.naming;
|
@ -19,8 +19,8 @@
|
||||
package org.mapstruct.ap.services;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* A simple locator for SPI implementations.
|
||||
@ -29,32 +29,35 @@ import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||
*/
|
||||
public class Services {
|
||||
|
||||
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = findAccessorNamingStrategy();
|
||||
private static final ConcurrentMap<Class<?>, Object> SERVICES = new ConcurrentHashMap<Class<?>, Object>();
|
||||
|
||||
private Services() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain an implementation of {@link AccessorNamingStrategy}. If no specialized implementation is found using
|
||||
* {@link ServiceLoader}, a JavaBeans-compliant default implementation is returned. The result is cached across
|
||||
* invocations.
|
||||
*
|
||||
* @return The implementation of {@link AccessorNamingStrategy}.
|
||||
* @throws IllegalStateException If more than one implementation is found by
|
||||
* {@link ServiceLoader#load(Class, ClassLoader)}.
|
||||
*/
|
||||
public static AccessorNamingStrategy getAccessorNamingStrategy() {
|
||||
return ACCESSOR_NAMING_STRATEGY;
|
||||
public static <T> T get(Class<T> serviceType, T defaultValue) {
|
||||
@SuppressWarnings("unchecked")
|
||||
T service = (T) SERVICES.get( serviceType );
|
||||
|
||||
if ( service == null ) {
|
||||
service = loadAndCache( serviceType, defaultValue );
|
||||
}
|
||||
|
||||
private static AccessorNamingStrategy findAccessorNamingStrategy() {
|
||||
AccessorNamingStrategy defaultImpl = new DefaultAccessorNamingStrategy();
|
||||
AccessorNamingStrategy impl = find( AccessorNamingStrategy.class );
|
||||
if ( impl == null ) {
|
||||
impl = defaultImpl;
|
||||
return service;
|
||||
}
|
||||
|
||||
return impl;
|
||||
private static <T> T loadAndCache(Class<T> serviceType, T defaultValue) {
|
||||
T service = find( serviceType );
|
||||
if ( service == null ) {
|
||||
service = defaultValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T cached = (T) SERVICES.putIfAbsent( serviceType, service );
|
||||
if ( cached != null ) {
|
||||
service = (T) cached;
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
private static <T> T find(Class<T> spi) {
|
||||
@ -68,7 +71,8 @@ public class Services {
|
||||
throw new IllegalStateException(
|
||||
"Multiple implementations have been found for the service provider interface "
|
||||
+ spi.getCanonicalName() + ": " + matchingImplementation.getClass().getCanonicalName() + ", "
|
||||
+ implementation.getClass().getCanonicalName() + "." );
|
||||
+ implementation.getClass().getCanonicalName() + "."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ package org.mapstruct.ap.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
@ -29,6 +28,7 @@ import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.naming.DefaultAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.services.Services;
|
||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.MethodType;
|
||||
@ -43,7 +43,10 @@ import static org.mapstruct.ap.util.SpecificCompilerWorkarounds.replaceTypeEleme
|
||||
*/
|
||||
public class Executables {
|
||||
|
||||
private static AccessorNamingStrategy accessorNamingStrategy = Services.getAccessorNamingStrategy();
|
||||
private static AccessorNamingStrategy accessorNamingStrategy = Services.get(
|
||||
AccessorNamingStrategy.class,
|
||||
new DefaultAccessorNamingStrategy()
|
||||
);
|
||||
|
||||
private Executables() {
|
||||
}
|
||||
@ -51,7 +54,7 @@ public class Executables {
|
||||
public static boolean isGetterMethod(ExecutableElement method) {
|
||||
return isPublic( method ) &&
|
||||
method.getParameters().isEmpty() &&
|
||||
Services.getAccessorNamingStrategy().getMethodType( method ) == MethodType.GETTER;
|
||||
accessorNamingStrategy.getMethodType( method ) == MethodType.GETTER;
|
||||
}
|
||||
|
||||
public static boolean isSetterMethod(ExecutableElement method) {
|
||||
@ -83,6 +86,11 @@ public class Executables {
|
||||
return accessorNamingStrategy.getElementName( adderMethod );
|
||||
}
|
||||
|
||||
public static String getCollectionGetterName(ExecutableElement targetSetter) {
|
||||
String propertyName = accessorNamingStrategy.getPropertyName( targetSetter );
|
||||
return accessorNamingStrategy.getCollectionGetterName( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mirror the type mirror
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user