package io.fluxcapacitor.javaclient.persisting.eventsourcing;

import io.fluxcapacitor.common.handling.HandlerInvoker;
import io.fluxcapacitor.common.handling.HandlerNotFoundException;
import io.fluxcapacitor.common.handling.ParameterResolver;
import io.fluxcapacitor.javaclient.common.serialization.DeserializingMessage;

import java.util.List;

import static io.fluxcapacitor.common.handling.HandlerConfiguration.defaultHandlerConfiguration;
import static io.fluxcapacitor.common.handling.HandlerInspector.inspect;

public class AnnotatedEventSourcingHandler<T> implements EventSourcingHandler<T> {
    
    private final Class<T> handlerType;
    private final HandlerInvoker<DeserializingMessage> invoker;

    public AnnotatedEventSourcingHandler(Class<T> handlerType) {
        this(handlerType, DeserializingMessage.defaultParameterResolvers);
    }

    public AnnotatedEventSourcingHandler(Class<T> handlerType,
                                         List<ParameterResolver<? super DeserializingMessage>> parameterResolvers) {
        this.handlerType = handlerType;
        this.invoker = inspect(handlerType, ApplyEvent.class, parameterResolvers, defaultHandlerConfiguration());
    }

    @Override
    public T invoke(T target, DeserializingMessage message) {
        Object result;
        try {
            result = invoker.invoke(target, message);
        } catch (HandlerNotFoundException e) {
            if (target == null) {
                throw e;
            }
            return target;
        }
        if (target == null) {
            return handlerType.cast(result);
        }
        if (handlerType.isInstance(result)) {
            return handlerType.cast(result);
        }
        if (result == null && invoker.expectResult(target, message)) {
            return null; //this handler has deleted the model on purpose
        }
        return target; //Annotated method returned void - apparently the model is mutable
    }

    @Override
    public boolean canHandle(T target, DeserializingMessage message) {
        return invoker.canHandle(target, message);
    }

}

@@ -1260,32 +1260,72 @@
 sage message) %7B%0A
+        return message.apply(m -%3E %7B%0A    
         Object r
@@ -1343,14 +1343,22 @@
     
+    
 try %7B%0A
+    
     
@@ -1394,33 +1394,31 @@
 ke(target, m
-essage);%0A
+);%0A    
         %7D ca
@@ -1456,32 +1456,36 @@
 ) %7B%0A            
+  
+  
 if (target == nu
@@ -1506,16 +1506,20 @@
         
+    
 throw e;
@@ -1523,34 +1523,42 @@
  e;%0A            
+  
-%7D%0A
+  %7D%0A    
             retu
@@ -1568,34 +1568,42 @@
 target;%0A        
+   
+ 
 %7D%0A
+    
         if (targ
@@ -1620,32 +1620,36 @@
 ) %7B%0A            
+   
+ 
 return handlerTy
@@ -1665,34 +1665,42 @@
 esult);%0A        
-%7D%0A
+    %7D%0A    
         if (hand
@@ -1733,32 +1733,36 @@
 ) %7B%0A            
+    
 return handlerTy
@@ -1770,32 +1770,36 @@
 e.cast(result);%0A
+    
         %7D%0A      
@@ -1796,24 +1796,28 @@
   %7D%0A        
+    
 if (result =
@@ -1860,19 +1860,17 @@
 t, m
-essage
 )) %7B%0A
+    
     
@@ -1938,34 +1938,42 @@
 purpose%0A        
+   
+ 
 %7D%0A
+    
         return t
@@ -2046,16 +2046,28 @@
 mutable%0A
+        %7D);%0A
     %7D%0A%0A 

Set current Deserializing message when applying event to aggregate