001/* Query PROV serializations.
002
003Copyright (c) 2015 The Regents of the University of California.
004All rights reserved.
005Permission is hereby granted, without written agreement and without
006license or royalty fees, to use, copy, modify, and distribute this
007software and its documentation for any purpose, provided that the above
008copyright notice and the following two paragraphs appear in all copies
009of this software.
010
011IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015SUCH DAMAGE.
016
017THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022ENHANCEMENTS, OR MODIFICATIONS.
023
024*/
025package org.kepler.provenance.prov;
026
027import java.io.File;
028import java.io.FileOutputStream;
029import java.io.InputStream;
030import java.util.ArrayList;
031import java.util.Collections;
032import java.util.Date;
033import java.util.LinkedList;
034import java.util.List;
035import java.util.jar.JarFile;
036import java.util.regex.Matcher;
037import java.util.regex.Pattern;
038import java.util.zip.ZipEntry;
039
040import javax.xml.datatype.DatatypeConfigurationException;
041import javax.xml.datatype.DatatypeFactory;
042import javax.xml.datatype.XMLGregorianCalendar;
043
044import org.apache.commons.io.IOUtils;
045import org.kepler.objectmanager.lsid.KeplerLSID;
046import org.kepler.provenance.DefaultQuery;
047import org.kepler.provenance.QueryException;
048import org.openprovenance.prov.interop.InteropFramework;
049import org.openprovenance.prov.interop.InteropFramework.ProvFormat;
050import org.openprovenance.prov.model.Activity;
051import org.openprovenance.prov.model.Document;
052import org.openprovenance.prov.model.Entity;
053import org.openprovenance.prov.model.HasOther;
054import org.openprovenance.prov.model.HasRole;
055import org.openprovenance.prov.model.Identifiable;
056import org.openprovenance.prov.model.Other;
057import org.openprovenance.prov.model.QualifiedName;
058import org.openprovenance.prov.model.Role;
059import org.openprovenance.prov.model.StatementOrBundle;
060import org.openprovenance.prov.model.Used;
061import org.openprovenance.prov.model.WasGeneratedBy;
062
063/** A class to query provenance in PROV serializations.
064 * 
065 *  @author Daniel Crawl
066 *  @version $Id: ProvQuery.java 33846 2015-09-02 00:25:36Z crawl $
067 * 
068 */
069public class ProvQuery extends DefaultQuery {
070
071    /** Create a new ProvQuery from an input stream using a specific
072     *  format. The stream is not closed by this method.
073     */
074    public ProvQuery(InputStream stream, ProvFormat format) throws QueryException {
075        
076        _initialize();
077                
078        InteropFramework framework = new InteropFramework();
079        Document document = framework.readDocument(stream, format);
080        _statements = document.getStatementOrBundle();
081    }
082        
083    /** Create a new ProvQuery for a PROV serialization in the
084     *  specified file.
085     */
086    public ProvQuery(String filename) throws QueryException {
087        
088        _initialize();
089        
090        File file = new File(filename);
091        if(!file.exists()) {
092            throw new QueryException("File does not exist: " + filename);
093        }
094                
095        InteropFramework framework = new InteropFramework();
096        Document document = framework.readDocumentFromFile(filename);
097        _statements = document.getStatementOrBundle();        
098    }
099    
100    /** Disconnect from the underlying provenance store. Once this
101     *  method is called, no further methods may be called on this
102     *  object.
103     */
104    @Override
105    public void disconnect() throws QueryException {
106        _statements.clear();
107        _wfEntity = null;
108        _wfName = null;
109    }
110    
111    /** Get the actor firing ids for a workflow execution id. */
112    @Override
113    public List<Integer> getActorFirings(int execId) throws QueryException {
114        if(execId == _EXECUTION_ID) {
115            return _getIdentifiableIds(StatementOrBundle.Kind.PROV_ACTIVITY,
116                _ACTIVITY_ID_PATTERN);
117        }        
118        return null;
119    }
120    
121    /** Get the firing id(s) of the actor(s) that read or wrote a token.
122     *  @param tokenId the token id
123     *  @param read If true, return the actor(s) firing id(s) that read
124     *  the token. Otherwise, return the actor firing that wrote the token.
125     */
126    @Override
127    public List<Integer> getActorFiringForToken(int tokenId, boolean read)
128            throws QueryException {
129        
130        List<Integer> firings = new LinkedList<Integer>();
131
132        StatementOrBundle.Kind kind;        
133        if(read) {
134            kind = StatementOrBundle.Kind.PROV_USAGE;
135        } else {
136            kind = StatementOrBundle.Kind.PROV_GENERATION;
137        }
138        
139        for(StatementOrBundle statement : _statements) {
140            if(statement.getKind() == kind) {
141                
142                QualifiedName activity;
143                QualifiedName entity;
144                if(kind == StatementOrBundle.Kind.PROV_USAGE) {
145                    activity = ((Used)statement).getActivity();
146                    entity = ((Used)statement).getEntity();
147                } else {
148                    activity = ((WasGeneratedBy)statement).getActivity();
149                    entity = ((WasGeneratedBy)statement).getEntity();
150                }
151                
152                Matcher matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
153                if(matcher.matches()) {
154                    Integer entityId = Integer.valueOf(matcher.group(1));
155                    if(entityId.equals(Integer.valueOf(tokenId))) {
156                        matcher = _ACTIVITY_ID_PATTERN.matcher(activity.getLocalPart());
157                        if(!matcher.matches()) {
158                            System.err.println("WARNING: unknown activity id: " +
159                                activity.getLocalPart());
160                            continue;
161                        }
162                        Integer idVal = Integer.valueOf(matcher.group(1));
163                        firings.add(idVal);
164                    }
165                }
166            }
167        }
168        return firings;
169
170    }
171
172    /** Get the actor name for a firing id. */
173    @Override
174    public String getActorName(int fireId) throws QueryException {        
175
176        if(_wfEntity == null) {
177            _findWorkflowEntity(_EXECUTION_ID);
178        }
179
180        Activity activity = _getActivityForFiring(fireId);
181        if(activity != null) {
182            String actorFullName = (String) _getOtherValue(activity, ProvRecording.QN_ACTOR_NAME);
183            if(actorFullName != null) {
184                return actorFullName.substring(_wfName.length());
185            }
186        }
187        return null;
188    }
189    
190    /** Get the execution LSID for a workflow execution id. */
191    @Override
192    public KeplerLSID getExecutionLSIDForExecution(Integer execId)
193            throws QueryException {
194        
195        if(_wfEntity == null) {
196            _findWorkflowEntity(execId);
197        }
198        
199        if(_wfEntity != null && execId == _EXECUTION_ID) {
200            String lsidStr = (String) _getOtherValue(_wfEntity, ProvRecording.QN_EXECUTION_LSID);
201            if(lsidStr != null) {
202                try {
203                    return new KeplerLSID(lsidStr);
204                } catch (Exception e) {
205                    throw new QueryException("Error created LSID.", e);
206                }
207            }
208        }        
209        return null;
210    }
211
212    /** Get execution ids. For Prov, there is only one execution
213     *  per file.
214     */
215    @Override
216    public List<Integer> getExecutions() throws QueryException {
217        List<Integer> list = new LinkedList<Integer>();
218        list.add(Integer.valueOf(_EXECUTION_ID));
219        return list;
220    }
221
222    /** Get the MoML for an execution. */
223    @Override
224    public String getMoMLForExecution(int execId) throws QueryException {
225        
226        if(_wfEntity == null) {
227            _findWorkflowEntity(execId);
228        }
229        
230        if(_wfEntity != null) {
231            return (String) _wfEntity.getValue().getValue();
232        }
233        
234        return null;
235    }
236
237    /** Get the output role (port name) of a token. */
238    @Override
239    public String getOutputRoleToken(int tokenId) throws QueryException {
240        return _getRole(tokenId, null, StatementOrBundle.Kind.PROV_GENERATION);
241    }
242    
243    /** Get the input role (port name) of a token. */
244    @Override
245    public String getInputRoleForTokenAndFireId(int tokenId, int fireId)
246        throws QueryException {
247        return _getRole(tokenId, fireId, StatementOrBundle.Kind.PROV_USAGE);
248    }
249
250    /** Get the start and end timestamps of an actor firing. */
251    @Override
252    public Date[] getTimestampsForActorFiring(int fireId)
253        throws QueryException
254    {
255
256        Activity activity = _getActivityForFiring(fireId);
257        if(activity != null) {
258            Date startDate = null;
259            Date endDate = null;
260            XMLGregorianCalendar start = activity.getStartTime();
261            if(start != null) {
262                startDate = start.toGregorianCalendar().getTime();
263            }
264   
265            XMLGregorianCalendar end = activity.getEndTime();
266            if(end != null) {
267                endDate = end.toGregorianCalendar().getTime();
268            }
269            
270            if(startDate != null && endDate != null) {
271                return new Date [] {startDate, endDate};
272            }
273        }
274        return null;
275    }
276    
277    /** Get the start and stop timestampes for a workflow execution id. */
278    @Override
279    public Date[] getTimestampsForExecution(int execId) throws QueryException {
280
281        if(_wfEntity == null) {
282            _findWorkflowEntity(execId);
283        }
284
285        if(_wfEntity != null && execId == _EXECUTION_ID) {
286            Date timestamps[] = new Date[2];
287            for(Other other : _wfEntity.getOther()) {
288                String localPart = other.getElementName().getLocalPart();
289                if(localPart.equals(ProvRecording.QN_EXECUTION_START_DATETIME)) {
290                    String timestampStr = (String) other.getValue();
291                    timestamps[0] = _dataTypeFactory.newXMLGregorianCalendar(timestampStr).toGregorianCalendar().getTime();
292                } else if(localPart.equals(ProvRecording.QN_EXECUTION_END_DATETIME)) {
293                    String timestampStr = (String) other.getValue();
294                    timestamps[1] = _dataTypeFactory.newXMLGregorianCalendar(timestampStr).toGregorianCalendar().getTime();                    
295                }
296            }
297            return timestamps;
298        }
299        return null;
300    }
301
302    /** Get the timestamp(s) when a token was read. If a token was
303     *  never read, this can return null or an empty array.
304     */
305    @Override
306    public Date[] getTimestampsForTokenRead(Integer tokenId) throws QueryException {
307        
308        List<Date> dates = new LinkedList<Date>();
309        for(StatementOrBundle statement : _statements) {
310            if(statement.getKind() == StatementOrBundle.Kind.PROV_USAGE) {
311                Used used = (Used)statement;
312                QualifiedName entity = used.getEntity();
313                Matcher matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
314                if(!matcher.matches()) {
315                    System.err.println("WARNING: unknown entity id: " +
316                        entity.getLocalPart() + " in Used " + used);
317                    continue;
318                }
319                if(Integer.valueOf(matcher.group(1)).equals(tokenId)) {
320                    XMLGregorianCalendar time = used.getTime();
321                    if(time != null) {
322                        dates.add(time.toGregorianCalendar().getTime());
323                    }
324                } 
325            }
326        }
327        return dates.toArray(new Date[dates.size()]);
328    }
329
330    /** Get the timestamp when a token was written. */
331    @Override
332    public Date getTimestampForTokenWrite(Integer tokenId) throws QueryException {
333     
334        for(StatementOrBundle statement : _statements) {
335            if(statement.getKind() == StatementOrBundle.Kind.PROV_GENERATION) {
336                WasGeneratedBy wgb = (WasGeneratedBy)statement;
337                QualifiedName entity = wgb.getEntity();
338                Matcher matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
339                if(!matcher.matches()) {
340                    System.err.println("WARNING: unknown entity id: " +
341                        entity.getLocalPart() + " in WasGeneratedBy " + wgb);
342                    continue;
343                }
344                if(Integer.valueOf(matcher.group(1)).equals(tokenId)) {
345                    XMLGregorianCalendar time = wgb.getTime();
346                    if(time != null) {
347                        return time.toGregorianCalendar().getTime();
348                    }
349                }
350            }
351        }
352        return null;
353    }
354
355    /** Get an sequence of tokens for an execution.
356     *  @param execId the execution id
357     *  @param portId the port id. If null, returns a the ids of
358     *  tokens read in entire execution.
359     *  @param last if true, the sequence starts at the last token created
360     *  and goes backwards to the first; otherwise the sequence starts at
361     *  the first.
362     */
363    @Override
364    public List<Integer> getTokensForExecution(int execId, Integer portId,
365        boolean last) throws QueryException {
366     
367        if(portId != null) {
368            throw new QueryException("Getting tokens for a specific " +
369                "port not implemented for PROV.");
370        }
371        
372        if(_wfEntity == null) {
373            _findWorkflowEntity(execId);
374        }
375        
376        if(_wfEntity != null && execId == _EXECUTION_ID) {
377            
378            List<Integer> tokenIds = new ArrayList<Integer>();
379            for(StatementOrBundle statement : _statements) {
380                if(statement.getKind() == StatementOrBundle.Kind.PROV_GENERATION) {
381
382                    QualifiedName entity = ((WasGeneratedBy)statement).getEntity();
383
384                    Matcher matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
385                    if(!matcher.matches()) {
386                        System.err.println("WARNING: unknown entity id: " +
387                            entity.getLocalPart());
388                        continue;
389                    }
390                    Integer idVal = Integer.valueOf(matcher.group(1));
391                    tokenIds.add(idVal);
392                }
393            }
394            if(last) {
395                Collections.sort(tokenIds, Collections.reverseOrder());
396            } else {
397                Collections.sort(tokenIds);
398            }
399            return tokenIds;
400        }
401        return null;        
402    }
403
404    /** Get tokens for a firing.
405     *  @param fireId the firing id
406     *  @param read if true, get the tokens read; otherwise get the tokens
407     *  written.
408     */
409    @Override
410    public List<Integer> getTokensForFiring(int fireId, boolean read)
411        throws QueryException {
412
413        List<Integer> tokens = new LinkedList<Integer>();
414
415        StatementOrBundle.Kind kind;        
416        if(read) {
417            kind = StatementOrBundle.Kind.PROV_USAGE;
418        } else {
419            kind = StatementOrBundle.Kind.PROV_GENERATION;
420        }
421        
422        for(StatementOrBundle statement : _statements) {
423            if(statement.getKind() == kind) {
424                
425                QualifiedName activity;
426                QualifiedName entity;
427                if(kind == StatementOrBundle.Kind.PROV_USAGE) {
428                    activity = ((Used)statement).getActivity();
429                    entity = ((Used)statement).getEntity();
430                } else {
431                    activity = ((WasGeneratedBy)statement).getActivity();
432                    entity = ((WasGeneratedBy)statement).getEntity();
433                }
434                
435                Matcher matcher = _ACTIVITY_ID_PATTERN.matcher(activity.getLocalPart());
436                if(matcher.matches()) {
437                    Integer activityId = Integer.valueOf(matcher.group(1));
438                    if(activityId.equals(Integer.valueOf(fireId))) {
439                        matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
440                        if(!matcher.matches()) {
441                            System.err.println("WARNING: unknown entity id: " + entity.getLocalPart());
442                            continue;
443                        }
444                        Integer idVal = Integer.valueOf(matcher.group(1));
445                        tokens.add(idVal);
446                    }
447                }
448            }
449        }
450        return tokens;
451    }
452
453    /** Get the value of a token. */
454    @Override
455    public String getTokenValue(int tokenId) throws QueryException {
456        
457        Entity entity = _getEntity(tokenId);
458        if(entity != null) {
459            return (String) entity.getValue().getValue();
460        }
461        return null;
462    }
463
464    /** Get the type of a token. */
465    @Override
466    public String getTokenType(int tokenId) throws QueryException {
467        
468        Entity entity = _getEntity(tokenId);
469        if(entity != null) {
470            return (String) _getOtherValue(entity, ProvRecording.QN_TOKEN_CLASS);
471        }
472        return null;
473    }
474
475    /** Get the channel that a token was read or written on.
476     *  @param tokenId the token id
477     *  @param read if true, return the channel the token was read on.
478     *  otherwise, return the channel the token was written on.
479     *  @param fireId the actor firing id. can be null for writes, but
480     *  must be specified for reads.
481     *  @return the channel the token was read or written on.
482     */
483    @Override
484    public Integer getChannelForToken(int tokenId, boolean read, Integer fireId)
485        throws QueryException {
486
487        StatementOrBundle.Kind kind;
488        if(read) {
489            kind = StatementOrBundle.Kind.PROV_USAGE;
490        } else {
491            kind = StatementOrBundle.Kind.PROV_GENERATION;
492        }
493        
494        StatementOrBundle statement = _getUsedOrWasGeneratedBy(tokenId, fireId, kind);
495        
496        if(statement != null) {
497            String value = (String) _getOtherValue((HasOther) statement,
498                ProvRecording.QN_CHANNEL);
499            if(value != null) {
500                try {
501                    return Integer.valueOf(value);
502                } catch(NumberFormatException e) {
503                    throw new QueryException("Error converting channel to number: " +
504                        value);
505                }
506            }
507        }
508        return null;        
509    }
510
511    ///////////////////////////////////////////////////////////////////
512    ////                       protected methods                   ////
513
514    /** Returns false since ProvRecording saves StringToken values
515     *  using StringToken.stringValue(), which does not add
516     *  surrounding double-quotes.
517     */
518    @Override
519    protected boolean _stringTokenValuesHaveSurroundingQuotes() {
520        return false;
521    }
522
523    ///////////////////////////////////////////////////////////////////
524    ////                       private methods                     ////
525
526    /** Set the workflow entity for a workflow execution id. */
527    private void _findWorkflowEntity(int execId) throws QueryException {
528        if(_wfEntity == null && execId == _EXECUTION_ID) {
529            for(StatementOrBundle statement : _statements) {
530                if(statement.getKind() == StatementOrBundle.Kind.PROV_ENTITY &&
531                    ((Entity)statement).getId().getLocalPart().equals(ProvRecording.QN_WORKFLOW)) {
532                    _wfEntity = (Entity)statement;
533                    _wfName = (String) _getOtherValue(_wfEntity, ProvRecording.QN_ACTOR_NAME);                  
534                    break;
535                }
536            }
537        }
538        
539        //System.out.println(_wfEntity);
540        
541        if(_wfEntity == null) {
542            throw new QueryException("Could not query workflow entity.");
543        }
544        if(_wfName == null) {
545            throw new QueryException("Could not find workflow name in workflow entity.");
546        }
547    }
548    
549    /** Get the value for an Other with a specific id. */
550    private Object _getOtherValue(HasOther hasOther, String idLocalPart) {
551        for(Other other : hasOther.getOther()) {
552            if(other.getElementName().getLocalPart().equals(idLocalPart)) {
553                return other.getValue();
554            }
555        }
556        return null;
557    }
558    
559    /** Get the Activity for an actor firing id. */
560    private Activity _getActivityForFiring(int fireId) {
561        return (Activity) _getIdentifiable(fireId,
562                StatementOrBundle.Kind.PROV_ACTIVITY,
563                _ACTIVITY_ID_PATTERN);
564    }
565    
566    
567    /** Get the Entity for an token id. */
568    private Entity _getEntity(int tokenId) {
569        return (Entity) _getIdentifiable(tokenId,
570                StatementOrBundle.Kind.PROV_ENTITY,
571                _ENTITY_ID_PATTERN);
572    }
573
574    /** Get an Identifiable with a specific id. */
575    private Identifiable _getIdentifiable(int id, StatementOrBundle.Kind kind,
576            Pattern pattern) {
577        for(StatementOrBundle statement : _statements) {
578            if(statement.getKind() == kind) {              
579                String idStr = ((Identifiable)statement).getId().getLocalPart();
580                if(!idStr.equals(ProvRecording.QN_WORKFLOW)) {
581                    Matcher matcher = pattern.matcher(idStr);
582                    if(!matcher.matches()) {
583                        System.err.println("WARNING: unknown id for " + 
584                            kind + ": " + id);
585                        continue;
586                    }
587                    Integer idVal = Integer.valueOf(matcher.group(1));
588                    if(idVal.equals(Integer.valueOf(id))) {
589                        return (Identifiable) statement;
590                    }
591                }
592            }
593        }
594        return null;
595    }
596    
597    /** Get the ids of identifiables.
598     *  @param kind The kind of identifiable, e.g., activity, entity.
599     *  @param pattern The regex pattern to capture that id in the identifiable name.
600     *  @return The ids of the identifiables.
601     */
602    private List<Integer> _getIdentifiableIds(StatementOrBundle.Kind kind, Pattern pattern) {        
603        List<Integer> ids = new LinkedList<Integer>();
604        for(StatementOrBundle statement : _statements) {
605            if(statement.getKind() == kind) {
606                //System.out.println(statement);
607                String id = ((Identifiable) statement).getId().getLocalPart();
608                Matcher matcher = pattern.matcher(id);
609                if(!matcher.matches()) {
610                    System.err.println("WARNING: unknown id in activity: " + id);
611                    continue;
612                }
613                ids.add(Integer.valueOf(matcher.group(1)));
614            }
615        }
616        return ids;
617    }
618
619    /** Get the role (port name) for a token read or write. */
620    private String _getRole(int entityId, Integer activityId,
621            StatementOrBundle.Kind kind) {       
622
623        StatementOrBundle statement = _getUsedOrWasGeneratedBy(entityId,
624                activityId, kind);
625        
626        if(statement != null) {
627            // get the port name from the Role
628            List<Role> roles = ((HasRole)statement).getRole();
629            if(roles != null && !roles.isEmpty()) {
630                String roleStr = (String) roles.get(0).getValue();                            
631                return roleStr.substring(_wfName.length());
632            }
633        }
634        return null;
635    }
636    
637    /** Get a used or was generated by for the specified entity and
638     *  optional activity.
639     *  @param entityId the id of the entity
640     *  @param activityId the id of the activity. can be null
641     *  @param kind the kind of statement to find, either used or
642     *  was generated by.
643     */
644    private StatementOrBundle _getUsedOrWasGeneratedBy(int entityId,
645            Integer activityId,  StatementOrBundle.Kind kind) {       
646        
647        for(StatementOrBundle statement : _statements) {
648            if(statement.getKind() == kind) {
649                
650                QualifiedName activity;
651                QualifiedName entity;
652                if(kind == StatementOrBundle.Kind.PROV_USAGE) {
653                    activity = ((Used)statement).getActivity();
654                    entity = ((Used)statement).getEntity();
655                } else {
656                    activity = ((WasGeneratedBy)statement).getActivity();
657                    entity = ((WasGeneratedBy)statement).getEntity();
658                }
659
660                // find the matching entity
661                Matcher matcher = _ENTITY_ID_PATTERN.matcher(entity.getLocalPart());
662                if(matcher.matches()) {
663                    Integer curEntityId = Integer.valueOf(matcher.group(1));
664                    if(curEntityId.equals(Integer.valueOf(entityId))) {
665                    
666                        // see if activity was specified
667                        if(activityId != null) {
668                            // find the matching activity
669                            matcher = _ACTIVITY_ID_PATTERN.matcher(activity.getLocalPart());
670                            if(!matcher.matches()) {
671                                continue;
672                            } else {
673                                Integer curActivityId = Integer.valueOf(matcher.group(1));
674                                if(!curActivityId.equals(Integer.valueOf(activityId))) {
675                                    continue;
676                                }
677                            }
678                        }
679                        return statement;
680                    }
681                }
682            }
683        }
684        return null;
685    }
686
687    /** Perform initialization . */
688    private void _initialize() throws QueryException {
689        try {
690            _dataTypeFactory = DatatypeFactory.newInstance();
691        } catch (DatatypeConfigurationException e) {
692            throw new QueryException("Error create DataTypeFactory.", e);
693        }
694    }
695
696    ///////////////////////////////////////////////////////////////////
697    ////                       private fields                      ////
698
699    /** The statements in the PROV record. */
700    private List<StatementOrBundle> _statements;
701    
702    /** The workflow Entity. */
703    private Entity _wfEntity;
704    
705    /** The name of the workflow. */
706    private String _wfName;
707    
708    /** The execution id of the workflow. */
709    private final static int _EXECUTION_ID = 1;
710    
711    /** Factory for calendars. */
712    private DatatypeFactory _dataTypeFactory;
713    
714    /** Regex pattern for activity ids. */
715    private final static Pattern _ACTIVITY_ID_PATTERN = Pattern.compile("a(\\d+)");
716
717    /** Regex pattern for entity ids. */
718    private final static Pattern _ENTITY_ID_PATTERN = Pattern.compile("e(\\d+)");
719    
720    /** For testing. */
721    public static void main(String[] args) {
722        
723        try {
724
725            String file = "/home/crawl/KeplerData/workflows/MyWorkflows/prov/04-HelloWorld-run382.kar"; 
726            JarFile jar = new JarFile(file);
727            ZipEntry entry = jar.getEntry("04-HelloWorld.382.PROV.xml");
728            InputStream stream = jar.getInputStream(entry);
729            
730            FileOutputStream out = new FileOutputStream("/tmp/a.xml");
731            out.write(IOUtils.toByteArray(stream));
732            out.close();
733            stream.close();
734            jar.close();
735            
736            //ProvQuery query = new ProvQuery(stream, ProvFormat.XML);
737            
738            /*
739            String file = "/home/crawl/KeplerData/workflows/MyWorkflows/prov/04-HelloWorld.382.PROV.xml"; 
740            @SuppressWarnings("resource")
741            ProvQuery query = new ProvQuery(new FileInputStream(file), ProvFormat.XML);
742            */
743            
744            
745            //@SuppressWarnings("unused")
746            //String momlStr = query.getMoMLForExecution(_EXECUTION_ID);
747            //System.out.println("got moml");
748        } catch (Exception e) {
749            System.err.println("ERROR: " + e.getMessage());
750            e.printStackTrace();
751        }
752        
753    }
754    
755}