001/*
002 * Copyright (c) 2007-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-11-26 22:22:25 +0000 (Mon, 26 Nov 2012) $' 
007 * '$Revision: 31122 $'
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.kepler.gui;
031
032import java.awt.Component;
033import java.awt.event.ActionEvent;
034import java.lang.reflect.Method;
035import java.util.Set;
036import java.util.Vector;
037
038import javax.swing.tree.TreePath;
039
040import org.kepler.kar.KARCacheContent;
041import org.kepler.kar.KARCacheManager;
042import org.kepler.kar.KarDoclet;
043import org.kepler.kar.SuperClassPathFinderDoclet;
044import org.kepler.objectmanager.ActorMetadata;
045import org.kepler.objectmanager.ObjectManager;
046import org.kepler.objectmanager.cache.ActorCacheObject;
047import org.kepler.objectmanager.cache.CacheManager;
048import org.kepler.objectmanager.cache.CacheObject;
049import org.kepler.objectmanager.lsid.KeplerLSID;
050
051import ptolemy.actor.gui.Configuration;
052import ptolemy.actor.gui.Effigy;
053import ptolemy.actor.gui.PtolemyFrame;
054import ptolemy.actor.gui.TableauFrame;
055import ptolemy.kernel.util.ConfigurableAttribute;
056import ptolemy.kernel.util.NamedObj;
057import ptolemy.util.MessageHandler;
058import ptolemy.vergil.actor.DocEffigy;
059import ptolemy.vergil.basic.GetDocumentationAction;
060import ptolemy.vergil.basic.KeplerDocumentationAttribute;
061import ptolemy.vergil.toolbox.FigureAction;
062
063
064/**
065 * This action displays Kepler documentation. Created to display when actor in
066 * library tree is right clicked.
067 * 
068 *@author Chad Berkley
069 *@since 6/5/2007
070 */
071public class ShowDocumentationAction extends FigureAction {
072        private final static String LABEL = "View Documentation";
073        private TableauFrame parent = null;
074        private PtolemyFrame pFrame = null;
075        private KeplerLSID _lsidToView = null;
076        private TreePath _path;
077
078        /**
079         * Constructor
080         * 
081         *@param path
082         *            the TreePath where the actor is being removed.
083         */
084        public ShowDocumentationAction(TreePath path, Component parent) {
085                super(LABEL);
086                _path = path;
087        }
088    
089    public ShowDocumentationAction(TableauFrame parent) {
090        super("");
091        if (parent == null) {
092            IllegalArgumentException iae = new IllegalArgumentException(
093                    "ShowDocumentationAction constructor received NULL argument for TableauFrame");
094            iae.fillInStackTrace();
095            throw iae;
096        }
097        this.parent = parent;    
098    }
099        
100        public void setLsidToView(KeplerLSID lsid) {
101                _lsidToView = lsid;
102        }
103        public KeplerLSID getLsidToView() {
104                return _lsidToView;
105        }
106
107        /**
108         * Invoked when an action occurs.
109         * 
110         *@param e
111         *            ActionEvent
112         */
113        public void actionPerformed(ActionEvent e) {
114                super.actionPerformed(e);
115                NamedObj target = null;
116                KeplerLSID lsidToView = getLsidToView();
117                
118                try {
119                        
120                        if (lsidToView != null) {
121                                target = ObjectManager.getInstance().getObjectRevision(lsidToView);
122                        } else {
123                                target = getTarget();
124                        }       
125                        
126                        if(target == null) {
127                            Object object = _path.getLastPathComponent();
128                            if(object instanceof NamedObj) {
129                                target = (NamedObj) object;
130                            }
131                        }
132                        
133                        
134                        NamedObj container = null;
135                        if (pFrame != null){
136                                container = pFrame.getModel();
137                        }
138                        
139                        if (container == null) {
140                                container = target.getContainer();
141                        }
142                        
143                        Effigy ee = Configuration.findEffigy(container);
144                        Configuration c = null;
145                        
146                        if (ee != null){
147                                c = (Configuration) ee.toplevel();
148                        }
149                        else{
150                                if (parent != null){
151                                        c = parent.getConfiguration();
152                                }
153                        }       
154                        GetDocumentationAction gda = new GetDocumentationAction(1);
155                        gda.setConfiguration(c);
156                        DocEffigy de = null;
157                        if (ee != null){
158                                try {
159                                        de = new DocEffigy(ee, ee.uniqueName("DocEffigy"));
160                                        gda.setEffigy(de);
161                                } catch (Exception exc) {
162                                        exc.printStackTrace();
163                                }
164                        }
165                        if (target != null) {
166
167                                boolean missingDocs = false;
168                                
169                        final KeplerDocumentationAttribute keplerDocumentationAttribute = (KeplerDocumentationAttribute) target
170                                .getAttribute("KeplerDocumentation");
171                        
172                        // see if the docs are missing or empty
173                        if(keplerDocumentationAttribute == null) {
174                                System.out.println("No KeplerDocumentation attribute.");
175                                missingDocs = true;
176                        } else {
177                                ConfigurableAttribute userLevelDoc = 
178                                                (ConfigurableAttribute) keplerDocumentationAttribute.getAttribute("userLevelDocumentation");
179                                if(userLevelDoc == null) {
180                                        System.out.println("No userLevelDocumentation attribute.");
181                                        missingDocs = true;
182                                } else {
183                                        String uldStr = userLevelDoc.getConfigureText();
184                                        if(uldStr == null || uldStr.trim().isEmpty() || uldStr.trim().equals("null")) {
185                                                System.out.println("UserLevelDocumentation appears to be empty.");
186                                                missingDocs = true;
187                                        }
188                                }
189                        }
190                        
191                        if(missingDocs) {
192                                
193                                System.out.println("Missing documentation for " + target.getFullName());
194                                System.out.println("Will try to generate from javadocs.");
195                                
196                                // see if we have javadoc api
197                                
198                                Method javadocMethod = null;
199                                try {
200                                        Class<?> clazz = Class.forName("com.sun.tools.javadoc.Main");
201                                        javadocMethod = clazz.getMethod("execute", String[].class);
202                                } catch(Exception e1) {
203                                        System.err.println("ERROR: javadoc API not in class path.");
204                                }
205                                
206                                if(javadocMethod != null) {
207                                        
208                                        final String fileName = SuperClassPathFinderDoclet.getFileNameForClassName(target.getClassName());
209                                        if(fileName == null) {
210                                                System.err.println("ERROR: unable to get file name for class " + target.getClassName());
211                                        } else {
212                                                
213                                                    // find parent files for this class
214                                                javadocMethod.invoke(null, new Object[]{ new String[] {
215                                                            "-quiet",
216                                                            "-doclet",
217                                                            "org.kepler.kar.SuperClassPathFinderDoclet", fileName }});
218                                            
219                                                    final String className = SuperClassPathFinderDoclet.getClassName();
220                                                    final Set<String> classFiles = SuperClassPathFinderDoclet.getClassFiles();
221                                            
222                                                    if(classFiles.isEmpty()) {
223                                                        System.out.println("ERROR: could not find files of super classes of " + fileName);
224                                                    } else {
225                
226                                                            // construct documentation for the class using its source file, and
227                                                            // those of its super classes
228                                                            final String[] args = new String[3 + classFiles.size()];
229                                                            args[0] = "-quiet";
230                                                            args[1] = "-doclet";
231                                                            args[2] = "org.kepler.kar.KarDoclet";
232                                                            int j = 3;
233                                                            for(String filename : classFiles) {
234                                                                args[j] = filename;
235                                                                j++;
236                                                            }
237                                                            
238                                                            javadocMethod.invoke(null, new Object[]{args});
239                                                                
240                                                                // replace the kepler documentation attribute with the generated one
241                                                final KeplerDocumentationAttribute docletDocAttribute = KarDoclet.getDoc(className);
242                                                target.removeAttribute(keplerDocumentationAttribute);
243                                                ((KeplerDocumentationAttribute) docletDocAttribute.clone(target.workspace())).setContainer(target);
244                                                missingDocs = false;
245                                                    }   
246                                            }
247                                }
248                        }
249                        
250                        // see if docs are still missing
251                        if(missingDocs) {
252                                
253                                System.out.println("Will try to load from Kepler cache.");
254                                
255                                // try to load from cache
256                            final KARCacheManager kcm = KARCacheManager.getInstance();
257                            final Vector<KARCacheContent> list = kcm.getKARCacheContents();
258
259                            final String targetClassName = target.getClassName();
260                                for(KARCacheContent content : list) {
261                                    String cacheClassName = content.getCacheContent().getClassName();
262                                    
263                                    // make sure class name is not null.
264                                    // it's null for, e.g., workflow runs and report layouts
265                                    if(cacheClassName != null) {
266
267                                        if(cacheClassName.equals(targetClassName)) {
268
269                                                        KeplerLSID lsid = content.getLsid(); 
270                                                        if(lsid != null) {
271                                                                        CacheObject cacheObject = CacheManager.getInstance().getHighestCacheObjectRevision(lsid);
272                                                                        if(cacheObject != null && (cacheObject instanceof ActorCacheObject)) {
273                                                                                ActorMetadata metadata = ((ActorCacheObject)cacheObject).getMetadata();
274                                                                                if(metadata != null) {
275                                                                                        final KeplerDocumentationAttribute cacheDocAttribute = metadata.getDocumentationAttribute();
276                                                                                        if(cacheDocAttribute != null) {
277                                                                                                target.removeAttribute(keplerDocumentationAttribute);
278                                                                                                ((KeplerDocumentationAttribute) cacheDocAttribute.clone(target.workspace())).setContainer(target);
279                                                                                                missingDocs = false;
280                                                                                        }
281                                                                                }
282                                                                        }
283                                                        }
284                                                        break;
285                                        }
286                                    }
287                                }
288                        }
289                                
290                        if(!missingDocs) {
291                            gda.showDocumentation(target);
292                        } else {
293                            MessageHandler.error("Could not find documentation for " + target.getName() +
294                                ". To generate documentation, download Kepler from svn and run 'ant update-actor-doc'.");
295                        }
296                        }
297                } catch (Exception ee) {
298                        ee.printStackTrace();
299                }
300        }
301
302        /**
303         * allows you to set the ptolemyFrame that should be used as the parent of
304         * this action.
305         */
306        public void setPtolemyFrame(PtolemyFrame pFrame) {
307                this.pFrame = pFrame;
308        }
309}