001/* Singleton class for displaying exceptions, errors, warnings, and messages that 002includes a button to open the actor that caused the problem 003 004 Copyright (c) 2010-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 */ 028package ptolemy.actor.gui; 029 030import java.util.Iterator; 031 032import ptolemy.gui.GraphicalMessageHandler; 033import ptolemy.kernel.CompositeEntity; 034import ptolemy.kernel.util.InternalErrorException; 035import ptolemy.kernel.util.KernelException; 036import ptolemy.kernel.util.KernelRuntimeException; 037import ptolemy.kernel.util.Nameable; 038import ptolemy.kernel.util.NamedObj; 039 040/////////////////////////////////////////////////////////////////// 041//// GraphicalMessageHandler 042 043/** 044 A message handler that optionally includes a button that opens the model 045 that contains the actor that caused the exception. 046 047 @author Christopher Brooks 048 @version $Id$ 049 @since Ptolemy II 10.0 050 @Pt.ProposedRating Red (cxh) 051 @Pt.AcceptedRating Red (cxh) 052 */ 053public class ActorGraphicalMessageHandler extends GraphicalMessageHandler { 054 055 /** Under certain circumstances, add a "Go To Actor" button to the 056 * options array. The button is added to the array if the 057 * throwable is a KernelException or a KernelRuntimeException 058 * with a non-null Nameable and the Nameable is not at the 059 * toplevel. 060 * @param options An array of Strings, suitable for passing to 061 * JOptionPane.showOptionDialog(). 062 * @param throwable The throwable. 063 * @return An array of Strings. If the throwable is an instance 064 * of KernelException and non-null, then the String "Go To Actor" 065 * is added to the array as the last element. Otherwise, the 066 * options argument is returned. 067 */ 068 @Override 069 protected Object[] _checkThrowableNameable(Object[] options, 070 Throwable throwable) { 071 072 Object[] result = options; 073 Nameable nameable1 = _getNameable(throwable); 074 // If the throwable has a Nameable, and is not the top level, 075 // then add a button 076 if (nameable1 != null && nameable1 instanceof NamedObj 077 && ((NamedObj) nameable1).toplevel() != nameable1) { 078 result = new Object[options.length + 1]; 079 System.arraycopy(options, 0, result, 0, options.length); 080 result[options.length] = "Go To Actor"; 081 } 082 return result; 083 } 084 085 /** Given a throwable, return the first Nameable (if any). 086 * @param throwable The throwable that may or may not 087 * be an instance of KernelException or KernelRuntimeException. 088 * @return The first Nameable or null if the throwable 089 * is not a KernelException or KernelRuntimeException. 090 */ 091 protected Nameable _getNameable(Throwable throwable) { 092 Nameable nameable1 = null; 093 if (throwable instanceof KernelException) { 094 nameable1 = ((KernelException) throwable).getNameable1(); 095 } else if (throwable instanceof KernelRuntimeException) { 096 Iterator nameables = ((KernelRuntimeException) throwable) 097 .getNameables().iterator(); 098 while (nameables.hasNext()) { 099 Object object = nameables.next(); 100 if (object instanceof NamedObj) { 101 nameable1 = (NamedObj) object; 102 break; 103 } 104 } 105 106 } 107 return nameable1; 108 } 109 110 /** Open the level of hierarchy of the model that contains the 111 * Nameable referred to by the KernelException or KernelRuntimeException. 112 * @param throwable The throwable that may be a KernelException 113 * or KernelRuntimeException. 114 */ 115 @Override 116 protected void _showNameable(Throwable throwable) { 117 Nameable nameable1 = _getNameable(throwable); 118 if (nameable1 != null) { 119 Effigy effigy = Configuration 120 .findEffigy(((NamedObj) nameable1).toplevel()); 121 Configuration configuration = (Configuration) effigy.toplevel(); 122 try { 123 Nameable container = nameable1; 124 while (container != null 125 && !(container instanceof CompositeEntity)) { 126 container = container.getContainer(); 127 } 128 if (container == null) { 129 // Hmm. Could not find container? 130 container = nameable1; 131 } 132 configuration.openModel((NamedObj) container); 133 } catch (KernelException ex) { 134 // FIXME: Could be an endless loop here if 135 // we keep failing to open container. 136 throw new InternalErrorException(nameable1, ex, 137 "Could not open " + nameable1.getFullName()); 138 } 139 return; 140 } 141 142 message("Internal Error: The throwable \"" + throwable 143 + "\" is not a KernelException or KernelRuntimeException?"); 144 } 145}