001package co.codewizards.cloudstore.ls.client.handler; 002 003import static java.util.Objects.*; 004 005import java.util.HashMap; 006import java.util.Iterator; 007import java.util.Map; 008import java.util.ServiceLoader; 009import java.util.Set; 010import java.util.SortedSet; 011import java.util.TreeSet; 012 013import co.codewizards.cloudstore.ls.core.dto.InverseServiceRequest; 014 015@SuppressWarnings("rawtypes") 016public class InverseServiceRequestHandlerManager { 017 018 private static final class HandlerClass implements Comparable<HandlerClass> { 019 public final Class<? extends InverseServiceRequestHandler> handlerClass; 020 public final int priority; 021 022 public HandlerClass(final Class<? extends InverseServiceRequestHandler> handlerClass, final int priority) { 023 this.handlerClass = requireNonNull(handlerClass, "handlerClass"); 024 this.priority = priority; 025 } 026 027 /** 028 * {@inheritDoc} 029 * <p> 030 * <b>Important:</b> the implementation in {@code HandlerClass} sorts by priority first, then by name. 031 * The highest priority (greatest number) comes first! 032 */ 033 @Override 034 public int compareTo(HandlerClass o) { 035 int result = -1 * Integer.compare(this.priority, o.priority); 036 if (result != 0) 037 return result; 038 039 return this.handlerClass.getName().compareTo(o.handlerClass.getName()); 040 } 041 } 042 043 private final Map<Class<?>, HandlerClass> requestType2HandlerClass = new HashMap<>(); 044 private final Map<Class<?>, Class<? extends InverseServiceRequestHandler>> resolvedRequestType2HandlerClassCache = new HashMap<>(); 045 046 private static final class Holder { 047 public static final InverseServiceRequestHandlerManager instance = new InverseServiceRequestHandlerManager(); 048 } 049 050 public static InverseServiceRequestHandlerManager getInstance() { 051 return Holder.instance; 052 } 053 054 protected InverseServiceRequestHandlerManager() { 055 } 056 057 public InverseServiceRequestHandler getInverseServiceRequestHandler(Class<?> requestClass) { 058 requireNonNull(requestClass, "requestClass"); 059 060 final Class<? extends InverseServiceRequestHandler> handlerClass = getInverseServiceRequestHandlerClass(requestClass); 061 if (handlerClass == null) 062 return null; 063 else 064 return newInstance(handlerClass); 065 } 066 067 private synchronized Class<? extends InverseServiceRequestHandler> getInverseServiceRequestHandlerClass(Class<?> requestClass) { 068 Class<? extends InverseServiceRequestHandler> result = resolvedRequestType2HandlerClassCache.get(requestClass); 069 if (result == null) { 070 final SortedSet<HandlerClass> handlerClasses = getInverseServiceRequestHandlerClasses(requestClass); 071 if (handlerClasses.isEmpty()) 072 return null; 073 074 result = handlerClasses.iterator().next().handlerClass; 075 } 076 return result; 077 } 078 079 private synchronized SortedSet<HandlerClass> getInverseServiceRequestHandlerClasses(final Class<?> requestClass) { 080 requireNonNull(requestClass, "requestClass"); 081 082 if (requestType2HandlerClass.isEmpty()) { 083 final Iterator<InverseServiceRequestHandler> iterator = ServiceLoader.load(InverseServiceRequestHandler.class).iterator(); 084 while (iterator.hasNext()) { 085 final InverseServiceRequestHandler handler = iterator.next(); 086 requestType2HandlerClass.put(handler.getInverseServiceRequestType(), new HandlerClass(handler.getClass(), handler.getPriority())); 087 } 088 } 089 090 final SortedSet<HandlerClass> handlerClasses = new TreeSet<>(); 091 Class<?> c = requestClass; 092 while (c != null && c != Object.class) { 093 populateHandlerClasses(handlerClasses, c); 094 c = c.getSuperclass(); 095 } 096 return handlerClasses; 097 } 098 099 private void populateHandlerClasses(final Set<HandlerClass> handlerClasses, final Class<?> requestClass) { 100 final HandlerClass handlerClass = requestType2HandlerClass.get(requestClass); 101 if (handlerClass != null) 102 handlerClasses.add(handlerClass); 103 104 for (final Class<?> iface : requestClass.getInterfaces()) 105 populateHandlerClasses(handlerClasses, iface); 106 } 107 108 public InverseServiceRequestHandler getInverseServiceRequestHandlerOrFail(Class<?> requestClass) { 109 final InverseServiceRequestHandler handler = getInverseServiceRequestHandler(requestClass); 110 if (handler == null) 111 throw new IllegalArgumentException("Could not find a handler for this requestClass: " + requestClass.getName()); 112 113 return handler; 114 } 115 116 public InverseServiceRequestHandler getInverseServiceRequestHandlerOrFail(final InverseServiceRequest request) { 117 requireNonNull(request, "request"); 118 return getInverseServiceRequestHandlerOrFail(request.getClass()); 119 } 120 121 private InverseServiceRequestHandler newInstance(Class<? extends InverseServiceRequestHandler> handlerClass) { 122 requireNonNull(handlerClass, "handlerClass"); 123 try { 124 return handlerClass.newInstance(); 125 } catch (final InstantiationException | IllegalAccessException e) { 126 throw new RuntimeException(e); 127 } 128 } 129}