001/*
002 * Copyright (c) 2010-2011 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-05-09 11:05:40 -0700 (Wed, 09 May 2012) $' 
007 * '$Revision: 29823 $'
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.util;
031
032import java.io.Reader;
033import java.io.StringReader;
034import java.text.SimpleDateFormat;
035import java.util.ArrayList;
036import java.util.Date;
037import java.util.Iterator;
038import java.util.List;
039import java.util.Map;
040
041import org.apache.commons.logging.Log;
042import org.apache.commons.logging.LogFactory;
043import org.kepler.kar.KARFile;
044import org.kepler.moml.NamedObjId;
045import org.kepler.objectmanager.ObjectManager;
046import org.kepler.objectmanager.lsid.KeplerLSID;
047import org.kepler.provenance.Queryable;
048import org.kepler.sms.SemanticType;
049
050import ptolemy.kernel.util.NamedObj;
051
052public class WorkflowRunUtil {
053        
054        private static final Log log = LogFactory.getLog(WorkflowRunUtil.class
055                        .getName());
056        
057        public static final String KARENTRY_TYPE = 
058                "karEntry/karEntryAttributes/type";
059        public static final String KARENTRY_PROPERTY = 
060                "karEntry/karEntryXML/property";
061        
062        public static final String KARENTRY_PROPERTY_PROPERTY = 
063                "karEntry/karEntryXML/property/property";
064        
065        public static final String KARENTRY_PROPERTY_PROPERTY_PROPERTY = 
066                        KARENTRY_PROPERTY_PROPERTY + "/property";
067
068        public static final String KARENTRY_PROPERTY_PROPERTY_AT_NAME = 
069                KARENTRY_PROPERTY_PROPERTY + "/@name";
070        public static final String KARENTRY_PROPERTY_NAME = 
071                KARENTRY_PROPERTY_PROPERTY + "/name";
072        public static final String KARENTRY_PROPERTY_AT_VALUE = 
073                KARENTRY_PROPERTY_PROPERTY + "/@value";
074        public static final String KARENTRY_SUBPROPERTY_NAME = 
075                KARENTRY_PROPERTY_PROPERTY + "/property/@name";
076        public static final String KARENTRY_SUBPROPERTY_VALUE = 
077                KARENTRY_PROPERTY_PROPERTY + "/property/@value";
078        
079        public static final String KARENTRY_WORKFLOWRUN_DERIVEDFROM = 
080                KARENTRY_PROPERTY_PROPERTY + "[@name='derivedFrom']/@value";
081        public static final String KARENTRY_WORKFLOWRUN_USER = 
082                KARENTRY_PROPERTY_PROPERTY + "[@name='user']/@value";
083        public static final String KARENTRY_WORKFLOWRUN_WORKFLOWNAME = 
084                KARENTRY_PROPERTY_PROPERTY + "[@name='workflowName']/@value";
085        public static final String KARENTRY_WORKFLOWRUN_WORKFLOWLSID = 
086                KARENTRY_PROPERTY_PROPERTY + "[@name='workflowLSID']/@value";
087        public static final String KARENTRY_WORKFLOWRUN_STARTTIME = 
088                KARENTRY_PROPERTY_PROPERTY + "[@name='startTime']/@value";
089        public static final String KARENTRY_WORKFLOWRUN_DURATION = 
090                KARENTRY_PROPERTY_PROPERTY + "[@name='duration']/@value";
091        public static final String KARENTRY_WORKFLOWRUN_EXECID = 
092                KARENTRY_PROPERTY_PROPERTY + "[@name='execId']/@value";
093        public static final String KARENTRY_WORKFLOWRUN_EXECLSID = 
094                KARENTRY_PROPERTY_PROPERTY + "[@name='execLSID']/@value";
095        public static final String KARENTRY_WORKFLOWRUN_ERRORMESSAGES = 
096                KARENTRY_PROPERTY_PROPERTY + "[@name='errorMessages']/@value";
097        public static final String KARENTRY_WORKFLOWRUN_HOSTID = 
098                KARENTRY_PROPERTY_PROPERTY + "[@name='hostId']/@value";
099        public static final String KARENTRY_WORKFLOWRUN_ANNOTATION = 
100                KARENTRY_PROPERTY_PROPERTY + "[@name='annotation']/@value";
101        public static final String KARENTRY_WORKFLOWRUN_MODULEDEPENDENCIES = 
102                KARENTRY_PROPERTY_PROPERTY + "[@name='moduleDependencies']/@value";
103        public static final String KARENTRY_WORKFLOWRUN_TYPE = 
104                KARENTRY_PROPERTY_PROPERTY + "[@name='type']/@value";
105        public static final String KARENTRY_WORKFLOWRUN_ENTITYID = 
106                KARENTRY_PROPERTY_PROPERTY + "[@name='entityId']/@value";
107        public static final String KARENTRY_WORKFLOWRUN_WORKFLOWTAGS = 
108                KARENTRY_PROPERTY_PROPERTY + "[@name='workflowTags']/@value";
109        // since semanticType attribute can be numbered (semanticType, semanticType2, etc)
110        // match on class instead of name
111        public static final String KARENTRY_WORKFLOWRUN_TAG = 
112                KARENTRY_PROPERTY_PROPERTY + "[@class='"+ SemanticType.class.getName() +"']/@value";
113        //starts-with not supported?
114        //public static final String KARENTRY_WORKFLOWRUN_SEMANTICTYPE = 
115        //      KARENTRY_PROPERTY_PROPERTY + "[starts-with(@name, 'semanticType')]/@value";
116        
117        public static final String KARENTRY_WORKFLOWRUN_SUBPROPERTY_ERROR = 
118                KARENTRY_PROPERTY_PROPERTY + "[@name='errorMessages']/property/@value";
119        //starts-with not supported?
120        //public static final String KARENTRY_WORKFLOWRUN_SUBPROPERTY_ERROR = 
121        //      KARENTRY_PROPERTY_PROPERTY_PROPERTY + "[starts-with(@name, 'error')]/@value";
122        
123        // since semanticType attribute can be numbered (semanticType, semanticType2, etc)
124        // match on class instead of name
125        public static final String KARENTRY_WORKFLOWRUN_SUBPROPERTY_WORKFLOW_TAG = 
126                KARENTRY_PROPERTY_PROPERTY_PROPERTY + "[@class='"+ SemanticType.class.getName() +"']/@value";
127        //starts-with not supported?
128        //public static final String KARENTRY_WORKFLOWRUN_SUBPROPERTY_WORKFLOW_TAG = 
129        //      KARENTRY_PROPERTY_PROPERTY_PROPERTY + "[starts-with(@name, 'semanticType')]/@value";
130                        
131        
132        public static final String KARLSID = "mainAttributes/lsid";
133        public static final String KARFILENAME = "karFileName";
134        public static final String KARFILESIZE = "karFileSize";
135
136        /**
137         * Put run in ObjectManager, removing any previous version.
138         * 
139         * @param run
140         */
141        public static void putInObjectManager(WorkflowRun run) {
142                                
143                ObjectManager om = ObjectManager.getInstance();
144                try 
145                {
146                        NamedObj nObj = ObjectManager.getInstance().getObjectRevision(run.getExecLSID());
147                        if (nObj != null)
148                        {
149                                NamedObjId noi = NamedObjId.getIdAttributeFor(nObj);
150                        
151                                if (noi != null)
152                                {
153                                        if (noi.getId().equals(run.getExecLSID()))
154                                        {
155                                                om.removeObject(noi.getId());
156                                        }
157                                }
158                        }
159                        NamedObjId.assignIdTo(run, run.getExecLSID(), true);
160                        om.addNamedObj(run); //this must come after assignIdTo
161                } 
162                catch (Exception e) 
163                {
164                        e.printStackTrace();
165                }
166        }
167
168
169        public static WorkflowRun lookupWorkflowRun(KeplerLSID workflowRunLSID,
170                        Queryable queryable) throws Exception 
171        {
172
173                // look up the execution (will only be 1)
174                Integer executionId = queryable
175                                .getExecutionForExecutionLSID(workflowRunLSID);
176                
177                if (executionId != null)
178                {
179                        List<KeplerLSID> execLSIDs = new ArrayList<KeplerLSID>();
180                        execLSIDs.add(workflowRunLSID);
181
182                        Map<KeplerLSID, WorkflowRun> runsForExecutions = queryable
183                                .getWorkflowRunsForExecutionLSIDs(execLSIDs);
184                        Iterator<WorkflowRun> runItr = runsForExecutions.values().iterator();
185
186                        if (runItr.hasNext()) 
187                        {
188                                return runItr.next();
189                        }
190                }
191                
192                return null;
193
194        }
195
196        public static String formatDateToISO8601(Date date) 
197        {
198                SimpleDateFormat sdf = new SimpleDateFormat(WorkflowRun.RUN_DATE_FORMAT);
199                String dateStr = sdf.format(date);
200                return dateStr.substring(0, 26) + ":"
201                                + dateStr.substring(26, dateStr.length());
202        }
203
204        public static Date formatStringFromISO8601(String dateStr)
205                        throws Exception 
206        {
207                SimpleDateFormat sdf = new SimpleDateFormat(WorkflowRun.RUN_DATE_FORMAT);
208                try{
209                        String newString = dateStr.substring(0, 26)
210                                + dateStr.substring(27, dateStr.length());
211                        return sdf.parse(newString);
212                }catch(IndexOutOfBoundsException ioobe){
213                        throw new Exception(ioobe);
214                }
215                
216        }
217        
218        /**
219         * Build a query - for all karXmls that contain a WorkflowRun, return 
220         * karFileName, the KAR's lsid, and karFileSize.
221         * @return StringReader containing query
222         * @deprecated
223         */
224        public static Reader buildRunKARQueryDoc() {
225                // we query all KAR namespaces
226                Iterator<String> namespaceItr = KARFile.getKARNamespaces().iterator();
227
228                StringBuffer sb = new StringBuffer();
229                sb.append("<egq:query queryId=\"test.1.1\" system=\"http://knb.ecoinformatics.org\" ");
230                sb.append("xmlns:egq=\"http://ecoinformatics.org/query-1.0.1\" ");
231                sb.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
232                sb.append("xsi:schemaLocation=\"http://ecoinformatics.org/query-1.0.1 ../../src/xsd/query.xsd\">\n");
233
234                while (namespaceItr.hasNext()) {
235                        sb.append("<namespace prefix=\"kepler\">");
236                        sb.append(namespaceItr.next());
237                        sb.append("</namespace>\n");
238                }
239                sb.append("<returnField>" + KARFILENAME + "</returnField>\n");
240                sb.append("<returnField>" + KARLSID + "</returnField>\n");
241                sb.append("<returnField>" + KARFILESIZE + "</returnField>\n");
242                sb.append("<title>kepler query</title>\n");
243                sb.append("<AND>\n");
244                // contains a WorkflowRun
245                sb.append("   <condition operator=\"LIKE\" concept=\"" + KARENTRY_TYPE + "\">"
246                                + WorkflowRun.class.getName() + "</condition>\n");
247                sb.append("</AND>\n");
248                sb.append("</egq:query>\n");
249                log.debug(sb.toString());
250                return new StringReader(sb.toString());
251        }
252                
253        /**
254         * Create query document that for all karXmls that contain a WorkflowRun, 
255         * will return KAR filename, KAR LSID, KAR filesize, karEntry types, 
256         * and a subset of properties that includes all WorkflowRun properties.
257         * @return Reader containing aforementioned query document.
258         */
259        public static Reader buildWorkflowRunPiecesQueryDoc() {
260                                
261                // we query all KAR namespaces
262                Iterator<String> namespaceItr = KARFile.getKARNamespaces().iterator();
263
264                StringBuffer sb = new StringBuffer();
265                sb.append("<egq:query queryId=\"test.1.1\" system=\"http://knb.ecoinformatics.org\" ");
266                sb.append("xmlns:egq=\"http://ecoinformatics.org/query-1.0.1\" ");
267                sb.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
268                sb.append("xsi:schemaLocation=\"http://ecoinformatics.org/query-1.0.1 ../../src/xsd/query.xsd\">\n");
269                // sb.append("<namespace prefix=\"kepler\">kar</namespace>\n");
270
271                while (namespaceItr.hasNext()) {
272                        sb.append("<namespace prefix=\"kepler\">");
273                        sb.append(namespaceItr.next());
274                        sb.append("</namespace>\n");
275                }
276                sb.append("<returnField>" + KARFILENAME + "</returnField>\n");
277                sb.append("<returnField>" + KARLSID + "</returnField>\n");
278                sb.append("<returnField>" + KARFILESIZE + "</returnField>\n");
279                sb.append("<returnField>" + KARENTRY_TYPE + "</returnField>\n");
280                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_DERIVEDFROM + "</returnField>\n");
281                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_USER + "</returnField>\n");
282                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_WORKFLOWNAME + "</returnField>\n");
283                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_WORKFLOWLSID + "</returnField>\n");
284                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_STARTTIME + "</returnField>\n");
285                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_DURATION + "</returnField>\n");
286                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_EXECID + "</returnField>\n");
287                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_EXECLSID + "</returnField>\n");
288                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_ERRORMESSAGES + "</returnField>\n");
289                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_SUBPROPERTY_ERROR + "</returnField>\n");
290                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_HOSTID + "</returnField>\n");
291                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_ANNOTATION + "</returnField>\n");
292                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_MODULEDEPENDENCIES + "</returnField>\n");
293                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_TYPE + "</returnField>\n");
294                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_ENTITYID + "</returnField>\n");
295                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_WORKFLOWTAGS + "</returnField>\n");
296                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_SUBPROPERTY_WORKFLOW_TAG + "</returnField>\n");
297                sb.append("<returnField>" + KARENTRY_WORKFLOWRUN_TAG + "</returnField>\n");
298                
299                sb.append("<title>kepler query</title>\n");
300                sb.append("<AND>\n");
301                // contains a WorkflowRun
302                sb.append("   <condition operator=\"LIKE\" concept=\"" + KARENTRY_TYPE + "\">" +
303                                 WorkflowRun.class.getName() + "</condition>\n");
304                sb.append("</AND>\n");
305                sb.append("</egq:query>\n");
306                log.debug(sb.toString());
307                return new StringReader(sb.toString());
308        }
309        
310        /**
311         * Build a query - get docIds for all karXmls that contain a WorkflowRun 
312         * @return StringReader
313         * @deprecated unused.
314         */
315        public static Reader buildWorkflowRunQueryDocO() {
316                // we query all KAR namespaces
317                Iterator<String> namespaceItr = KARFile.getKARNamespaces().iterator();
318
319                StringBuffer sb = new StringBuffer();
320                sb.append("<egq:query queryId=\"test.1.1\" system=\"http://knb.ecoinformatics.org\" ");
321                sb.append("xmlns:egq=\"http://ecoinformatics.org/query-1.0.1\" ");
322                sb.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
323                sb.append("xsi:schemaLocation=\"http://ecoinformatics.org/query-1.0.1 ../../src/xsd/query.xsd\">\n");
324
325                while (namespaceItr.hasNext()) {
326                        sb.append("<namespace prefix=\"kepler\">");
327                        sb.append(namespaceItr.next());
328                        sb.append("</namespace>\n");
329                }
330                sb.append("<returnField>/entity/@name</returnField>\n");
331                sb.append("<title>kepler query</title>\n");
332                sb.append("<AND>\n");
333                // contains a WorkflowRun
334                sb.append("   <condition operator=\"LIKE\" concept=\"" + KARENTRY_TYPE + "\">"
335                                + WorkflowRun.class.getName() + "</condition>\n");
336                sb.append("</AND>\n");
337                sb.append("</egq:query>\n");
338                log.debug(sb.toString());
339                return new StringReader(sb.toString());
340        }
341
342}