package org.oddjob.jobs.structural; import javax.swing.ImageIcon; import org.apache.log4j.Logger; import org.oddjob.FailedToStopException; import org.oddjob.Iconic; import org.oddjob.Structural; import org.oddjob.images.IconEvent; import org.oddjob.images.IconHelper; import org.oddjob.images.IconListener; import org.oddjob.images.ImageIconStable; import org.oddjob.structural.ChildHelper; import org.oddjob.structural.StructuralListener; /** * @oddjob.description Holds a collection of jobs but does not * execute them. Used to collect and organise jobs. The jobs can either * be scheduled by a scheduler or run manually. * <p> * A folder has no state, it can't be run and it can't be stopped. * * @oddjob.example * * A folder of jobs. * * {@oddjob.xml.resource org/oddjob/jobs/structural/JobFolderExample.xml} * * * @author Rob Gordon */ public class JobFolder implements Structural, Iconic { private static final Logger logger = Logger.getLogger(JobFolder.class); /** Icon. */ private static final ImageIcon icon = new ImageIconStable( IconHelper.class.getResource("Open16.gif"), "folder"); /** Child helper. */ protected ChildHelper<Object> childHelper = new ChildHelper<Object>(this); /** * @oddjob.property * @oddjob.description The name of the folder. * @oddjob.required No. */ private String name; /** * This flag is set once the object is destroyed * Methods in subclass should check this flag. */ protected transient volatile boolean destroyed; /** * Set the job name. Used by subclasses to set the job name. * * @param name The name of the job. */ synchronized public void setName(String name) { if (destroyed) { throw new IllegalStateException("[" + this + "] destroyed"); } this.name = name; } /** * Get the job name. * * @return The job name. */ synchronized public String getName() { return name; } /** * Add a child. * * @oddjob.property jobs * @oddjob.description The jobs. * @oddjob.required No. * * @param child A child */ public void setJobs(int index, Object child) { if (child == null) { childHelper.removeChildAt(index); } else { childHelper.insertChild(index, child); } } /** * Add a listener. The listener will immediately recieve add * notifications for all existing children. * * @param listener The listener. */ public void addStructuralListener(StructuralListener listener) { if (destroyed) { throw new IllegalStateException("[" + this + "] destroyed"); } childHelper.addStructuralListener(listener); } /** * Remove a listener. * * @param listener The listner. */ public void removeStructuralListener(StructuralListener listener) { childHelper.removeStructuralListener(listener); } /** * Override toString. */ public String toString() { if (name == null) { return getClass().getSimpleName(); } else { return name; } } /** * Return an icon tip for a given id. Part * of the Iconic interface. */ public ImageIcon iconForId(String iconId) { return icon; } /** * Add an icon listener. Part of the Iconic * interface. * * @param listener The listener. */ public void addIconListener(IconListener listener) { if (destroyed) { throw new IllegalStateException("[" + this + "] destroyed"); } listener.iconEvent(new IconEvent(this, "folder")); } /** * Remove an icon listener. Part of the Iconic * interface. * * @param listener The listener. */ public void removeIconListener(IconListener listener) { } public void initialised() { } public void configured() { } /** * Destroy this component. */ public void destroy() { if (destroyed) { throw new IllegalStateException("[" + this + "] destroyed"); } try { childHelper.stopChildren(); } catch (FailedToStopException e) { logger.warn(e); } destroyed = true; } }