001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: barseghian $'
006 * '$Date: 2013-01-29 22:20:09 +0000 (Tue, 29 Jan 2013) $' 
007 * '$Revision: 31384 $'
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
030/* A class containing workflow execution metadata. */
031
032/**
033 *  '$Author: barseghian $'
034 *  '$Date: 2013-01-29 22:20:09 +0000 (Tue, 29 Jan 2013) $'
035 *  '$Revision: 31384 $'
036 *
037 *  For Details:
038 *  http://www.kepler-project.org
039 *
040 *  Copyright (c) 2009-2010 The Regents of the
041 *  University of California. All rights reserved. Permission is hereby granted,
042 *  without written agreement and without license or royalty fees, to use, copy,
043 *  modify, and distribute this software and its documentation for any purpose,
044 *  provided that the above copyright notice and the following two paragraphs
045 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
046 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
047 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
048 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
049 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
050 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
051 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
052 *  SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
053 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
054 *  ENHANCEMENTS, OR MODIFICATIONS.
055 */
056
057package org.kepler.util;
058
059import java.util.ArrayList;
060import java.util.Collections;
061import java.util.Comparator;
062import java.util.Date;
063import java.util.Iterator;
064import java.util.LinkedHashMap;
065import java.util.List;
066import java.util.Map;
067import java.util.Set;
068import java.util.Vector;
069
070import org.apache.commons.logging.Log;
071import org.apache.commons.logging.LogFactory;
072import org.kepler.moml.NamedObjId;
073import org.kepler.moml.NamedObjIdReferralList;
074import org.kepler.objectmanager.ObjectManager;
075import org.kepler.objectmanager.lsid.KeplerLSID;
076import org.kepler.provenance.Recording;
077import org.kepler.provenance.sql.SQLRecordingV8;
078import org.kepler.sms.NamedOntClass;
079import org.kepler.sms.SMSServices;
080import org.kepler.sms.SemanticType;
081
082import ptolemy.kernel.util.Attribute;
083import ptolemy.kernel.util.IllegalActionException;
084import ptolemy.kernel.util.NameDuplicationException;
085import ptolemy.kernel.util.NamedObj;
086import ptolemy.kernel.util.StringAttribute;
087import ptolemy.kernel.util.Workspace;
088
089/**
090 * A class containing workflow execution metadata.
091 * 
092 * @author
093 * @version $Id: WorkflowRun.java 31384 2013-01-29 22:20:09Z barseghian $
094 */
095public class WorkflowRun extends NamedObj {
096
097        public static final Log log = LogFactory.getLog(WorkflowRun.class);
098        private static final boolean isDebugging = log.isDebugEnabled();
099
100        // change if classname changes:
101        private static String WORKFLOW_RUN = "WorkflowRun";
102
103        public enum RunAttribute {
104                
105                // NOTE: if another attribute that keeps a date is added, 
106                // the logic that determines field order in 
107                // ProvenanceStore.downloadAllWorkflowRuns will have to change.
108                
109                WORKFLOWTAGS("workflowTags"),
110                DURATION("duration"),
111                STARTTIME("startTime"),
112                USER("user"),
113                WORKFLOWLSID("workflowLSID"),
114                WORKFLOWNAME("workflowName"),
115                EXECID("execId"),
116                EXECLSID("execLSID"),
117                ERRORMESSAGES("errorMessages"),
118                HOSTID("hostId"),
119                ANNOTATION("annotation"),
120                MODULEDEPENDENCIES("moduleDependencies"),
121                TYPE("type"),
122                // the following attributes are or may also be found in WorkflowRun
123                // note the property name for each semanticType after the first 
124                // includes a number: semanticType, semanticType2, etc.
125                ERROR("error"),
126                SEMANTICTYPE("semanticType"),
127                ENTITYID("entityId"),
128                REFERRALLIST("derivedFrom");
129                
130                /** Construct a new attribute. */
131                RunAttribute(String name) {
132                        _name = name;
133                }
134                
135                /** Get the name. */
136                public String toString() {
137                        return _name;
138                }
139                
140                /** check if attributeName is one specified in enum, or 
141                 *  semanticType\\d* or error\\d* 
142                 */
143                static public boolean isValid(String attributeName){
144                        for (RunAttribute ra: RunAttribute.values()){
145                                if (ra.toString().equals(attributeName) || 
146                                                attributeName.matches(RunAttribute.SEMANTICTYPE.toString()+"\\d*") ||
147                                                attributeName.matches(RunAttribute.ERROR.toString()+"\\d*")){
148                                        return true;
149                                }
150                        }
151                        return false;
152                }
153
154                /** The name of the attribute. */
155                private String _name;
156        }
157                
158        public enum type {
159                Running("running"), 
160                Complete("complete"), 
161                Error("error"), 
162                Imported("imported"),
163                Imported_Error("imported_error"),
164                Unknown("unknown"),
165                // a WorkflowRun from a KAR not yet downloaded
166                Preview("preview"),
167                Preview_Error("preview_error");
168
169
170                /** Construct a new runType. */
171                type(String name) {
172                        _name = name;
173                }
174
175                /** Get the name. */
176                public String toString() {
177                        return _name;
178                }
179
180                /** The name of the type. */
181                private String _name;
182        }
183
184        
185        public static final String TAG_TYPE_WORKFLOW = "workflow";
186        public static final String TAG_TYPE_RUN = "run";
187
188        public static final String FILENAME_EXTENSION = ".xml";
189
190        // runDateFormat is not ISO 8601 until we add missing colon in code.
191        // see formatDateToISO8601(Date)
192        // TODO get official kepler date format from elsewhere
193        public static final String RUN_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
194
195        // override NamedObj default _elementName of entity, so that we can read the
196        // moml back in with momlparser, which seems unhappy with an entity of
197        // WorkflowRun
198        private String _workflowRunElementName = "property";
199
200        public static String WORKFLOWRUN_SELECTED = "WORKFLOWRUN_SELECTED";
201
202        // backwards compatibility type string
203        // KAR version 2.0 uses the binary class name as the type
204        // public static final String TYPE = "workflowRun";
205
206        // constructor to satisfy momlparser
207        // TODO check about workspace...
208        public WorkflowRun(Workspace workspace, String string)
209                        throws IllegalActionException {
210                super(workspace, string);
211
212                _elementName = _workflowRunElementName;
213
214                setExecLSID("");
215                setWorkflowLSID("");
216                setUser("");
217                setWorkflowName("");
218                setStartTime(new Date(0));
219                setDuration(Long.valueOf(0));
220                setExecId(Integer.valueOf(-111));
221                setErrorMessages(null);
222                setHostId("");
223                setAnnotation("");
224                setModuleDependencies(null);
225                setType("");
226                setTags(null);
227
228        }
229
230        public WorkflowRun() throws IllegalActionException {
231                super(WORKFLOW_RUN);
232
233                _elementName = _workflowRunElementName;
234
235                setExecLSID("");
236                setWorkflowLSID("");
237                setUser("");
238                setWorkflowName("");
239                setStartTime(new Date(0));
240                setDuration(Long.valueOf(0));
241                setExecId(Integer.valueOf(-111));
242                setErrorMessages(null);
243                setHostId("");
244                setAnnotation("");
245                setModuleDependencies(null);
246                setType("");
247                setTags(null);
248
249        }
250
251        /**
252         * Constructor.
253         * 
254         * @param runlsid
255         * @param theUser
256         * @param workflowName
257         * @param start
258         * @param dur
259         * @param execid
260         * @param errorMsgs
261         * @param host_id
262         * @param anno
263         * @param tagsList
264         * @param wflsid
265         * @param replaceInObjectManager
266         *            - attempt to replace any preexisting version in ObjectManager,
267         *            taking on preexisting version's entity id.
268         * @throws Exception
269         */
270        public WorkflowRun(KeplerLSID runlsid, String referralList, String theUser, String workflowName,
271                        KeplerLSID wfLSID, Date start, Long dur, Integer execid,
272                        Map<Integer, String> errorMsgs, String host_id, String anno,
273                        String module_dependencies, String type, Map<NamedOntClass, String> tagsList)
274                        throws Exception {
275                super(WORKFLOW_RUN);
276
277                if (isDebugging)
278                        log.debug("new WorkflowRun");
279
280                _elementName = _workflowRunElementName;
281
282                if (runlsid == null || theUser == null || workflowName == null || wfLSID == null || 
283                                start == null || dur == null || execid == null || errorMsgs == null || 
284                                host_id == null || module_dependencies == null || type == null){
285                        
286                                throw new Exception("WorkflowRun constructor got disallowed NULL argument: " +
287                                        "execLSID:"+runlsid+", user:" + theUser + ", workflowName:" + workflowName +
288                                        ", workflowLSID:" + wfLSID + ", startTime:" + start + ", duartion:" + dur +
289                                        ", execId:" + execid + ", errorMessages:" + errorMsgs + ", hostId:" + host_id + 
290                                        ", moduleDependencies:" + module_dependencies + ", type:" + type);
291                }
292                
293                log.debug("WorkflowRun constructor: " +
294                                "execLSID:"+runlsid+", user:" + theUser + ", workflowName:" + workflowName +
295                                ", workflowLSID:" + wfLSID + ", startTime:" + start + ", duartion:" + dur +
296                                ", execId:" + execid + ", errorMessages:" + errorMsgs + ", hostId:" + host_id + 
297                                ", moduleDependencies:" + module_dependencies + ", type:" + type);
298                
299                setExecLSID(runlsid);
300                setReferralList(referralList);
301                setUser(theUser);
302                setWorkflowName(workflowName);
303                setWorkflowLSID(wfLSID);
304                setStartTime(start);
305                setDuration(dur);
306                setExecId(execid);
307                setErrorMessages(errorMsgs);
308                setHostId(host_id);
309                setAnnotation(anno);
310                setModuleDependencies(module_dependencies);
311                setType(type);
312                setTags(tagsList);
313
314                try {
315                        WorkflowRunUtil.putInObjectManager(this);
316                } catch (Exception e) {
317                        e.printStackTrace();
318                }
319                
320        }
321
322        public KeplerLSID getExecLSID() {
323                Attribute att = getAttribute(RunAttribute.EXECLSID.toString());
324                if (att == null) {
325                        return null;
326                }
327                if (att instanceof StringAttribute) {
328                        StringAttribute sa = (StringAttribute) att;
329                        String val = sa.getExpression();
330                        KeplerLSID klsid = null;
331                        try {
332                                klsid = new KeplerLSID(val);
333                        } catch (Exception e) {
334                                e.printStackTrace();
335                        }
336                        return klsid;
337                } else {
338                        log.error("not a StringAttribute");
339                }
340                return null;
341        }
342
343        private void setExecLSID(KeplerLSID execLsid) {
344                if (execLsid == null) {
345                        setExecLSID("");
346                } else {
347                        setExecLSID(execLsid.toString());
348                }
349        }
350
351        private void setExecLSID(String execLsid) {
352                Attribute att = getAttribute(RunAttribute.EXECLSID.toString());
353                try {
354                        if (att == null) {
355                                if (execLsid == null || execLsid.equals("")) {
356                                        return;
357                                }
358                                att = new StringAttribute(this, RunAttribute.EXECLSID.toString());
359                        }
360                        if (att instanceof StringAttribute) {
361                                StringAttribute sa = (StringAttribute) att;
362                                if (execLsid == null || execLsid.equals("")) {
363                                        // delete the attribute
364                                        sa.setContainer(null);
365                                } else {
366                                        sa.setExpression(execLsid);
367                                }
368                        } else {
369                                log.error("not a StringAttribute");
370                        }
371                } catch (IllegalActionException e) {
372                        e.printStackTrace();
373                } catch (NameDuplicationException e) {
374                        e.printStackTrace();
375                }
376        }
377        
378        /**
379         * @param referralList (i.e. derivedFrom)
380         */
381        private void setReferralList(String referralList) {
382                try {
383                        NamedObjIdReferralList referrals;
384                        referrals = (NamedObjIdReferralList) this
385                                .getAttribute(NamedObjIdReferralList.NAME);
386                        
387                        if (referrals == null){
388                                referrals = new NamedObjIdReferralList(this,
389                                        NamedObjIdReferralList.NAME);
390                        }
391                                                
392                        if (referralList != null && !referralList.equals("")){
393                                referrals.setExpression(referralList);
394                        }
395                        
396                } catch (IllegalActionException e) {
397                        // TODO Auto-generated catch block
398                        e.printStackTrace();
399                } catch (NameDuplicationException e) {
400                        // TODO Auto-generated catch block
401                        e.printStackTrace();
402                } catch (Exception e) {
403                        // TODO Auto-generated catch block
404                        e.printStackTrace();
405                }
406        }
407        
408        public List<KeplerLSID> getReferralList()
409        {
410                 NamedObjIdReferralList referrals = (NamedObjIdReferralList) this
411                        .getAttribute(NamedObjIdReferralList.NAME);
412                 if (referrals != null)
413                 {
414                         try {
415                                return referrals.getReferrals();
416                        } catch (Exception e) {
417                                // TODO Auto-generated catch block
418                                e.printStackTrace();
419                        }
420                 }
421                 return null;
422        }
423
424        /**
425         * Return the LSID of the workflow that this WorkflowRun was generated from.
426         * 
427         * @return KeplerLSID
428         */
429        public KeplerLSID getWorkflowLSID() {
430                Attribute att = getAttribute(RunAttribute.WORKFLOWLSID.toString());
431                if (att == null) {
432                        return null;
433                }
434                if (att instanceof StringAttribute) {
435                        StringAttribute sa = (StringAttribute) att;
436                        String val = sa.getExpression();
437                        KeplerLSID klsid = null;
438                        try {
439                                klsid = new KeplerLSID(val);
440                        } catch (Exception e) {
441                                e.printStackTrace();
442                        }
443                        return klsid;
444                } else {
445                        log.error("not a StringAttribute");
446                }
447                return null;
448        }
449
450        private void setWorkflowLSID(KeplerLSID wfLSID) {
451                if (wfLSID == null) {
452                        setWorkflowLSID("");
453                } else {
454                        setWorkflowLSID(wfLSID.toString());
455                }
456        }
457
458        private void setWorkflowLSID(String wfLSID) {
459                Attribute att = getAttribute(RunAttribute.WORKFLOWLSID.toString());
460                try {
461                        if (att == null) {
462                                if (wfLSID == null || wfLSID.equals("")) {
463                                        return;
464                                }
465                                att = new StringAttribute(this, RunAttribute.WORKFLOWLSID.toString());
466                        }
467                        if (att instanceof StringAttribute) {
468                                StringAttribute sa = (StringAttribute) att;
469                                if (wfLSID == null || wfLSID.equals("")) {
470                                        // delete the attribute
471                                        sa.setContainer(null);
472                                } else {
473                                        sa.setExpression(wfLSID);
474                                }
475                        } else {
476                                log.error("not a StringAttribute");
477                        }
478                } catch (IllegalActionException e) {
479                        e.printStackTrace();
480                } catch (NameDuplicationException e) {
481                        e.printStackTrace();
482                }
483
484        }
485
486        /**
487         * Get the WorkflowRun annotation.
488         * 
489         * @return
490         */
491        public String getAnnotation() {
492                Attribute att = getAttribute(RunAttribute.ANNOTATION.toString());
493                if (att == null) {
494                        setAnnotation("");
495                        att = getAttribute(RunAttribute.ANNOTATION.toString());
496                }
497                if (att instanceof StringAttribute) {
498                        StringAttribute sa = (StringAttribute) att;
499                        String val = sa.getExpression();
500                        return val;
501                } else {
502                        log.error("not a StringAttribute");
503                }
504                return "";
505        }
506
507        /**
508         * Set the WorkflowRun annotation.
509         * 
510         * @param annotation
511         */
512        private void setAnnotation(String annotation) {
513                Attribute att = getAttribute(RunAttribute.ANNOTATION.toString());
514                try {
515                        if (att == null) {
516                                att = new StringAttribute(this, RunAttribute.ANNOTATION.toString());
517                        }
518                        if (att instanceof StringAttribute) {
519                                StringAttribute sa = (StringAttribute) att;
520                                sa.setExpression(annotation);
521                        } else {
522                                log.error("not a StringAttribute");
523                        }
524                } catch (IllegalActionException e) {
525                        e.printStackTrace();
526                } catch (NameDuplicationException e) {
527                        e.printStackTrace();
528                }
529        }
530        
531        /**
532         * Get the WorkflowRun module-dependencies.
533         * 
534         * @return moduleDependencies
535         */
536        public String getModuleDependencies() {
537                Attribute att = getAttribute(RunAttribute.MODULEDEPENDENCIES.toString());
538                if (att == null) {
539                        setAnnotation("");
540                        att = getAttribute(RunAttribute.MODULEDEPENDENCIES.toString());
541                }
542                if (att instanceof StringAttribute) {
543                        StringAttribute sa = (StringAttribute) att;
544                        String val = sa.getExpression();
545                        return val;
546                } else {
547                        log.error("not a StringAttribute");
548                }
549                return "";
550        }
551        
552        /**
553         * Set the WorkflowRun module-dependencies.
554         * 
555         * @param moduleDependencies
556         */
557        private void setModuleDependencies(String modDeps) {
558                Attribute att = getAttribute(RunAttribute.MODULEDEPENDENCIES.toString());
559                try {
560                        if (att == null) {
561                                att = new StringAttribute(this, RunAttribute.MODULEDEPENDENCIES.toString());
562                        }
563                        if (att instanceof StringAttribute) {
564                                StringAttribute sa = (StringAttribute) att;
565                                sa.setExpression(modDeps);
566                        } else {
567                                log.error("not a StringAttribute");
568                        }
569                } catch (IllegalActionException e) {
570                        e.printStackTrace();
571                } catch (NameDuplicationException e) {
572                        e.printStackTrace();
573                }
574        }
575
576        public String getHostId() {
577                Attribute att = getAttribute(RunAttribute.HOSTID.toString());
578                if (att == null) {
579                        setHostId("");
580                        att = getAttribute(RunAttribute.HOSTID.toString());
581                }
582                if (att instanceof StringAttribute) {
583                        StringAttribute sa = (StringAttribute) att;
584                        String val = sa.getExpression();
585                        return val;
586                } else {
587                        log.error("not a StringAttribute");
588                }
589                return "";
590        }
591
592        private void setHostId(String hostId) {
593                Attribute att = getAttribute(RunAttribute.HOSTID.toString());
594                try {
595                        if (att == null) {
596                                att = new StringAttribute(this, RunAttribute.HOSTID.toString());
597                        }
598                        if (att instanceof StringAttribute) {
599                                StringAttribute sa = (StringAttribute) att;
600                                sa.setExpression(hostId);
601                        } else {
602                                log.error("not a StringAttribute");
603                        }
604                } catch (IllegalActionException e) {
605                        e.printStackTrace();
606                } catch (NameDuplicationException e) {
607                        e.printStackTrace();
608                }
609        }
610
611        
612        /**
613         * Set the WorkflowRun type status.
614         * 
615         * @param moduleDependencies
616         */
617        private void setType(String type) {
618                Attribute att = getAttribute(RunAttribute.TYPE.toString());
619                try {
620                        if (att == null) {
621                                att = new StringAttribute(this, RunAttribute.TYPE.toString());
622                        }
623                        if (att instanceof StringAttribute) {
624                                StringAttribute sa = (StringAttribute) att;
625                                sa.setExpression(type);
626                        } else {
627                                log.error("not a StringAttribute");
628                        }
629                } catch (IllegalActionException e) {
630                        e.printStackTrace();
631                } catch (NameDuplicationException e) {
632                        e.printStackTrace();
633                }
634        }
635        
636        public String getType() {
637                Attribute att = getAttribute(RunAttribute.TYPE.toString());
638                if (att == null) {
639                        setType("");
640                        att = getAttribute(RunAttribute.TYPE.toString());
641                }
642                if (att instanceof StringAttribute) {
643                        StringAttribute sa = (StringAttribute) att;
644                        String val = sa.getExpression();
645                        return val;
646                } else {
647                        log.error("not a StringAttribute");
648                }
649                return "";
650        }
651        
652        
653        public String getUser() {
654                Attribute att = getAttribute(RunAttribute.USER.toString());
655                if (att == null) {
656                        setUser("");
657                        att = getAttribute(RunAttribute.USER.toString());
658                }
659                if (att instanceof StringAttribute) {
660                        StringAttribute sa = (StringAttribute) att;
661                        String val = sa.getExpression();
662                        return val;
663                } else {
664                        log.error("not a StringAttribute");
665                }
666                return "";
667        }
668
669        private void setUser(String user) {
670                Attribute att = getAttribute(RunAttribute.USER.toString());
671                try {
672                        if (att == null) {
673                                att = new StringAttribute(this, RunAttribute.USER.toString());
674                        }
675                        if (att instanceof StringAttribute) {
676                                StringAttribute sa = (StringAttribute) att;
677                                sa.setExpression(user);
678                        } else {
679                                log.error("not a StringAttribute");
680                        }
681                } catch (IllegalActionException e) {
682                        e.printStackTrace();
683                } catch (NameDuplicationException e) {
684                        e.printStackTrace();
685                }
686        }
687
688        /**
689         * Return the name of the workflow that this run was generated from.
690         * 
691         * @return String the name of the workflow that generated this run
692         */
693        public String getWorkflowName() {
694                Attribute att = getAttribute(RunAttribute.WORKFLOWNAME.toString());
695                if (att == null) {
696                        setWorkflowName("");
697                        att = getAttribute(RunAttribute.WORKFLOWNAME.toString());
698                }
699                if (att instanceof StringAttribute) {
700                        StringAttribute sa = (StringAttribute) att;
701                        String val = sa.getExpression();
702                        return val;
703                } else {
704                        log.error("not a StringAttribute");
705                }
706                return "";
707        }
708
709        private void setWorkflowName(String workflowName) {
710                Attribute att = getAttribute(RunAttribute.WORKFLOWNAME.toString());
711                try {
712                        if (att == null) {
713                                att = new StringAttribute(this, RunAttribute.WORKFLOWNAME.toString());
714                        }
715                        if (att instanceof StringAttribute) {
716                                StringAttribute sa = (StringAttribute) att;
717                                sa.setExpression(workflowName);
718                        } else {
719                                log.error("not a StringAttribute");
720                        }
721                } catch (IllegalActionException e) {
722                        e.printStackTrace();
723                } catch (NameDuplicationException e) {
724                        e.printStackTrace();
725                }
726        }
727
728        public String getStartTimeISO8601() {
729                Date d = getStartTime();
730                String s = WorkflowRunUtil.formatDateToISO8601(d);
731                return s;
732        }
733
734        public Date getStartTime() {
735                Attribute att = getAttribute(RunAttribute.STARTTIME.toString());
736                if (att == null) {
737                        setStartTime(new Date(0));
738                        att = getAttribute(RunAttribute.STARTTIME.toString());
739                }
740                if (att instanceof StringAttribute) {
741                        StringAttribute sa = (StringAttribute) att;
742                        String val = sa.getExpression();
743                        Date date = null;
744                        try {
745                                date = WorkflowRunUtil.formatStringFromISO8601(val);
746                                return date;
747                        } catch (Exception e) {
748                                e.printStackTrace();
749                        }
750                } else {
751                        log.error("not a StringAttribute");
752                }
753                return new Date(0);
754        }
755
756        private void setStartTime(Date date) {
757                String startTime = WorkflowRunUtil.formatDateToISO8601(date);
758                setStartTime(startTime);
759        }
760
761        private void setStartTime(String startTime) {
762                Attribute att = getAttribute(RunAttribute.STARTTIME.toString());
763                try {
764                        if (att == null) {
765                                att = new StringAttribute(this, RunAttribute.STARTTIME.toString());
766                        }
767                        if (att instanceof StringAttribute) {
768                                StringAttribute sa = (StringAttribute) att;
769                                sa.setExpression(startTime);
770                        } else {
771                                log.error("not a StringAttribute");
772                        }
773                } catch (IllegalActionException e) {
774                        e.printStackTrace();
775                } catch (NameDuplicationException e) {
776                        e.printStackTrace();
777                }
778        }
779
780        /**
781         * Get the duration in Seconds of the WorkflowRun.
782         * 
783         * @return Long
784         */
785        public Long getDuration() {
786                Attribute att = getAttribute(RunAttribute.DURATION.toString());
787                if (att == null) {
788                        setDuration(Long.valueOf(0));
789                        att = getAttribute(RunAttribute.DURATION.toString());
790                }
791                if (att instanceof StringAttribute) {
792                        StringAttribute sa = (StringAttribute) att;
793                        String val = sa.getExpression();
794                        Long lVal = null;
795                        try {
796                                lVal = Long.valueOf(val);
797                                return lVal;
798                        } catch (NumberFormatException nfe) {
799                                log.error(nfe.getMessage());
800                        }
801                } else {
802                        log.error("not a StringAttribute");
803                }
804                return Long.valueOf(0);
805        }
806
807        /**
808         * Set the duration in Seconds of the WorkflowRun.
809         * @param duration
810         */
811        private void setDuration(Long duration) {
812                Attribute att = getAttribute(RunAttribute.DURATION.toString());
813                try {
814                        if (att == null) {
815                                att = new StringAttribute(this, RunAttribute.DURATION.toString());
816                        }
817                        if (att instanceof StringAttribute) {
818                                StringAttribute sa = (StringAttribute) att;
819                                sa.setExpression(duration.toString());
820                        } else {
821                                log.error("not a StringAttribute");
822                        }
823                } catch (IllegalActionException e) {
824                        e.printStackTrace();
825                } catch (NameDuplicationException e) {
826                        e.printStackTrace();
827                }
828        }
829
830        /**
831         * Return the execution ID.
832         * 
833         * @return
834         */
835        public Integer getExecId() {
836                Attribute att = getAttribute(RunAttribute.EXECID.toString());
837                if (att == null) {
838                        setExecId(Integer.valueOf(0));
839                        att = getAttribute(RunAttribute.EXECID.toString());
840                }
841                if (att instanceof StringAttribute) {
842                        StringAttribute sa = (StringAttribute) att;
843                        String val = sa.getExpression();
844                        Integer iVal = null;
845                        try {
846                                iVal = Integer.valueOf(val);
847                                return iVal;
848                        } catch (NumberFormatException nfe) {
849                                log.error(nfe.getMessage());
850                        }
851                } else {
852                        log.error("not a StringAttribute");
853                }
854                return Integer.valueOf(0);
855        }
856
857        /**
858         * Set the execution ID.
859         * 
860         * @param execId
861         */
862        private void setExecId(int execId) {
863                Attribute att = getAttribute(RunAttribute.EXECID.toString());
864                try {
865                        if (att == null) {
866                                att = new StringAttribute(this, RunAttribute.EXECID.toString());
867                        }
868                        if (att instanceof StringAttribute) {
869                                StringAttribute sa = (StringAttribute) att;
870                                sa.setExpression("" + execId);
871                        } else {
872                                log.error("not a StringAttribute");
873                        }
874                } catch (IllegalActionException e) {
875                        e.printStackTrace();
876                } catch (NameDuplicationException e) {
877                        e.printStackTrace();
878                }
879
880        }
881
882        /**
883         * Assign new execId to a run, and entityId revision. *Note: This should
884         * probably only be called in the special insertHuskRun case.
885         */
886        public void resetExecId(int newExecId, Recording r) {
887                setExecId(newExecId);
888
889                // now roll the revision.
890                rollRevision(getExecLSID(), r);
891        }
892        
893        public void resetType(String workflowRunType, Recording r) {
894                setType(workflowRunType);
895
896                // now roll the revision.
897                rollRevision(getExecLSID(), r);
898        }
899
900        public Map<Integer, String> getErrorMessages() {
901
902                Map<Integer, String> errorMsgs = new LinkedHashMap<Integer, String>();
903
904                Attribute errorMessagesAtt = getAttribute(RunAttribute.ERRORMESSAGES.toString());
905                if (errorMessagesAtt == null) {
906                        return errorMsgs;
907                }
908                if (isDebugging) {
909                        log.debug("getErrorMessages()");
910                        log.debug(errorMessagesAtt.exportMoML());
911                }
912                if (errorMessagesAtt instanceof StringAttribute) {
913                        StringAttribute errorMessagesSA = (StringAttribute) errorMessagesAtt;
914
915                        List<Object> errs = errorMessagesSA.attributeList();
916                        for (Object err : errs) {
917                                if (err instanceof StringAttribute) {
918                                        StringAttribute errSA = (StringAttribute) err;
919                                        String errName = errSA.getName();
920                                        if (errName.toLowerCase().startsWith(RunAttribute.ERROR.toString())) {
921                                                String errNumStr = errName.substring(5);
922                                                try {
923                                                        Integer errNum = new Integer(errNumStr);
924                                                        String errorMsg = errSA.getExpression();
925                                                        errorMsgs.put(errNum, errorMsg);
926                                                } catch (NumberFormatException nfe) {
927                                                        nfe.printStackTrace();
928                                                }
929                                        }
930                                }
931                        }
932                }
933                return errorMsgs;
934        }
935
936        private void clearErrorMessages() {
937
938                Attribute errorMessagesAtt = getAttribute(RunAttribute.ERRORMESSAGES.toString());
939                if (errorMessagesAtt == null) {
940                        return;
941                }
942                if (errorMessagesAtt instanceof StringAttribute) {
943                        StringAttribute errorMessagesSA = (StringAttribute) errorMessagesAtt;
944                        String numErrorsStr = null;
945                        int numErrors = 0;
946                        if (errorMessagesSA != null) {
947                                numErrorsStr = errorMessagesSA.getExpression();
948                                if (numErrorsStr != null && !numErrorsStr.equals("")) {
949                                        try {
950                                                numErrors = Integer.parseInt(numErrorsStr);
951                                        } catch (NumberFormatException nfe) {
952                                                nfe.printStackTrace();
953                                        }
954                                }
955                        }
956
957                        for (int i = 1; i < numErrors; i++) {
958                                // start at 1 not 0
959                                StringAttribute errorMessageAttrib = (StringAttribute) errorMessagesSA
960                                                .getAttribute("error" + i);
961                                try {
962                                        errorMessageAttrib.setContainer(null);
963                                } catch (IllegalActionException e) {
964                                        e.printStackTrace();
965                                } catch (NameDuplicationException e) {
966                                        e.printStackTrace();
967                                }
968                        }
969                }
970
971        }
972
973        private void setErrorMessages(Map<Integer, String> errorMessages) {
974                if (isDebugging) {
975                        if (errorMessages == null) {
976                                log.debug("setErrorMessages(null)");
977                        } else {
978                                log.debug("setErrorMessages(" + errorMessages.toString() + ")");
979                        }
980                }
981                try {
982                        Attribute errorMessagesAtt = getAttribute(RunAttribute.ERRORMESSAGES.toString());
983                        if (errorMessagesAtt == null) {
984                                errorMessagesAtt = new StringAttribute(this,
985                                                RunAttribute.ERRORMESSAGES.toString());
986                        }
987                        if (isDebugging)
988                                log.debug("Before:\n" + errorMessagesAtt.exportMoML());
989                        if (errorMessagesAtt instanceof StringAttribute) {
990                                clearErrorMessages();
991                                StringAttribute errorMessagesSA = (StringAttribute) errorMessagesAtt;
992                                if (errorMessages == null || errorMessages.isEmpty()) {
993                                        errorMessagesSA.setExpression("");
994                                } else {
995                                        Set<Integer> errKeys = errorMessages.keySet();
996                                        errorMessagesSA.setExpression("" + errKeys.size());
997                                        Iterator<Integer> itr = errKeys.iterator();
998                                        while (itr.hasNext()) {
999                                                int err = itr.next();
1000                                                StringAttribute errorAttribute = new StringAttribute(
1001                                                                errorMessagesSA, "error" + err);
1002                                                String mess = errorMessages.get(err);
1003                                                errorAttribute.setExpression(mess);
1004                                        }
1005                                }
1006                        }
1007                        if (isDebugging)
1008                                log.debug("After:\n" + errorMessagesAtt.exportMoML());
1009                } catch (IllegalActionException e) {
1010                        e.printStackTrace();
1011                } catch (NameDuplicationException e) {
1012                        e.printStackTrace();
1013                }
1014        }
1015
1016        public String toString() {
1017                return this.exportMoML();
1018        }
1019
1020        /**
1021         * Clear any existing tags and set to tagsList, and roll entityId revision.
1022         * 
1023         * @throws IllegalActionException
1024         */
1025        private void setTags(Map<NamedOntClass, String> tagsList) {
1026
1027                if (tagsList == null || tagsList.isEmpty())
1028                        return;
1029
1030                try {
1031
1032                        Attribute wfatt = getAttribute(RunAttribute.WORKFLOWTAGS.toString());
1033                        if (wfatt == null) {
1034                                wfatt = new StringAttribute(this, RunAttribute.WORKFLOWTAGS.toString());
1035                        }
1036                        StringAttribute wfSA = null;
1037                        if (wfatt instanceof StringAttribute) {
1038                                wfSA = (StringAttribute) wfatt;
1039                        }
1040                        if (wfSA == null) {
1041                                log.error("workflow String Attribute is null");
1042                        }
1043
1044                        Vector<NamedOntClass> runSemTypes = new Vector<NamedOntClass>();
1045                        Vector<NamedOntClass> wfSemTypes = new Vector<NamedOntClass>();
1046                        for (Map.Entry<NamedOntClass,String> entry : tagsList.entrySet()) {
1047                            NamedOntClass tag = entry.getKey();
1048                            String type = entry.getValue();
1049
1050                                if (type == null)
1051                                        continue;
1052
1053                                if (type.equals(TAG_TYPE_WORKFLOW)) {
1054                                        wfSemTypes.add(tag);
1055                                }
1056                                if (type.equals(TAG_TYPE_RUN)) {
1057                                        runSemTypes.add(tag);
1058                                }
1059                        }
1060
1061                        if (wfSemTypes.size() > 0){
1062                                wfSA.setExpression("" + wfSemTypes.size());
1063                        }
1064
1065                        SMSServices.setActorSemanticTypes(wfSA, wfSemTypes);
1066                        SMSServices.setActorSemanticTypes(this, runSemTypes);
1067
1068                } catch (NameDuplicationException e) {
1069                        e.printStackTrace();
1070                } catch (IllegalActionException e) {
1071                        e.printStackTrace();
1072                }
1073        }
1074
1075        /**
1076         * Whenever a run is changed, update revision in OM, 
1077         * update run's execLSID, and update workflow_exec lsid in provenance.
1078         *  
1079         */
1080        public void rollRevision(KeplerLSID lsid, Recording recording) {
1081                try {
1082                        NamedObj nObj = ObjectManager.getInstance()
1083                                        .getHighestObjectRevision(lsid);
1084                        if (nObj == null){
1085                                //WorkflowRunUtil.putInObjectManager(this, recording.getQueryable(false));
1086                                WorkflowRunUtil.putInObjectManager(this);
1087                        }
1088                        nObj = ObjectManager.getInstance().getHighestObjectRevision(lsid);
1089                        
1090                        if (nObj != null) {
1091                                NamedObjId noi = NamedObjId.getIdAttributeFor(nObj);
1092                                if (noi != null) {
1093                                        noi.updateRevision();
1094                                        this.setExecLSID(noi.getId());
1095                                        
1096                                        //WorkflowRunUtil.putInObjectManager(this, recording.getQueryable(false));
1097                                        WorkflowRunUtil.putInObjectManager(this);
1098                                        
1099                                        recording.changeExecutionLSID(this.getExecId(), this.getExecLSID(), recording.getQueryable(false));
1100                                
1101                                        //FIXME hardcoded to SQLRecordingV8. also check on this line here.
1102                                        //insert any referrals
1103                                ((SQLRecordingV8)recording).insertAnyHuskRunReferralList(this);
1104                                }
1105                                else{
1106                                        log.error("noi was null. This shouldn't happen.");
1107                                }
1108                        } else {
1109                                log.error("nObj was null. This shouldn't happen");
1110                                NamedObjId.assignIdTo(this, lsid, true);
1111                        }
1112                } catch (Exception e) {
1113                        e.printStackTrace();
1114                }
1115        }
1116
1117        public Vector<SemanticType> getWorkflowSemanticTypes() {
1118
1119                Vector<SemanticType> wfSemTypes = new Vector<SemanticType>();
1120
1121                try {
1122
1123                        Attribute wfatt = getAttribute(RunAttribute.WORKFLOWTAGS.toString());
1124                        if (wfatt == null) {
1125                                wfatt = new StringAttribute(this, RunAttribute.WORKFLOWTAGS.toString());
1126                        }
1127                        StringAttribute wfSA = null;
1128                        if (wfatt instanceof StringAttribute) {
1129                                wfSA = (StringAttribute) wfatt;
1130                        }
1131                        if (wfSA == null) {
1132                                log.error("workflow String Attribute is null");
1133                        }
1134
1135                        wfSemTypes = SMSServices.getActorSemanticTypes(wfSA);
1136
1137                } catch (IllegalActionException e) {
1138                        e.printStackTrace();
1139                } catch (NameDuplicationException e) {
1140                        e.printStackTrace();
1141                }
1142                return wfSemTypes;
1143        }
1144
1145        public Map<NamedOntClass, String> getTags() {
1146
1147                Map<NamedOntClass, String> tags = new LinkedHashMap<NamedOntClass, String>();
1148
1149                for (SemanticType st : getWorkflowSemanticTypes()) {
1150                        NamedOntClass namedOntClass = NamedOntClass
1151                                        .createNamedOntClassFromURI(st.getConceptId());
1152                        if (namedOntClass == null) {
1153                                namedOntClass = new NamedOntClass(st.getConceptName());
1154                        }
1155                        tags.put(namedOntClass, TAG_TYPE_WORKFLOW);
1156                }
1157
1158                Vector<SemanticType> runSemTypes = SMSServices
1159                                .getActorSemanticTypes(this);
1160                for (SemanticType st : runSemTypes) {
1161                        NamedOntClass namedOntClass = NamedOntClass
1162                                        .createNamedOntClassFromURI(st.getConceptId());
1163                        if (namedOntClass == null) {
1164                                namedOntClass = new NamedOntClass(st.getConceptName());
1165                        }
1166                        tags.put(namedOntClass, TAG_TYPE_RUN);
1167                }
1168                return tags;
1169        }
1170
1171        public String getTagsAsFormattedString() {
1172                Map<NamedOntClass, String> tags = getTags();
1173                List<String> tagNames = new ArrayList<String>();
1174                for (NamedOntClass tag : tags.keySet()) {
1175                        tagNames.add(tag.getName());
1176                }
1177                
1178                Collections.sort(tagNames, new Comparator<String>() {
1179                        public int compare(String o1, String o2) {
1180                                return o1.compareToIgnoreCase(o2);
1181                        }
1182                });
1183                
1184                return join(tagNames, ", ");
1185        }
1186
1187        private static String join(List<String> strings, String delimiter) {
1188                if (strings.size() == 0) return "";
1189                StringBuilder sb = new StringBuilder(strings.get(0));
1190                for (int i = 1; i < strings.size(); i++) {
1191                        String string = strings.get(i);
1192                        sb.append(delimiter).append(string);
1193                }
1194                return sb.toString();
1195        }
1196
1197        /**
1198         * Return a description of the object. The level of detail depends on the
1199         * argument, which is an or-ing of the static final constants defined in
1200         * this class (NamedObj). Lines are indented according to to the level
1201         * argument using the static method _getIndentPrefix(). Zero, one or two
1202         * brackets can be specified to surround the returned description. If one is
1203         * specified it is the the leading bracket. This is used by derived classes
1204         * that will append to the description. Those derived classes are
1205         * responsible for the closing bracket. An argument other than 0, 1, or 2 is
1206         * taken to be equivalent to 0. This method is read-synchronized on the
1207         * workspace.
1208         * 
1209         * @param detail
1210         *            The level of detail.
1211         * @param indent
1212         *            The amount of indenting.
1213         * @param bracket
1214         *            The number of surrounding brackets (0, 1, or 2).
1215         * @return A description of the object.
1216         * @exception IllegalActionException
1217         */
1218        protected String _description(int detail, int indent, int bracket)
1219                        throws IllegalActionException {
1220
1221                StringBuffer result = new StringBuffer();
1222                /*
1223                 * _workspace.getReadAccess();
1224                 * 
1225                 * if ((bracket == 1) || (bracket == 2)) {
1226                 * result.append(super._description(detail, indent, 1)); } else {
1227                 * result.append(super._description(detail, indent, 0)); }
1228                 * 
1229                 * if (bracket == 2) { result.append("}"); }
1230                 * 
1231                 * 
1232                 * _workspace.doneReading();
1233                 */
1234                return result.toString();
1235        }
1236
1237        public String getElementName() {
1238                return _workflowRunElementName;
1239        }
1240
1241        public void setName(String name) throws IllegalActionException,
1242                        NameDuplicationException {
1243                super.setName(name);
1244                if (isDebugging)
1245                        log.debug("setName(" + name + ")");
1246        }
1247        
1248}