001package org.apache.turbine.services.schedule;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.Collections;
023import java.util.Comparator;
024import java.util.List;
025import java.util.Vector;
026
027import org.apache.turbine.util.TurbineException;
028
029/**
030 * Queue for the scheduler.
031 *
032 * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
033 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
034 * @version $Id: JobQueue.java 615328 2008-01-25 20:25:05Z tv $
035 * @param <J> a specialized job entry type
036 */
037public class JobQueue<J extends JobEntry>
038{
039    /**
040     * The queue of <code>JobEntry</code> objects.
041     */
042    private Vector<J> queue = null;
043
044    /**
045     * Creates a new instance.
046     */
047    public JobQueue()
048    {
049        queue = new Vector<>(10);
050    }
051
052    /**
053     * Return the next job off the top of the queue, or <code>null</code> if
054     * there are no jobs in the queue.
055     *
056     * @return The next job in the queue.
057     */
058    public J getNext()
059    {
060        if (queue.size() > 0)
061        {
062            return queue.elementAt(0);
063        }
064        else
065        {
066            return null;
067        }
068    }
069
070    /**
071     * Return a specific job.
072     *
073     * @param je The JobEntry we are looking for.
074     * @return A JobEntry.
075     */
076    public J getJob(J je)
077    {
078        int index = -1;
079
080        if (je != null)
081        {
082            index = queue.indexOf(je);
083        }
084
085        if (index < 0)
086        {
087            return null;
088        }
089        else
090        {
091            return queue.elementAt(index);
092        }
093    }
094
095    /**
096     * List jobs in the queue.  This is used by the scheduler UI.
097     *
098     * @return A Vector of <code>JobEntry</code> objects.
099     */
100    @SuppressWarnings("unchecked")
101    public Vector<J> list()
102    {
103        if (queue != null && queue.size() > 0)
104        {
105            return (Vector<J>) queue.clone();
106        }
107        else
108        {
109            return null;
110        }
111    }
112
113    /**
114     * Add a job to the queue.
115     *
116     * @param je A JobEntry job.
117     */
118    public synchronized void add(J je)
119    {
120        queue.addElement(je);
121        sortQueue();
122    }
123
124    /**
125     * Batch load jobs.  Retains any already enqueued jobs.  Called on
126     * <code>SchedulerService</code> start-up.
127     *
128     * @param jobEntries A list of the <code>JobEntry</code> objects to load.
129     */
130    public synchronized void batchLoad(List<J> jobEntries)
131    {
132        if (jobEntries != null)
133        {
134            queue.addAll(jobEntries);
135            sortQueue();
136        }
137
138    }
139
140    /**
141     * Remove a job from the queue.
142     *
143     * @param je A JobEntry with the job to remove.
144     */
145    public synchronized void remove(J je)
146    {
147        queue.removeElement(je);
148        sortQueue();
149    }
150
151    /**
152     * Modify a job on the queue.
153     *
154     * @param je A JobEntry with the job to modify
155     * @throws TurbineException if the runtime calculation fails
156     */
157    public synchronized void modify(J je) throws TurbineException
158    {
159        remove(je);
160        je.calcRunTime();
161        this.add(je);
162        sortQueue();
163    }
164
165    /**
166     * Update the job for its next run time.
167     *
168     * @param je A JobEntry to be updated.
169     * @throws TurbineException a generic exception.
170     */
171    public synchronized void updateQueue(J je)
172            throws TurbineException
173    {
174        je.calcRunTime();
175        sortQueue();
176    }
177
178    /**
179     * Re-sort the existing queue.  Consumers of this method should be
180     * <code>synchronized</code>.
181     */
182    private void sortQueue()
183    {
184        Comparator<J> aComparator = (o1, o2) -> {
185            Long time1 = Long.valueOf(o1.getNextRuntime());
186            Long time2 = Long.valueOf(o2.getNextRuntime());
187            return time1.compareTo(time2);
188        };
189
190        Collections.sort(queue, aComparator);
191    }
192}