package com.hpe.caf.api.worker;


import com.hpe.caf.api.Codec;
import com.hpe.caf.api.CodecException;
import com.hpe.caf.api.ConfigurationException;
import com.hpe.caf.api.ConfigurationSource;

import java.util.Objects;


/**
 * A WorkerFactory that uses a pre-defined configuration and Worker task class.
 * This is the recommended abstract base to create a WorkerFactory from.
 *
 * @param <C> the Worker Configuration type parameter
 * @param <T> the Worker Task type parameter
 * @since 9.0
 */
public abstract class DefaultWorkerFactory<C, T> extends WorkerFactory
{
    private final DataStore dataStore;
    private final C configuration;
    private final Codec codec;
    private final Class<T> taskClass;


    /**
     * Instantiates a new DefaultWorkerFactory.
     * @param configSource the worker configuration source
     * @param dataStore the external data store
     * @param codec the codec used in serialisation
     * @param configurationClass the worker configuration class
     * @param taskClass the worker task class
     * @throws WorkerException if the factory cannot be instantiated
     */
    public DefaultWorkerFactory(final ConfigurationSource configSource, final DataStore dataStore, final Codec codec, final Class<C> configurationClass,
                                final Class<T> taskClass)
        throws WorkerException
    {
        this.codec = Objects.requireNonNull(codec);
        this.taskClass = Objects.requireNonNull(taskClass);
        this.dataStore = Objects.requireNonNull(dataStore);
        try {
            this.configuration = configSource.getConfiguration(configurationClass);
        } catch (ConfigurationException e) {
            throw new WorkerException("Failed to create worker factory", e);
        }
    }


    @Override
    public final Worker getWorker
    (
        final String classifier,
        final int version,
        final TaskStatus status,
        final byte[] data,
        final byte[] context
    )
        throws TaskRejectedException, InvalidTaskException
    {
        // Reject tasks of the wrong type and tasks that require a newer version (based on TestWorkerFactory.java)
        final String workerName = getWorkerName();
        if (workerName != null)
        {
            if (!workerName.equals(classifier)) {
                throw new InvalidTaskException(
                    "Task of type " + classifier + " found on queue for " + workerName);
            }

            final int workerApiVersion = getWorkerApiVersion();

            if (workerApiVersion >= 0 && workerApiVersion < version) {
                throw new TaskRejectedException(
                    "Found task version " + version + ", which is newer than " + workerApiVersion);
            }
        }

        // Deserialise the task
        final T task;
        try {
            task = codec.deserialise(data, taskClass);
        } catch (CodecException e) {
            throw new InvalidTaskException("Invalid input message", e);
        }

        // Construct the worker
        return createWorker(task);
    }


    /**
     * Returns the name of the worker to use when checking the task type
     */
    protected String getWorkerName() {
        return null;
    }

    /**
     * Returns the maximum version of the worker message that is supported
     */
    protected int getWorkerApiVersion() {
        return -1;
    }

    /**
     * Create a Worker instance.
     * @param task the deserialised Worker task
     * @return the worker instance
     * @throws TaskRejectedException if a Worker cannot be created to handle this task currently
     * @throws InvalidTaskException if it appears this task cannot possibly be handled by a Worker of this type
     */
    protected abstract Worker createWorker(final T task)
        throws TaskRejectedException, InvalidTaskException;


    /**
     * @return the data store supplied by the application
     */
    protected DataStore getDataStore()
    {
        return dataStore;
    }


    /**
     * @return the configuration associated with this WorkerFactory
     */
    protected C getConfiguration()
    {
        return configuration;
    }


    /**
     * @return the codec supplied by the application for de/serialisation purposes
     */
    protected Codec getCodec()
    {
        return codec;
    }
}

@@ -186,16 +186,53 @@
 nSource;
+%0Aimport com.hpe.caf.api.DecodeMethod;
 %0A%0Aimport
@@ -1804,24 +1804,155 @@
   %7D%0A    %7D%0A%0A%0A
+    /**%0A     * %7B@inheritDoc%7D%0A     * Verify that the incoming task has the right type and is a version that can be handled.%0A     */%0A
     @Overrid
@@ -1990,23 +1990,9 @@
 rker
-%0A    (%0A        
+(
 fina
@@ -2011,24 +2011,16 @@
 ssifier,
-%0A       
  final i
@@ -2030,24 +2030,16 @@
 version,
-%0A       
  final T
@@ -2055,24 +2055,16 @@
  status,
-%0A       
  final b
@@ -2074,24 +2074,16 @@
 %5B%5D data,
-%0A       
  final b
@@ -2095,21 +2095,16 @@
  context
-%0A    
 )%0A      
@@ -2246,42 +2246,8 @@
 sion
- (based on TestWorkerFactory.java)
 %0A   
@@ -2298,54 +2298,8 @@
 ();%0A
-        if (workerName != null)%0A        %7B%0A    
     
@@ -2344,36 +2344,32 @@
 ) %7B%0A            
-    
 throw new Invali
@@ -2383,37 +2383,16 @@
 ception(
-%0A                    
 %22Task of
@@ -2456,35 +2456,27 @@
 e);%0A        
-  
-  
 %7D%0A%0A
-    
         fina
@@ -2528,28 +2528,24 @@
 );%0A%0A        
-    
 if (workerAp
@@ -2557,33 +2557,8 @@
 ion 
-%3E= 0 && workerApiVersion 
 %3C ve
@@ -2562,28 +2562,24 @@
  version) %7B%0A
-    
             
@@ -2610,37 +2610,16 @@
 ception(
-%0A                    
 %22Found t
@@ -2702,112 +2702,58 @@
     
-    %7D%0A        %7D%0A%0A        // Deserialise the task%0A        final T task;%0A        try %7B%0A            task = 
+%7D%0A%0A        try %7B%0A             return createWorker(
 code
@@ -2773,32 +2773,55 @@
 (data, taskClass
+, DecodeMethod.LENIENT)
 );%0A        %7D cat
@@ -2929,76 +2929,8 @@
    %7D
-%0A%0A        // Construct the worker%0A        return createWorker(task);
 %0A   
@@ -3037,16 +3037,25 @@
 otected 
+abstract 
 String g
@@ -3072,37 +3072,10 @@
 me()
- %7B%0A        return null;%0A    %7D
+;%0A
 %0A%0A  
@@ -3177,16 +3177,25 @@
 otected 
+abstract 
 int getW
@@ -3215,35 +3215,10 @@
 on()
- %7B%0A        return -1;%0A    %7D
+;%0A
 %0A%0A  

Change logic of DefaultWorkerFactory so that Worker name and API version are required