package com.oldratlee.mtc;

import java.util.Map;

/**
 * {@link MtContextRunnable} decorate {@link Runnable}, so as to get @{@link MtContext}
 * and transmit it to the time of {@link Runnable} execution, needed when use {@link Runnable} to thread pool.
 * <p/>
 * Use factory method {@link #get(Runnable)} to create instance.
 *
 * @author ding.lid
 * @see java.util.concurrent.Executor
 * @see java.util.concurrent.ExecutorService
 * @see java.util.concurrent.ThreadPoolExecutor
 * @see java.util.concurrent.ScheduledThreadPoolExecutor
 * @see java.util.concurrent.Executors
 * @since 0.9.0
 */
public final class MtContextRunnable implements Runnable {
    private final Map<String, Object> context;
    private final Runnable runnable;

    private MtContextRunnable(Runnable runnable) {
        context = MtContext.getContext().get();
        this.runnable = runnable;
    }

    /**
     * wrap method {@link Runnable#run()}.
     */
    @Override
    public void run() {
        MtContext mtContext = MtContext.getContext();
        final Map<String, Object> old = mtContext.get();
        try {
            mtContext.set(context);
            runnable.run();
        } finally {
            mtContext.set(old); // restore MtContext
        }
    }

    public Runnable getRunnable() {
        return runnable;
    }

    /**
     * Factory method, wrapper input {@link Runnable} to {@link MtContextRunnable}.
     * <p/>
     * This method is idempotent.
     *
     * @param runnable input {@link Runnable}
     * @return Wrapped {@link Runnable}
     */
    public static MtContextRunnable get(Runnable runnable) {
        if (null == runnable) {
            throw new NullPointerException("runnable argument is null!");
        }

        if (runnable instanceof MtContextRunnable) { // avoid redundant decoration, and ensure idempotency
            return (MtContextRunnable) runnable;
        }
        return new MtContextRunnable(runnable);
    }
}

@@ -21,16 +21,96 @@
 e.mtc;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Collection;%0Aimport java.util.List;%0A
 import j
@@ -2034,11 +2034,470 @@
 );%0A    %7D
+%0A%0A    /**%0A     * wrapper input %7B@link Runnable%7D Collection to %7B@link MtContextRunnable%7D Collection.%0A     */%0A    public static List%3CMtContextRunnable%3E gets(Collection%3C? extends Runnable%3E tasks) %7B%0A        if (null == tasks) %7B%0A            return null;%0A        %7D%0A        List%3CMtContextRunnable%3E copy = new ArrayList%3CMtContextRunnable%3E();%0A        for (Runnable task : tasks) %7B%0A            copy.add(MtContextRunnable.get(task));%0A        %7D%0A        return copy;%0A    %7D
 %0A%7D%0A

add util method gets to MtContextRunnable