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}