

package gov.va.med.cds.work;


import gov.va.med.cds.transaction.WorkManagerInterface;

import commonj.work.Work;
import commonj.work.WorkEvent;
import commonj.work.WorkException;
import commonj.work.WorkItem;
import commonj.work.WorkManager;

import java.util.ArrayList;
import java.util.List;


public class MultiThreadedWorkManager
    implements
        WorkManagerInterface
{

    // The Work Queue bean, is injected by Spring
    private final WorkQueue workQueue;
    private Worker worker;


    public MultiThreadedWorkManager( WorkQueue queue )
    {
        workQueue = queue;
    }


    public WorkItem schedule( final Work work )
        throws WorkException
    {
        WorkItem workItem = new DefaultWorkItem( work );
        workQueue.addWork( workItem );
        return workItem;
    }


    @Override
    public boolean waitForAll( List<? extends WorkItem> workItems )
        throws WorkException
    {
        return waitForAll( workItems, WorkManager.INDEFINITE );
    }


    /*
     * (non-Javadoc)
     * @see gov.va.med.cds.transaction.WorkManagerInterface#waitForAll(java.util.List, long)
     * @ returns  true if all WorkItems have completed, false if the timeout has expired. 
     */
    @Override
    public boolean waitForAll( List<? extends WorkItem> workItems, long timeout )
        throws WorkException
    {
        boolean timedIn = false;
        startWorker();
        long start = System.currentTimeMillis();
        List<WorkItem> completedWorkItems = new ArrayList<WorkItem>();
        do
        {
            completedWorkItems.clear();
            synchronized ( this )
            {
                for ( WorkItem workItem : workItems )
                {
                    if ( workItem.getStatus() == WorkEvent.WORK_COMPLETED || workItem.getStatus() == WorkEvent.WORK_REJECTED )
                    {
                        completedWorkItems.add( workItem );
                    }
                }
            }
            if ( completedWorkItems.size() == workItems.size() )
            {
                // Did not timeout
                return true;
            }

            timedIn = ( System.currentTimeMillis() - start ) < timeout;
        }
        while ( timedIn );

        // Execution timed out
        return timedIn;
    }


    private void startWorker( )
        throws WorkException
    {
        worker = new Worker( workQueue );
        worker.start();
    }
}
