001/* A notification exception used only to terminate a process.
002
003 Copyright (c) 1997-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor.process;
029
030import ptolemy.kernel.util.Nameable;
031
032///////////////////////////////////////////////////////////////////
033//// TerminateProcessException
034
035/**
036 This exception is thrown to terminate a process. This is only a
037 notification exception that a ProcessDirector uses to terminate all the
038 processes gracefully. It is not an exception that indicates an error in
039 the code or model.
040 <p>
041 In the process domains (PN and CSP for example), a simulation is
042 terminated only when a deadlock is detected. During a deadlock, the
043 threads corresponding to actors are normally blocked on a method call to
044 the receiver. This exception is normally thrown from these methods, so
045 that the threads can return from the call and terminate themselves.
046 <p>
047 This class is a standalone class and not derived from the Ptolemy
048 Runtime exceptions as those exceptions indicate an error in the model,
049 while this exception is used for passing of information to the threads.
050
051 @author Neil Smyth, Mudit Goel
052 @version $Id$
053 @since Ptolemy II 0.2
054 @Pt.ProposedRating Green (mudit)
055 @Pt.AcceptedRating Yellow (mudit)
056 */
057@SuppressWarnings("serial")
058public class TerminateProcessException extends RuntimeException {
059    // NOTE: This class has much duplicated code with KernelException,
060    // but because it needs to be a RuntimeException, there seemed to
061    // be no way to avoid this.  Should there be an interface defined
062    // for the commonality?
063
064    /** Constructs an Exception with only a detail message.
065     *  @param detail The message.
066     */
067    public TerminateProcessException(String detail) {
068        this(null, null, detail);
069    }
070
071    /** Constructs an Exception with a detail message that includes the
072     *  name of the first argument and the second argument string.
073     *  @param object The object.
074     *  @param detail The message.
075     */
076    public TerminateProcessException(Nameable object, String detail) {
077        this(object, null, detail);
078    }
079
080    /** Constructs an Exception with a detail message that includes the
081     *  names of the first two arguments plus the third argument string.
082     *  @param object1 The first object.
083     *  @param object2 The second object.
084     *  @param detail The message.
085     */
086    public TerminateProcessException(Nameable object1, Nameable object2,
087            String detail) {
088        String object1String = _getFullName(object1);
089        String object2String = _getFullName(object2);
090        String prefix;
091
092        if (!object1String.equals("")) {
093            if (!object2String.equals("")) {
094                prefix = object1String + " and " + object2String;
095            } else {
096                prefix = object1String;
097            }
098        } else {
099            prefix = object2String;
100        }
101
102        _setMessage(prefix);
103
104        if (detail != null) {
105            if (!detail.equals("")) {
106                if (!prefix.equals("")) {
107                    _setMessage(prefix + ": " + detail);
108                } else {
109                    _setMessage(detail);
110                }
111            }
112        }
113    }
114
115    ///////////////////////////////////////////////////////////////////
116    ////                         public methods                    ////
117
118    /** Get the detail message. */
119    @Override
120    public String getMessage() {
121        return _message;
122    }
123
124    ///////////////////////////////////////////////////////////////////
125    ////                         protected methods                 ////
126
127    /** Get the name of a Nameable object.  This method attempts to use
128     *  getFullName(), if it is defined, and resorts to getName() if it is
129     *  not.  If the argument is a null reference, return an empty string.
130     *  @param object An object with a full name.
131     *  @return The full name of the argument.
132     */
133    protected String _getFullName(Nameable object) {
134        String name;
135
136        if (object == null) {
137            return "";
138        } else {
139            try {
140                name = object.getFullName();
141            } catch (TerminateProcessException ex) {
142                name = object.getName();
143            }
144        }
145
146        return name;
147    }
148
149    /** Get the name of a Nameable object.
150     *  If the argument is a null reference, return an empty string.
151     *  @param object An object with a name.
152     *  @return The name of the argument.
153     */
154    protected String _getName(Nameable object) {
155        String name;
156
157        if (object == null) {
158            return "";
159        } else {
160            name = object.getName();
161
162            if (name.equals("")) {
163                name = "<Unnamed Object>";
164            }
165        }
166
167        return name;
168    }
169
170    /** Sets the error message to the specified string.
171     *  @param message The message.
172     */
173    protected void _setMessage(String message) {
174        _message = message;
175    }
176
177    ///////////////////////////////////////////////////////////////////
178    ////                         private variables                 ////
179    // The detail message.
180    private String _message;
181}