001/* 002 * Copyright (c) 1997-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2012-11-26 22:19:36 +0000 (Mon, 26 Nov 2012) $' 007 * '$Revision: 31113 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.sdm.spa; 031 032import java.awt.Color; 033import java.awt.Container; 034import java.awt.event.ActionEvent; 035import java.awt.event.ActionListener; 036 037import javax.swing.BorderFactory; 038import javax.swing.JButton; 039import javax.swing.JFrame; 040import javax.swing.JPanel; 041import javax.swing.border.LineBorder; 042 043import ptolemy.actor.CompositeActor; 044import ptolemy.actor.Manager; 045import ptolemy.actor.lib.Transformer; 046import ptolemy.data.BooleanToken; 047import ptolemy.data.type.BaseType; 048import ptolemy.kernel.CompositeEntity; 049import ptolemy.kernel.util.IllegalActionException; 050import ptolemy.kernel.util.NameDuplicationException; 051import ptolemy.kernel.util.Nameable; 052import ptolemy.kernel.util.TransientSingletonConfigurableAttribute; 053 054////////////////////////////////////////////////////////////////////////// 055//// Pause 056/** 057 * <p> 058 * This actor is used for putting an expected pause in the workflow 059 * specification to allow for execution to pause until the outputs until that 060 * time are reviewed and the workflow is paused. This actor is mainly useful for 061 * long-running jobs. 062 * </p> 063 * 064 * <p> Implementation of this actor is based on the 065 * ptolemy.actor.lib.Stop actor code by Edward A. Lee. 066 * </p> 067 * 068 * @author Ilkay Altintas, Contributors: Edward A. Lee and Christopher Brooks. 069 * @version $Id: Pause.java 31113 2012-11-26 22:19:36Z crawl $ 070 * @category.name flow control 071 * @category.name local 072 * @entity.description input Input content. Can be any input. They will be 073 * transfered to the next actor once the workflow resumes. 074 **/ 075public class Pause extends Transformer { 076 077 /** 078 * Construct an actor in the specified container with the specified name. 079 * 080 * @param container 081 * The container. 082 * @param name 083 * The name of this actor within the container. 084 * @exception IllegalActionException 085 * If the actor cannot be contained by the proposed 086 * container. 087 * @exception NameDuplicationException 088 * If the name coincides with an actor already in the 089 * container. 090 */ 091 public Pause(CompositeEntity container, String name) 092 throws IllegalActionException, NameDuplicationException { 093 super(container, name); 094 095 input.setMultiport(true); 096 input.setTypeEquals(BaseType.BOOLEAN); 097 output.setTypeEquals(BaseType.STRING); 098 // Icon is a yield sign. 099 _attachText("_iconDescription", "<svg>\n" 100 + "<polygon points=\"0,24 24,-22 -24,-22\" " 101 + "style=\"fill:red\"/>\n" + "<text x=\"-15\" y=\"-8\"" 102 + "style=\"font-size:11; fill:white; font-family:SansSerif\">" 103 + "PAUSE</text>\n" + "</svg>\n"); 104 // Hide the name because the name is in the icon. 105 new TransientSingletonConfigurableAttribute(this, "_hideName"); 106 } 107 108 /////////////////////////////////////////////////////////////////// 109 //// public methods //// 110 111 /** If any of the channels on the input port contain a true token, 112 * the cause postfire() to pause the Manager, display a dialog 113 * with a button to resume execution and send a true token. 114 * @exception IllegalActionException If there is a problem 115 * reading the input channels or sending the token to the output. 116 */ 117 public void fire() throws IllegalActionException { 118 super.fire(); 119 _sawTrueInput = false; 120 if (!input.isOutsideConnected()) { 121 _sawTrueInput = true; 122 } 123 // NOTE: We need to consume data on all channels that have data. 124 // If we don't then DE will go into an infinite loop. 125 for (int i = 0; i < input.getWidth(); i++) { 126 if (input.hasToken(i)) { 127 if (((BooleanToken) input.get(i)).booleanValue()) { 128 _sawTrueInput = true; 129 } 130 } 131 } 132 } 133 134 135 /** If we read a true token, then pause the Manager until the 136 * user presses a button. If nothing at all is connected to the 137 * input port, then pause unconditionaly. 138 * @return the value returned by the postfire() method in the 139 * superclass. Typically, true is returned if the iteration 140 * may continue. If stop was requested, then the superclass 141 * usually returns false. 142 * @exception IllegalActionException If there is no Manager, 143 * if the container is not a CompositeActor or if the 144 * there is some other problem. 145 */ 146 public boolean postfire() throws IllegalActionException { 147 if (_debugging) { 148 _debug("Pause.postfire(): _sawTrueInput: " + _sawTrueInput); 149 } 150 if (_sawTrueInput) { 151 // Create the UI each time we get a true on an input channel. 152 _resumeButton = new JButton("Resume model execution."); 153 _resumeButton.addActionListener(new ActionListener() { 154 public void actionPerformed(ActionEvent e) { 155 if (_debugging) { 156 _debug("Pause.actionPerformed()"); 157 } 158 if (_manager != null) { 159 _debug("Pause.actionPerformed(): resuming manager"); 160 _manager.resume(); 161 } 162 _frame.dispose(); 163 } 164 }); 165 166 _panel = new JPanel(); 167 _panel.add(_resumeButton); 168 169 if (_container == null) { 170 _frame = new JFrame(getFullName()); 171 _frame.getContentPane().add(_panel); 172 _frame.setSize(200, 250); 173 } else { 174 _container.add(_panel); 175 _panel.setBackground(null); 176 _panel.setBorder(new LineBorder(Color.black)); 177 } 178 _panel.setBorder(BorderFactory 179 .createTitledBorder("The border title goes here...")); 180 181 if (_frame != null) { 182 _frame.setVisible(true); 183 } 184 185 Nameable container = getContainer(); 186 if (container instanceof CompositeActor) { 187 _manager = ((CompositeActor) container).getManager(); 188 if (_manager != null) { 189 if (_debugging) { 190 _debug("Pause.postfire(): pausing Manager()"); 191 } 192 _manager.pause(); 193 } else { 194 throw new IllegalActionException(this, 195 "Cannot pause without a Manager."); 196 } 197 } else { 198 throw new IllegalActionException(this, 199 "Cannot pause without a container that is a CompositeActor."); 200 } 201 } 202 if (_debugging) { 203 _debug("Pause.postfire(): _sawTrueInput: " + _sawTrueInput); 204 } 205 206 // It is safer to do output in postfire() in case this method 207 // is inside a Continuous director. 208 output.send(0, new BooleanToken(_sawTrueInput)); 209 return super.postfire(); 210 } 211 212 /** Dispose the frame of the button dialog. 213 * @exception IllegalActionException Not thrown in this base class. 214 */ 215 public void wrapup() throws IllegalActionException { 216 if (_frame != null) { 217 _frame.dispose(); 218 } 219 } 220 221 /////////////////////////////////////////////////////////////////// 222 //// protected variables //// 223 224 protected JPanel _panel; 225 226 /////////////////////////////////////////////////////////////////// 227 //// private variables //// 228 229 private Container _container; 230 231 /** The frame into which to put the button, if any. */ 232 private JFrame _frame; 233 234 private Manager _manager; 235 236 private JButton _resumeButton; 237 238 private boolean _sawTrueInput; 239}