// Path: intf/src/main/java/funcatron/intf/Accumulator.java
// public interface Accumulator {
//     /**
//      * Accumulate vendors that need "finishing"
//      * @param item the item that was vended
//      * @param vendor the thing doing the vending
//      * @param <T> the type of thing
//      */
//     <T> void accumulate(T item, ServiceVendor<T> vendor);
// 
//     /**
//      * For all the vended things, finish them either successfully onsuccessfully.
//      *
//      * @param success was the operation a success (e.g., commit) or not (e.g., rollback)
//      */
//     void finished(boolean success);
// }
// 
// Path: intf/src/main/java/funcatron/intf/ServiceVendor.java
// public interface ServiceVendor<T> {
// 
//     /**
//      * The name of the service
//      * @return the name of the service
//      */
//     String name();
// 
//     /**
//      * The type of the service vended
//      *
//      * @return the class object of the type of service vended
//      */
//     Class<T> type();
// 
// 
//     /**
//      * Is the class of a given type? For example `ofType(java.sql.Connection.class)`
//      * to test for JDBC
//      * @param clz the class to test the instance against
//      * @return boolean
//      */
//     default boolean ofType(Class<?> clz) {
//         return type().isAssignableFrom(clz);
//     }
// 
//     /**
//      * Vends an instance of the thing (like a JDBC connection)
//      *
//      * @param acc the accumulator
//      * @return an instance of the thing
//      * @throws Exception failure to create the instance
//      */
//     T vend(Accumulator acc) throws Exception;
// 
//     /**
//      * Close down any resources the vendor has (e.g., close all the JDBC connections)
//      */
//     void endLife();
// 
//     /**
//      * Release the resource at the end of a Func execution. Depending on `success`,
//      * the resource may be released in different ways (e.g., database commit vs. database rollback)
//      * @param item the item to release
//      * @param success true if the function executed successfully and the transaction should be committed. false on an exception
//      * @throws Exception if the release operation throws an exception
//      */
//     void release(T item, boolean success) throws Exception;
// }
// 
// Path: intf/src/main/java/funcatron/intf/ServiceVendorProvider.java
// public interface ServiceVendorProvider {
//     /**
//      * The string type that this Builder will build a vendor for.
//      * Example "database"
//      * @return the name of the type this builder will build for
//      */
//     String forType();
// 
// 
//     /**
//      * If the 'type' field in the properties matches
//      * @param name the name of the ServiceVendor
//      * @param properties properties for the service vendor... for example the JDBC connection information
//      * @param logger log anything to the logger
//      * @return If we can successfull build the service vendor, build it
//      */
//     Optional<ServiceVendor<?>> buildVendor(String name, Map<String, Object> properties, Logger logger);
// }


import funcatron.intf.Accumulator;
import funcatron.intf.ServiceVendor;
import funcatron.intf.ServiceVendorProvider;
import redis.clients.jedis.Jedis;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Logger;
package $package;



/**
 * An example of a provider so the Context can vend instances of
 * things like DB drivers, cache drivers, etc.
 */
public class RedisProvider implements ServiceVendorProvider {
    /**
     * What's the name of this driver?
     * @return the unique name
     */
    @Override
    public String forType() {
        return "redis";
    }

    /**
     * Some fancy null testing
     * @param o an object
     * @param clz a class to test
     * @param <T> the type of the class
     * @return null if o is not an instance of the class or null
     */
    private <T> T ofType(Object o, Class<T> clz) {
        if (null != o &&
                clz.isInstance(o)) return (T) o;
        return null;
    }

    /**
     * Build something that will vend the named service based on the property map
     * @param name the name of the item
     * @param properties the properties
     * @param logger if something needs logging
     * @return If the properties are valid, return a ServiceVendor that will do the right thing
     */
    @Override
    public Optional<ServiceVendor<?>> buildVendor(String name, Map<String, Object> properties, Logger logger) {
        final String host = ofType(properties.get("host"), String.class);

        if (null == host) return Optional.empty();

        return Optional.of(new ServiceVendor<Jedis>() {
            @Override
// Path: intf/src/main/java/funcatron/intf/Accumulator.java
// public interface Accumulator {
//     /**
//      * Accumulate vendors that need "finishing"
//      * @param item the item that was vended
//      * @param vendor the thing doing the vending
//      * @param <T> the type of thing
//      */
//     <T> void accumulate(T item, ServiceVendor<T> vendor);
// 
//     /**
//      * For all the vended things, finish them either successfully onsuccessfully.
//      *
//      * @param success was the operation a success (e.g., commit) or not (e.g., rollback)
//      */
//     void finished(boolean success);
// }
// 
// Path: intf/src/main/java/funcatron/intf/ServiceVendor.java
// public interface ServiceVendor<T> {
// 
//     /**
//      * The name of the service
//      * @return the name of the service
//      */
//     String name();
// 
//     /**
//      * The type of the service vended
//      *
//      * @return the class object of the type of service vended
//      */
//     Class<T> type();
// 
// 
//     /**
//      * Is the class of a given type? For example `ofType(java.sql.Connection.class)`
//      * to test for JDBC
//      * @param clz the class to test the instance against
//      * @return boolean
//      */
//     default boolean ofType(Class<?> clz) {
//         return type().isAssignableFrom(clz);
//     }
// 
//     /**
//      * Vends an instance of the thing (like a JDBC connection)
//      *
//      * @param acc the accumulator
//      * @return an instance of the thing
//      * @throws Exception failure to create the instance
//      */
//     T vend(Accumulator acc) throws Exception;
// 
//     /**
//      * Close down any resources the vendor has (e.g., close all the JDBC connections)
//      */
//     void endLife();
// 
//     /**
//      * Release the resource at the end of a Func execution. Depending on `success`,
//      * the resource may be released in different ways (e.g., database commit vs. database rollback)
//      * @param item the item to release
//      * @param success true if the function executed successfully and the transaction should be committed. false on an exception
//      * @throws Exception if the release operation throws an exception
//      */
//     void release(T item, boolean success) throws Exception;
// }
// 
// Path: intf/src/main/java/funcatron/intf/ServiceVendorProvider.java
// public interface ServiceVendorProvider {
//     /**
//      * The string type that this Builder will build a vendor for.
//      * Example "database"
//      * @return the name of the type this builder will build for
//      */
//     String forType();
// 
// 
//     /**
//      * If the 'type' field in the properties matches
//      * @param name the name of the ServiceVendor
//      * @param properties properties for the service vendor... for example the JDBC connection information
//      * @param logger log anything to the logger
//      * @return If we can successfull build the service vendor, build it
//      */
//     Optional<ServiceVendor<?>> buildVendor(String name, Map<String, Object> properties, Logger logger);
// }


// Path: starter/src/main/resources/archetype-resources/src/main/java/RedisProvider.java
import funcatron.intf.Accumulator;
import funcatron.intf.ServiceVendor;
import funcatron.intf.ServiceVendorProvider;
import redis.clients.jedis.Jedis;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Logger;

package $package;



/**
 * An example of a provider so the Context can vend instances of
 * things like DB drivers, cache drivers, etc.
 */
public class RedisProvider implements ServiceVendorProvider {
    /**
     * What's the name of this driver?
     * @return the unique name
     */
    @Override
    public String forType() {
        return "redis";
    }

    /**
     * Some fancy null testing
     * @param o an object
     * @param clz a class to test
     * @param <T> the type of the class
     * @return null if o is not an instance of the class or null
     */
    private <T> T ofType(Object o, Class<T> clz) {
        if (null != o &&
                clz.isInstance(o)) return (T) o;
        return null;
    }

    /**
     * Build something that will vend the named service based on the property map
     * @param name the name of the item
     * @param properties the properties
     * @param logger if something needs logging
     * @return If the properties are valid, return a ServiceVendor that will do the right thing
     */
    @Override
    public Optional<ServiceVendor<?>> buildVendor(String name, Map<String, Object> properties, Logger logger) {
        final String host = ofType(properties.get("host"), String.class);

        if (null == host) return Optional.empty();

        return Optional.of(new ServiceVendor<Jedis>() {
            @Override
            public String name() {