// Path: src/main/java/de/skuzzle/inject/async/schedule/SpiTriggerStrategyRegistryImpl.java
// class SpiTriggerStrategyRegistryImpl implements TriggerStrategyRegistry {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(SpiTriggerStrategyRegistryImpl.class);
// 
//     private final Map<Class<? extends Annotation>, TriggerStrategy> strategies;
// 
//     private final Injector injector;
// 
//     @Inject
//     public SpiTriggerStrategyRegistryImpl(Injector injector) {
//         this.injector = injector;
//         this.strategies = collectTriggerStrategies();
//     }
// 
//     private Map<Class<? extends Annotation>, TriggerStrategy> collectTriggerStrategies() {
//         final ServiceLoader<TriggerStrategy> services = ServiceLoader.load(
//                 TriggerStrategy.class);
// 
//         return asStream(services)
//                 .peek(strategy -> LOG.debug("Installing strategy '{}' to handle '{}'",
//                         strategy, strategy.getTriggerType()))
//                 .peek(this.injector::injectMembers)
//                 .collect(Collectors.toMap(
//                         TriggerStrategy::getTriggerType,
//                         Function.identity()));
//     }
// 
//     private static <T> Stream<T> asStream(Iterable<T> iterable) {
//         return StreamSupport.stream(iterable.spliterator(), false);
//     }
// 
//     @Override
//     public TriggerStrategy getStrategyFor(Annotation triggerAnnotation) {
//         checkArgument(triggerAnnotation != null);
//         final Class<? extends Annotation> type = triggerAnnotation.annotationType();
//         final TriggerStrategy result = this.strategies.get(type);
//         checkState(result != null,
//                 "There is no TriggerStrategy registered which is able to handle '%s'",
//                 type.getName());
//         return result;
//     }
// 
// }
// 
// Path: src/main/java/de/skuzzle/inject/async/schedule/TriggerStrategy.java
// public interface TriggerStrategy {
// 
//     /**
//      * Returns the annotation type that this strategy can handle.
//      *
//      * @return The annotation type.
//      */
//     Class<? extends Annotation> getTriggerType();
// 
//     /**
//      * Extracts scheduling information from the provided {@link Method} and then schedules
//      * invocations of that method according to the information.
//      *
//      * <p>
//      * To support invocation of parameterized methods, implementors can refer to
//      * {@link InjectedMethodInvocation} to inject actual parameters of a method.
//      * </p>
//      *
//      * @param context The schedule context for the annotated method.
//      * @param executor The executor to use for scheduling.
//      * @param runnable A runnable that, when scheduled, will execute the annotated method.
//      */
//     void schedule(ScheduledContext context,
//             ScheduledExecutorService executor, LockableRunnable runnable);
// }
// 
// Path: src/main/java/de/skuzzle/inject/async/schedule/trigger/CronTriggerStrategy.java
// public class CronTriggerStrategy implements TriggerStrategy {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(CronTriggerStrategy.class);
// 
//     @Override
//     public Class<CronTrigger> getTriggerType() {
//         return CronTrigger.class;
//     }
// 
//     @Override
//     public void schedule(ScheduledContext context, ScheduledExecutorService executor, LockableRunnable runnable) {
//         final Method method = context.getMethod();
//         final CronTrigger trigger = method.getAnnotation(getTriggerType());
//         checkArgument(trigger != null, "Method '%s' not annotated with @CronTrigger", method);
// 
//         LOG.debug("Initially scheduling method '{}' on '{}' with trigger: {}", method, context.getSelf(), trigger);
//         final CronType cronType = trigger.cronType();
//         final CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(cronType.getType());
//         final CronParser parser = new CronParser(cronDefinition);
//         final Cron cron = parser.parse(trigger.value());
//         final ExecutionTime execTime = ExecutionTime.forCron(cron);
// 
//         CronScheduler
//                 .createWith(context, runnable.release(), executor, execTime)
//                 .start();
//     }
// }


import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.annotation.Annotation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import com.google.inject.Injector;
import de.skuzzle.inject.async.schedule.SpiTriggerStrategyRegistryImpl;
import de.skuzzle.inject.async.schedule.TriggerStrategy;
import de.skuzzle.inject.async.schedule.annotation.CronTrigger;
import de.skuzzle.inject.async.schedule.annotation.Scheduled;
import de.skuzzle.inject.async.schedule.trigger.CronTriggerStrategy;
package de.skuzzle.inject.async.schedule;






@RunWith(MockitoJUnitRunner.class)
public class SpiTriggerStrategyRegistryImplTest {

    @Mock
    private Injector injector;
    @Mock
    private Annotation triggerAnnotation;
    @InjectMocks
    private SpiTriggerStrategyRegistryImpl subject;

    @Before
    public void setup() {
        when(this.triggerAnnotation.annotationType()).thenReturn(
                (Class) CronTrigger.class);
    }

    @Test
    public void testGetStrategyFor() throws Exception {
        final TriggerStrategy strategy = this.subject
                .getStrategyFor(this.triggerAnnotation);
        verify(this.injector).injectMembers(Mockito.isA(CronTriggerStrategy.class));
        assertTrue(strategy instanceof CronTriggerStrategy);
    }

    @Test(expected = IllegalStateException.class)
    public void testGetStrategyForUnknown() throws Exception {
        when(this.triggerAnnotation.annotationType()).thenReturn(
                (Class) Scheduled.class); // random annotation type
        this.subject.getStrategyFor(this.triggerAnnotation);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testGetStrategyforNull() throws Exception {
// Path: src/main/java/de/skuzzle/inject/async/schedule/SpiTriggerStrategyRegistryImpl.java
// class SpiTriggerStrategyRegistryImpl implements TriggerStrategyRegistry {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(SpiTriggerStrategyRegistryImpl.class);
// 
//     private final Map<Class<? extends Annotation>, TriggerStrategy> strategies;
// 
//     private final Injector injector;
// 
//     @Inject
//     public SpiTriggerStrategyRegistryImpl(Injector injector) {
//         this.injector = injector;
//         this.strategies = collectTriggerStrategies();
//     }
// 
//     private Map<Class<? extends Annotation>, TriggerStrategy> collectTriggerStrategies() {
//         final ServiceLoader<TriggerStrategy> services = ServiceLoader.load(
//                 TriggerStrategy.class);
// 
//         return asStream(services)
//                 .peek(strategy -> LOG.debug("Installing strategy '{}' to handle '{}'",
//                         strategy, strategy.getTriggerType()))
//                 .peek(this.injector::injectMembers)
//                 .collect(Collectors.toMap(
//                         TriggerStrategy::getTriggerType,
//                         Function.identity()));
//     }
// 
//     private static <T> Stream<T> asStream(Iterable<T> iterable) {
//         return StreamSupport.stream(iterable.spliterator(), false);
//     }
// 
//     @Override
//     public TriggerStrategy getStrategyFor(Annotation triggerAnnotation) {
//         checkArgument(triggerAnnotation != null);
//         final Class<? extends Annotation> type = triggerAnnotation.annotationType();
//         final TriggerStrategy result = this.strategies.get(type);
//         checkState(result != null,
//                 "There is no TriggerStrategy registered which is able to handle '%s'",
//                 type.getName());
//         return result;
//     }
// 
// }
// 
// Path: src/main/java/de/skuzzle/inject/async/schedule/TriggerStrategy.java
// public interface TriggerStrategy {
// 
//     /**
//      * Returns the annotation type that this strategy can handle.
//      *
//      * @return The annotation type.
//      */
//     Class<? extends Annotation> getTriggerType();
// 
//     /**
//      * Extracts scheduling information from the provided {@link Method} and then schedules
//      * invocations of that method according to the information.
//      *
//      * <p>
//      * To support invocation of parameterized methods, implementors can refer to
//      * {@link InjectedMethodInvocation} to inject actual parameters of a method.
//      * </p>
//      *
//      * @param context The schedule context for the annotated method.
//      * @param executor The executor to use for scheduling.
//      * @param runnable A runnable that, when scheduled, will execute the annotated method.
//      */
//     void schedule(ScheduledContext context,
//             ScheduledExecutorService executor, LockableRunnable runnable);
// }
// 
// Path: src/main/java/de/skuzzle/inject/async/schedule/trigger/CronTriggerStrategy.java
// public class CronTriggerStrategy implements TriggerStrategy {
// 
//     private static final Logger LOG = LoggerFactory.getLogger(CronTriggerStrategy.class);
// 
//     @Override
//     public Class<CronTrigger> getTriggerType() {
//         return CronTrigger.class;
//     }
// 
//     @Override
//     public void schedule(ScheduledContext context, ScheduledExecutorService executor, LockableRunnable runnable) {
//         final Method method = context.getMethod();
//         final CronTrigger trigger = method.getAnnotation(getTriggerType());
//         checkArgument(trigger != null, "Method '%s' not annotated with @CronTrigger", method);
// 
//         LOG.debug("Initially scheduling method '{}' on '{}' with trigger: {}", method, context.getSelf(), trigger);
//         final CronType cronType = trigger.cronType();
//         final CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(cronType.getType());
//         final CronParser parser = new CronParser(cronDefinition);
//         final Cron cron = parser.parse(trigger.value());
//         final ExecutionTime execTime = ExecutionTime.forCron(cron);
// 
//         CronScheduler
//                 .createWith(context, runnable.release(), executor, execTime)
//                 .start();
//     }
// }


// Path: src/test/java/de/skuzzle/inject/async/schedule/SpiTriggerStrategyRegistryImplTest.java
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.annotation.Annotation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import com.google.inject.Injector;
import de.skuzzle.inject.async.schedule.SpiTriggerStrategyRegistryImpl;
import de.skuzzle.inject.async.schedule.TriggerStrategy;
import de.skuzzle.inject.async.schedule.annotation.CronTrigger;
import de.skuzzle.inject.async.schedule.annotation.Scheduled;
import de.skuzzle.inject.async.schedule.trigger.CronTriggerStrategy;

package de.skuzzle.inject.async.schedule;






@RunWith(MockitoJUnitRunner.class)
public class SpiTriggerStrategyRegistryImplTest {

    @Mock
    private Injector injector;
    @Mock
    private Annotation triggerAnnotation;
    @InjectMocks
    private SpiTriggerStrategyRegistryImpl subject;

    @Before
    public void setup() {
        when(this.triggerAnnotation.annotationType()).thenReturn(
                (Class) CronTrigger.class);
    }

    @Test
    public void testGetStrategyFor() throws Exception {
        final TriggerStrategy strategy = this.subject
                .getStrategyFor(this.triggerAnnotation);
        verify(this.injector).injectMembers(Mockito.isA(CronTriggerStrategy.class));
        assertTrue(strategy instanceof CronTriggerStrategy);
    }

    @Test(expected = IllegalStateException.class)
    public void testGetStrategyForUnknown() throws Exception {
        when(this.triggerAnnotation.annotationType()).thenReturn(
                (Class) Scheduled.class); // random annotation type
        this.subject.getStrategyFor(this.triggerAnnotation);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testGetStrategyforNull() throws Exception {
        this.subject.getStrategyFor(null);