| 1 | package fr.sii.ogham.core.sender; | |
| 2 | ||
| 3 | import static fr.sii.ogham.core.util.LogUtils.logString; | |
| 4 | ||
| 5 | import java.lang.reflect.ParameterizedType; | |
| 6 | import java.lang.reflect.Type; | |
| 7 | import java.util.List; | |
| 8 | ||
| 9 | import org.slf4j.Logger; | |
| 10 | import org.slf4j.LoggerFactory; | |
| 11 | ||
| 12 | import fr.sii.ogham.core.condition.Condition; | |
| 13 | import fr.sii.ogham.core.exception.MessageException; | |
| 14 | import fr.sii.ogham.core.message.Message; | |
| 15 | import fr.sii.ogham.core.util.PriorizedList; | |
| 16 | ||
| 17 | /** | |
| 18 | * Decorator sender that is able to handle a particular type of message. And for | |
| 19 | * handling this message it can rely on several possible implementations. Each | |
| 20 | * implementation is associated to a {@link Condition}. The condition indicates | |
| 21 | * at runtime if the message can be handled by the possible implementation. | |
| 22 | * There can be any kind of condition (for example, based on a required class in | |
| 23 | * the classpath or a particular property value...). | |
| 24 | * | |
| 25 | * The implementation selection is done in the {@link #supports(Message)} | |
| 26 | * method. | |
| 27 | * | |
| 28 | * @author Aurélien Baudet | |
| 29 | * | |
| 30 | * @param <M> | |
| 31 | * The type of message that the implementations can handle | |
| 32 | * @see Condition | |
| 33 | */ | |
| 34 | public abstract class MultiImplementationSender<M extends Message> implements ConditionalSender { | |
| 35 | private static final Logger LOG = LoggerFactory.getLogger(MultiImplementationSender.class); | |
| 36 | ||
| 37 | /** | |
| 38 | * The list of possible implementations indexed by the associated condition | |
| 39 | */ | |
| 40 | private final PriorizedList<Implementation> implementations; | |
| 41 | ||
| 42 | /** | |
| 43 | * Initialize with no registered implementation. | |
| 44 | */ | |
| 45 | public MultiImplementationSender() { | |
| 46 | this(new PriorizedList<>()); | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Initialize with several implementations. | |
| 51 | * | |
| 52 | * @param implementations | |
| 53 | * the list of possible implementations indexed by the condition | |
| 54 | * that indicates if the implementation is eligible at runtime | |
| 55 | */ | |
| 56 | public MultiImplementationSender(PriorizedList<Implementation> implementations) { | |
| 57 | super(); | |
| 58 | this.implementations = implementations; | |
| 59 | } | |
| 60 | ||
| 61 | /** | |
| 62 | * Register a new possible implementation with the associated condition. The | |
| 63 | * implementation is added at the end so any other possible implementation | |
| 64 | * will be used before this one if the associated condition allow it. | |
| 65 | * | |
| 66 | * @param condition | |
| 67 | * the condition that indicates if the implementation can be used | |
| 68 | * at runtime | |
| 69 | * @param implementation | |
| 70 | * the implementation to register | |
| 71 | * @param priority | |
| 72 | * the registration priority | |
| 73 | * @return this instance for fluent chaining | |
| 74 | */ | |
| 75 | public final MultiImplementationSender<M> addImplementation(Condition<Message> condition, MessageSender implementation, int priority) { | |
| 76 | implementations.register(new Implementation(condition, implementation), priority); | |
| 77 |
1
1. addImplementation : replaced return value with null for fr/sii/ogham/core/sender/MultiImplementationSender::addImplementation → RUN_ERROR |
return this; |
| 78 | } | |
| 79 | ||
| 80 | @Override | |
| 81 | public boolean supports(Message message) { | |
| 82 |
2
1. supports : replaced boolean return with true for fr/sii/ogham/core/sender/MultiImplementationSender::supports → RUN_ERROR 2. supports : negated conditional → RUN_ERROR |
return getSender(message) != null; |
| 83 | } | |
| 84 | ||
| 85 | @Override | |
| 86 | public void send(Message message) throws MessageException { | |
| 87 | MessageSender sender = getSender(message); | |
| 88 |
1
1. send : negated conditional → RUN_ERROR |
if (sender == null) { |
| 89 | LOG.warn("No implementation is able to send the message {}. Skipping", logString(message)); | |
| 90 | return; | |
| 91 | } | |
| 92 | LOG.debug("Sending message {} using {} implementation", logString(message), sender); | |
| 93 |
1
1. send : removed call to fr/sii/ogham/core/sender/MessageSender::send → RUN_ERROR |
sender.send(message); |
| 94 | } | |
| 95 | ||
| 96 | public List<Implementation> getImplementations() { | |
| 97 |
1
1. getImplementations : replaced return value with Collections.emptyList for fr/sii/ogham/core/sender/MultiImplementationSender::getImplementations → RUN_ERROR |
return implementations.getOrdered(); |
| 98 | } | |
| 99 | ||
| 100 | protected boolean supportsMessageType(Message message) { | |
| 101 | Class<M> managedClass = getManagedClass(); | |
| 102 |
1
1. supportsMessageType : negated conditional → RUN_ERROR |
if (managedClass == null) { |
| 103 | LOG.warn("No managed class is declared"); | |
| 104 |
1
1. supportsMessageType : replaced boolean return with true for fr/sii/ogham/core/sender/MultiImplementationSender::supportsMessageType → NO_COVERAGE |
return false; |
| 105 | } | |
| 106 |
2
1. supportsMessageType : replaced boolean return with true for fr/sii/ogham/core/sender/MultiImplementationSender::supportsMessageType → RUN_ERROR 2. supportsMessageType : replaced boolean return with false for fr/sii/ogham/core/sender/MultiImplementationSender::supportsMessageType → RUN_ERROR |
return managedClass.isAssignableFrom(message.getClass()); |
| 107 | } | |
| 108 | ||
| 109 | @SuppressWarnings("unchecked") | |
| 110 | protected Class<M> getManagedClass() { | |
| 111 | Type genericSuperclass = getClass().getGenericSuperclass(); | |
| 112 |
1
1. getManagedClass : negated conditional → RUN_ERROR |
if (genericSuperclass instanceof ParameterizedType) { |
| 113 |
1
1. getManagedClass : replaced return value with null for fr/sii/ogham/core/sender/MultiImplementationSender::getManagedClass → RUN_ERROR |
return (Class<M>) ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0]; |
| 114 | } | |
| 115 | return null; | |
| 116 | } | |
| 117 | ||
| 118 | private MessageSender getSender(Message message) { | |
| 119 |
1
1. getSender : negated conditional → RUN_ERROR |
if (supportsMessageType(message)) { |
| 120 | LOG.debug("Can handle the message type {}. Is there any implementation available to send it ?", message.getClass()); | |
| 121 | for (Implementation impl : implementations.getOrdered()) { | |
| 122 |
1
1. getSender : negated conditional → RUN_ERROR |
if (impl.getCondition().accept(message)) { |
| 123 | LOG.debug("The implementation {} can handle the message {}", impl.getSender(), logString(message)); | |
| 124 |
1
1. getSender : replaced return value with null for fr/sii/ogham/core/sender/MultiImplementationSender::getSender → RUN_ERROR |
return impl.getSender(); |
| 125 | } | |
| 126 | } | |
| 127 | } | |
| 128 | LOG.debug("Can't handle the message type {}", message.getClass()); | |
| 129 | return null; | |
| 130 | } | |
| 131 | ||
| 132 | public static class Implementation { | |
| 133 | private final Condition<Message> condition; | |
| 134 | private final MessageSender sender; | |
| 135 | ||
| 136 | public Implementation(Condition<Message> condition, MessageSender sender) { | |
| 137 | super(); | |
| 138 | this.condition = condition; | |
| 139 | this.sender = sender; | |
| 140 | } | |
| 141 | ||
| 142 | public Condition<Message> getCondition() { | |
| 143 |
1
1. getCondition : replaced return value with null for fr/sii/ogham/core/sender/MultiImplementationSender$Implementation::getCondition → RUN_ERROR |
return condition; |
| 144 | } | |
| 145 | ||
| 146 | public MessageSender getSender() { | |
| 147 |
1
1. getSender : replaced return value with null for fr/sii/ogham/core/sender/MultiImplementationSender$Implementation::getSender → RUN_ERROR |
return sender; |
| 148 | } | |
| 149 | } | |
| 150 | } | |
Mutations | ||
| 77 |
1.1 |
|
| 82 |
1.1 2.2 |
|
| 88 |
1.1 |
|
| 93 |
1.1 |
|
| 97 |
1.1 |
|
| 102 |
1.1 |
|
| 104 |
1.1 |
|
| 106 |
1.1 2.2 |
|
| 112 |
1.1 |
|
| 113 |
1.1 |
|
| 119 |
1.1 |
|
| 122 |
1.1 |
|
| 124 |
1.1 |
|
| 143 |
1.1 |
|
| 147 |
1.1 |