001/**
002 *     '$Author: crawl $'
003 *       '$Date: 2012-11-26 22:23:27 +0000 (Mon, 26 Nov 2012) $'
004 *   '$Revision: 31127 $'
005 *
006 *  For Details:
007 *  http://www.kepler-project.org
008 *
009 *  Copyright (c) 2009-2010 The Regents of the
010 *  University of California. All rights reserved. Permission is hereby granted,
011 *  without written agreement and without license or royalty fees, to use, copy,
012 *  modify, and distribute this software and its documentation for any purpose,
013 *  provided that the above copyright notice and the following two paragraphs
014 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
015 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
016 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
017 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
018 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
019 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
020 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
021 *  SOFTWARE 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
026package org.kepler.kar;
027
028import java.io.File;
029import java.util.ArrayList;
030import java.util.List;
031import java.util.ListIterator;
032
033import org.kepler.moml.NamedObjId;
034import org.kepler.objectmanager.ObjectManager;
035import org.kepler.objectmanager.cache.LocalRepositoryManager;
036import org.kepler.objectmanager.library.LibraryManager;
037import org.kepler.objectmanager.lsid.KeplerLSID;
038import org.kepler.provenance.Queryable;
039import org.kepler.util.ProvenanceStore;
040import org.kepler.util.WorkflowRun;
041import org.kepler.util.WorkflowRunUtil;
042import org.kepler.workflowrunmanager.WRMDefaults;
043import org.kepler.workflowrunmanager.WorkflowRunManager;
044import org.kepler.workflowrunmanager.WorkflowRunManagerManager;
045
046import ptolemy.actor.CompositeActor;
047import ptolemy.kernel.ComponentEntity;
048import ptolemy.kernel.util.IllegalActionException;
049import ptolemy.kernel.util.NamedObj;
050import ptolemy.moml.MoMLParser;
051
052
053/**
054 * This class allows for exporting runs to a KAR 
055 * without user interaction
056 * 
057 */
058public class ExportRunsToKAR
059{       
060
061        private Queryable _queryable = null;
062        
063        /**
064         * The SaveKAR object is a GUI free helper class for saving KARs.
065         */
066        protected SaveKAR _savekar = null;
067        
068        private KeplerLSID _workflowLSID = null;
069        
070        private WorkflowRunManager workflowRunManager = null;
071
072        /**
073         * Constructor
074         */     
075        public ExportRunsToKAR(Queryable q, KeplerLSID wfLSID){
076                _queryable = q;
077                _savekar = new SaveKAR();
078                _workflowLSID = wfLSID;
079
080                try {
081                        
082                        // FIXME this should use the proper prov store instead of just the default
083                        // we're only ok with this currently because ExportRunsToKAR is only used 
084                        // in headless, which currently only supports using the default store
085                        WorkflowRunManagerManager wrmm = WorkflowRunManagerManager.getInstance();
086                        ProvenanceStore provenanceStore = new ProvenanceStore(WRMDefaults.provenanceDefaultsProperty);
087                        workflowRunManager = wrmm.getWRM(null, provenanceStore);
088                        
089                        workflowRunManager.connect();
090                        ArrayList<WorkflowRun> runs = 
091                                workflowRunManager.queryForAndSetRuns("%", "%", "%", "%", "%", "%", false);
092                        if (runs.isEmpty()){
093                                System.out.println("WARN ExportRunsToKAR got no runs back from provenance!");
094                        }
095                } catch (Exception e) {
096                        // TODO Auto-generated catch block
097                        e.printStackTrace();
098                }
099        }
100
101
102        /**
103         * Export a list of runs and their associated workflow MoML into a KAR.
104         * 
105         * @param runLSIDs
106         * @param karFile
107         * @param addToLibraryAndCache
108         * @param overrideKARModuleDependencies - if true, use run's mod deps for kar's mod deps
109         * @return success
110         * @throws Exception 
111         */
112        public boolean exportRunsToKAR(List<KeplerLSID> runLSIDs, 
113                        File karFile, boolean addToLibraryAndCache, boolean overrideKARModuleDependencies) throws Exception{
114                
115                String runModDeps = null;
116                String lastRunModDeps = null;
117                
118                // first clear any runs previously added to the "selected" list:
119                workflowRunManager.clearSelectedRuns();
120
121                int i=0;
122                for (KeplerLSID runLSID : runLSIDs) {
123                        try {
124                                // Here we store the Run LSID in the workflowRunManager
125                                // so the WorkflowRunEntryHandler can figure out which runs for which
126                                // workflows to save
127                                        
128                                workflowRunManager.addRunToSelectedRuns(runLSID);
129                                
130                                WorkflowRun wr = workflowRunManager.getRun(runLSID);
131                                runModDeps = wr.getModuleDependencies();
132                                // if overriding KAR module dependencies, make sure all runs have same module dependencies
133                                if (overrideKARModuleDependencies && i != 0 && !lastRunModDeps.equals(runModDeps)){
134                                        System.out.println("ExportRunsToKAR exportRunsToKAR ERROR trying to override KAR module " +
135                                                "dependencies but runs have different module dependencies, this " +
136                                                "is not currently allowed, NOT creating KAR file!");
137                                        return false;
138                                }
139                                
140                                lastRunModDeps = runModDeps;
141                                i++;
142                        } catch (Exception exc) {
143                                exc.printStackTrace();
144                        }
145                }
146                
147                
148                ArrayList<NamedObj> namedObjs = prepareNamedObjs(runLSIDs);
149            
150                KARBuilder karBuilder = new KARBuilder();
151                karBuilder.setKarFile(karFile);
152                _savekar.setFile(karFile);
153
154            try{
155                for (NamedObj no : namedObjs) {
156                        if (no instanceof ComponentEntity) {
157                                karBuilder.addSaveInitiator((ComponentEntity)no);
158                        }
159                }
160                karBuilder.setRegisterLSID(false);
161                karBuilder.setRevision(false);
162                
163                //WARNING - using null TableauFrame here
164                karBuilder.generateKAR(null, runModDeps);
165                        _savekar.specifyLSID(karBuilder.getKarLSID());
166                        if (addToLibraryAndCache){
167                                _savekar.saveToCache();
168                        }
169            } 
170            catch (IllegalActionException iae) {
171                System.out.println("Failed to create kar file: "
172                                + iae.getMessage());
173                iae.printStackTrace();
174                return false;
175            }
176            
177            if (addToLibraryAndCache){
178                LibraryManager lm = LibraryManager.getInstance();
179                        LocalRepositoryManager lrm = LocalRepositoryManager.getInstance();
180                        // make sure there's a folder to put it in
181                        if(lrm.isInLocalRepository(_savekar.getFile())){
182                        try {
183                                lm.addKAR(_savekar.getFile());
184                        } 
185                        catch (Exception e2) {
186                                System.out.println("Exception when trying to add kar to library:"+e2);
187                        }
188                        }
189                        else{
190                                //System.out.println("Not adding to library since not kar not in local repo");
191                        }
192                try {
193                        lm.refreshJTrees(); //TODO check will this cause problems in headless kepler?
194                }
195                catch (IllegalActionException e2) {
196                        e2.printStackTrace();
197                }
198            }
199  
200            System.out.println("Successfully exported to kar file: "+karBuilder.getKarFile().toString());
201
202            //queryable.disconnect();
203
204                // now clear any runs added to the "selected" list
205                // in prep for any subsequent saves
206            workflowRunManager.clearSelectedRuns();
207            
208            return true;
209            
210        }
211        
212        
213        /**
214         * 
215         * helper method prepares list of NamedObjs (workflows) for KAR from list of run LSIDs
216         *
217         * @param runLSIDs
218         * @return
219         * @throws Exception
220         */
221        public ArrayList<NamedObj> prepareNamedObjs(List<KeplerLSID> runLSIDs) throws Exception{
222
223                //get workflowRuns for run lsids
224                ListIterator<KeplerLSID> lsidItr = runLSIDs.listIterator();
225                ArrayList<NamedObj> namedObjs = new ArrayList<NamedObj>();
226                ArrayList<KeplerLSID> momlLsids = new ArrayList<KeplerLSID>();
227                
228                while (lsidItr.hasNext()){
229                        KeplerLSID runLSID = lsidItr.next();
230                        
231                        //TODO this section may be unnecessary now
232                        //WorkflowRun wfRun = (WorkflowRun)ObjectManager.getInstance().getHighestObjectRevision(runLSID);
233                        WorkflowRun wfRun = (WorkflowRun)ObjectManager.getInstance().getObjectRevision(runLSID);
234
235                        // make sure we have the run object in the object manager
236                        if (wfRun == null) {
237                                wfRun = WorkflowRunUtil.lookupWorkflowRun(runLSID, _queryable);
238                                ObjectManager.getInstance().addNamedObj(wfRun);
239                        }
240                        //end TODO possibly unnecessary.
241                        
242                        //add moml associated with run
243                        String moml = _queryable.getMoMLForExecution(runLSID);
244                        MoMLParser parser = new MoMLParser();
245                        CompositeActor toplevel = ((CompositeActor) parser.parse(moml));
246                        ObjectManager.getInstance().addNamedObj(toplevel);
247                        KeplerLSID momlLsid = NamedObjId.getIdFor(toplevel);
248                        NamedObjId.assignIdTo(toplevel, momlLsid);
249                        if (!momlLsids.contains(momlLsid)){
250                                namedObjs.add(toplevel);
251                        }
252                        momlLsids.add(momlLsid);
253                }
254                
255                return namedObjs;
256        }
257        
258        
259}