@Test(expected = WorkflowOperationException.class) public void testNoChannelIdThrowsException() throws WorkflowOperationException { MediaPackage mediapackage = EasyMock.createNiceMock(MediaPackage.class); WorkflowOperationInstance workflowOperationInstance = EasyMock.createNiceMock(WorkflowOperationInstance.class); WorkflowInstance workflowInstance = EasyMock.createNiceMock(WorkflowInstance.class); EasyMock.expect(workflowInstance.getMediaPackage()).andStubReturn(mediapackage); EasyMock.expect(workflowInstance.getCurrentOperation()).andStubReturn(workflowOperationInstance); JobContext jobContext = EasyMock.createNiceMock(JobContext.class); EasyMock.replay(jobContext, mediapackage, workflowInstance, workflowOperationInstance); ConfigurablePublishWorkflowOperationHandler configurePublish = new ConfigurablePublishWorkflowOperationHandler(); configurePublish.start(workflowInstance, jobContext); }
@Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { RequireUtil.notNull(workflowInstance, "workflowInstance"); final MediaPackage mp = workflowInstance.getMediaPackage(); final WorkflowOperationInstance op = workflowInstance.getCurrentOperation(); final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY)); if ("".equals(channelId)) { throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements."); } final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN)); MimeType mimetype = null; String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE)); if (!"".equals(mimetypeString)) { try { mimetype = MimeTypes.parseMimeType(mimetypeString); } catch (IllegalArgumentException e) { throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e); } } final boolean withPublishedElements = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS))); boolean checkAvailability = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY))); boolean retractStreaming = RETRACT_STREAMING_DEFAULT; String retractStreamingString = workflowInstance.getConfiguration(RETRACT_STREAMING); if (retractStreamingString != null) { retractStreaming = BooleanUtils.toBoolean(StringUtils.trimToEmpty(retractStreamingString)); } if (getPublications(mp, channelId).size() > 0) { final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY)); switch (rePublishStrategy) { case ("fail"): fail(mp); break; case ("merge"): break; default: retract(mp, channelId, retractStreaming); } } String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE)); if ("".equals(mode)) { mode = DEFAULT_MODE; } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) { logger.error("Unknown value for configuration key mode: '{}'", mode); throw new IllegalArgumentException("Unknown value for configuration key mode"); } final String[] downloadSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_FLAVORS)), ","); final String[] downloadSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_TAGS)), ","); final String[] streamingSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_FLAVORS)), ","); final String[] streamingSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_TAGS)), ","); String publicationUUID = UUID.randomUUID().toString(); Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null); final SimpleElementSelector downloadSelector = new SimpleElementSelector(); for (String flavor : downloadSourceFlavors) { downloadSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : downloadSourceTags) { downloadSelector.addTag(tag); } final SimpleElementSelector streamingSelector = new SimpleElementSelector(); for (String flavor : streamingSourceFlavors) { streamingSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : streamingSourceTags) { streamingSelector.addTag(tag); } boolean streamingElementsDistributed = false; boolean downloadElementsDistributed = false; if (streamingDistributionService.publishToStreaming() && (streamingSourceFlavors.length > 0 || streamingSourceTags.length > 0)) { streamingElementsDistributed = distributeElements(streamingSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, true); } if (downloadSourceFlavors.length > 0 || downloadSourceTags.length > 0) { downloadElementsDistributed = distributeElements(downloadSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, false); } if (!downloadElementsDistributed && !streamingElementsDistributed) { return createResult(mp, Action.SKIP); } if (!"".equals(urlPattern)) { publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID)); } if (mimetype != null) { publication.setMimeType(mimetype); } mp.add(publication); return createResult(mp, Action.CONTINUE); }
ConfigurablePublishWorkflowOperationHandler extends ConfigurableWorkflowOperationHandlerBase { @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { RequireUtil.notNull(workflowInstance, "workflowInstance"); final MediaPackage mp = workflowInstance.getMediaPackage(); final WorkflowOperationInstance op = workflowInstance.getCurrentOperation(); final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY)); if ("".equals(channelId)) { throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements."); } final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN)); MimeType mimetype = null; String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE)); if (!"".equals(mimetypeString)) { try { mimetype = MimeTypes.parseMimeType(mimetypeString); } catch (IllegalArgumentException e) { throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e); } } final boolean withPublishedElements = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS))); boolean checkAvailability = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY))); boolean retractStreaming = RETRACT_STREAMING_DEFAULT; String retractStreamingString = workflowInstance.getConfiguration(RETRACT_STREAMING); if (retractStreamingString != null) { retractStreaming = BooleanUtils.toBoolean(StringUtils.trimToEmpty(retractStreamingString)); } if (getPublications(mp, channelId).size() > 0) { final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY)); switch (rePublishStrategy) { case ("fail"): fail(mp); break; case ("merge"): break; default: retract(mp, channelId, retractStreaming); } } String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE)); if ("".equals(mode)) { mode = DEFAULT_MODE; } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) { logger.error("Unknown value for configuration key mode: '{}'", mode); throw new IllegalArgumentException("Unknown value for configuration key mode"); } final String[] downloadSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_FLAVORS)), ","); final String[] downloadSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_TAGS)), ","); final String[] streamingSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_FLAVORS)), ","); final String[] streamingSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_TAGS)), ","); String publicationUUID = UUID.randomUUID().toString(); Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null); final SimpleElementSelector downloadSelector = new SimpleElementSelector(); for (String flavor : downloadSourceFlavors) { downloadSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : downloadSourceTags) { downloadSelector.addTag(tag); } final SimpleElementSelector streamingSelector = new SimpleElementSelector(); for (String flavor : streamingSourceFlavors) { streamingSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : streamingSourceTags) { streamingSelector.addTag(tag); } boolean streamingElementsDistributed = false; boolean downloadElementsDistributed = false; if (streamingDistributionService.publishToStreaming() && (streamingSourceFlavors.length > 0 || streamingSourceTags.length > 0)) { streamingElementsDistributed = distributeElements(streamingSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, true); } if (downloadSourceFlavors.length > 0 || downloadSourceTags.length > 0) { downloadElementsDistributed = distributeElements(downloadSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, false); } if (!downloadElementsDistributed && !streamingElementsDistributed) { return createResult(mp, Action.SKIP); } if (!"".equals(urlPattern)) { publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID)); } if (mimetype != null) { publication.setMimeType(mimetype); } mp.add(publication); return createResult(mp, Action.CONTINUE); } }
ConfigurablePublishWorkflowOperationHandler extends ConfigurableWorkflowOperationHandlerBase { @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { RequireUtil.notNull(workflowInstance, "workflowInstance"); final MediaPackage mp = workflowInstance.getMediaPackage(); final WorkflowOperationInstance op = workflowInstance.getCurrentOperation(); final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY)); if ("".equals(channelId)) { throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements."); } final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN)); MimeType mimetype = null; String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE)); if (!"".equals(mimetypeString)) { try { mimetype = MimeTypes.parseMimeType(mimetypeString); } catch (IllegalArgumentException e) { throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e); } } final boolean withPublishedElements = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS))); boolean checkAvailability = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY))); boolean retractStreaming = RETRACT_STREAMING_DEFAULT; String retractStreamingString = workflowInstance.getConfiguration(RETRACT_STREAMING); if (retractStreamingString != null) { retractStreaming = BooleanUtils.toBoolean(StringUtils.trimToEmpty(retractStreamingString)); } if (getPublications(mp, channelId).size() > 0) { final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY)); switch (rePublishStrategy) { case ("fail"): fail(mp); break; case ("merge"): break; default: retract(mp, channelId, retractStreaming); } } String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE)); if ("".equals(mode)) { mode = DEFAULT_MODE; } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) { logger.error("Unknown value for configuration key mode: '{}'", mode); throw new IllegalArgumentException("Unknown value for configuration key mode"); } final String[] downloadSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_FLAVORS)), ","); final String[] downloadSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_TAGS)), ","); final String[] streamingSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_FLAVORS)), ","); final String[] streamingSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_TAGS)), ","); String publicationUUID = UUID.randomUUID().toString(); Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null); final SimpleElementSelector downloadSelector = new SimpleElementSelector(); for (String flavor : downloadSourceFlavors) { downloadSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : downloadSourceTags) { downloadSelector.addTag(tag); } final SimpleElementSelector streamingSelector = new SimpleElementSelector(); for (String flavor : streamingSourceFlavors) { streamingSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : streamingSourceTags) { streamingSelector.addTag(tag); } boolean streamingElementsDistributed = false; boolean downloadElementsDistributed = false; if (streamingDistributionService.publishToStreaming() && (streamingSourceFlavors.length > 0 || streamingSourceTags.length > 0)) { streamingElementsDistributed = distributeElements(streamingSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, true); } if (downloadSourceFlavors.length > 0 || downloadSourceTags.length > 0) { downloadElementsDistributed = distributeElements(downloadSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, false); } if (!downloadElementsDistributed && !streamingElementsDistributed) { return createResult(mp, Action.SKIP); } if (!"".equals(urlPattern)) { publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID)); } if (mimetype != null) { publication.setMimeType(mimetype); } mp.add(publication); return createResult(mp, Action.CONTINUE); }  }
ConfigurablePublishWorkflowOperationHandler extends ConfigurableWorkflowOperationHandlerBase { @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { RequireUtil.notNull(workflowInstance, "workflowInstance"); final MediaPackage mp = workflowInstance.getMediaPackage(); final WorkflowOperationInstance op = workflowInstance.getCurrentOperation(); final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY)); if ("".equals(channelId)) { throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements."); } final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN)); MimeType mimetype = null; String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE)); if (!"".equals(mimetypeString)) { try { mimetype = MimeTypes.parseMimeType(mimetypeString); } catch (IllegalArgumentException e) { throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e); } } final boolean withPublishedElements = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS))); boolean checkAvailability = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY))); boolean retractStreaming = RETRACT_STREAMING_DEFAULT; String retractStreamingString = workflowInstance.getConfiguration(RETRACT_STREAMING); if (retractStreamingString != null) { retractStreaming = BooleanUtils.toBoolean(StringUtils.trimToEmpty(retractStreamingString)); } if (getPublications(mp, channelId).size() > 0) { final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY)); switch (rePublishStrategy) { case ("fail"): fail(mp); break; case ("merge"): break; default: retract(mp, channelId, retractStreaming); } } String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE)); if ("".equals(mode)) { mode = DEFAULT_MODE; } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) { logger.error("Unknown value for configuration key mode: '{}'", mode); throw new IllegalArgumentException("Unknown value for configuration key mode"); } final String[] downloadSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_FLAVORS)), ","); final String[] downloadSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_TAGS)), ","); final String[] streamingSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_FLAVORS)), ","); final String[] streamingSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_TAGS)), ","); String publicationUUID = UUID.randomUUID().toString(); Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null); final SimpleElementSelector downloadSelector = new SimpleElementSelector(); for (String flavor : downloadSourceFlavors) { downloadSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : downloadSourceTags) { downloadSelector.addTag(tag); } final SimpleElementSelector streamingSelector = new SimpleElementSelector(); for (String flavor : streamingSourceFlavors) { streamingSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : streamingSourceTags) { streamingSelector.addTag(tag); } boolean streamingElementsDistributed = false; boolean downloadElementsDistributed = false; if (streamingDistributionService.publishToStreaming() && (streamingSourceFlavors.length > 0 || streamingSourceTags.length > 0)) { streamingElementsDistributed = distributeElements(streamingSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, true); } if (downloadSourceFlavors.length > 0 || downloadSourceTags.length > 0) { downloadElementsDistributed = distributeElements(downloadSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, false); } if (!downloadElementsDistributed && !streamingElementsDistributed) { return createResult(mp, Action.SKIP); } if (!"".equals(urlPattern)) { publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID)); } if (mimetype != null) { publication.setMimeType(mimetype); } mp.add(publication); return createResult(mp, Action.CONTINUE); }  URI populateUrlWithVariables(String urlPattern, MediaPackage mp, String pubUUID); @Override WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context); }
ConfigurablePublishWorkflowOperationHandler extends ConfigurableWorkflowOperationHandlerBase { @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { RequireUtil.notNull(workflowInstance, "workflowInstance"); final MediaPackage mp = workflowInstance.getMediaPackage(); final WorkflowOperationInstance op = workflowInstance.getCurrentOperation(); final String channelId = StringUtils.trimToEmpty(op.getConfiguration(CHANNEL_ID_KEY)); if ("".equals(channelId)) { throw new WorkflowOperationException("Unable to publish this mediapackage as the configuration key " + CHANNEL_ID_KEY + " is missing. Unable to determine where to publish these elements."); } final String urlPattern = StringUtils.trimToEmpty(op.getConfiguration(URL_PATTERN)); MimeType mimetype = null; String mimetypeString = StringUtils.trimToEmpty(op.getConfiguration(MIME_TYPE)); if (!"".equals(mimetypeString)) { try { mimetype = MimeTypes.parseMimeType(mimetypeString); } catch (IllegalArgumentException e) { throw new WorkflowOperationException("Unable to parse the provided configuration for " + MIME_TYPE, e); } } final boolean withPublishedElements = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(WITH_PUBLISHED_ELEMENTS))); boolean checkAvailability = BooleanUtils .toBoolean(StringUtils.trimToEmpty(op.getConfiguration(CHECK_AVAILABILITY))); boolean retractStreaming = RETRACT_STREAMING_DEFAULT; String retractStreamingString = workflowInstance.getConfiguration(RETRACT_STREAMING); if (retractStreamingString != null) { retractStreaming = BooleanUtils.toBoolean(StringUtils.trimToEmpty(retractStreamingString)); } if (getPublications(mp, channelId).size() > 0) { final String rePublishStrategy = StringUtils.trimToEmpty(op.getConfiguration(STRATEGY)); switch (rePublishStrategy) { case ("fail"): fail(mp); break; case ("merge"): break; default: retract(mp, channelId, retractStreaming); } } String mode = StringUtils.trimToEmpty(op.getConfiguration(MODE)); if ("".equals(mode)) { mode = DEFAULT_MODE; } else if (!ArrayUtils.contains(KNOWN_MODES, mode)) { logger.error("Unknown value for configuration key mode: '{}'", mode); throw new IllegalArgumentException("Unknown value for configuration key mode"); } final String[] downloadSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_FLAVORS)), ","); final String[] downloadSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(DOWNLOAD_SOURCE_TAGS)), ","); final String[] streamingSourceFlavors = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_FLAVORS)), ","); final String[] streamingSourceTags = StringUtils.split(StringUtils.trimToEmpty(op.getConfiguration(STREAMING_SOURCE_TAGS)), ","); String publicationUUID = UUID.randomUUID().toString(); Publication publication = PublicationImpl.publication(publicationUUID, channelId, null, null); final SimpleElementSelector downloadSelector = new SimpleElementSelector(); for (String flavor : downloadSourceFlavors) { downloadSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : downloadSourceTags) { downloadSelector.addTag(tag); } final SimpleElementSelector streamingSelector = new SimpleElementSelector(); for (String flavor : streamingSourceFlavors) { streamingSelector.addFlavor(MediaPackageElementFlavor.parseFlavor(flavor)); } for (String tag : streamingSourceTags) { streamingSelector.addTag(tag); } boolean streamingElementsDistributed = false; boolean downloadElementsDistributed = false; if (streamingDistributionService.publishToStreaming() && (streamingSourceFlavors.length > 0 || streamingSourceTags.length > 0)) { streamingElementsDistributed = distributeElements(streamingSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, true); } if (downloadSourceFlavors.length > 0 || downloadSourceTags.length > 0) { downloadElementsDistributed = distributeElements(downloadSelector, mp, publication, channelId, mode, withPublishedElements, checkAvailability, false); } if (!downloadElementsDistributed && !streamingElementsDistributed) { return createResult(mp, Action.SKIP); } if (!"".equals(urlPattern)) { publication.setURI(populateUrlWithVariables(urlPattern, mp, publicationUUID)); } if (mimetype != null) { publication.setMimeType(mimetype); } mp.add(publication); return createResult(mp, Action.CONTINUE); }  URI populateUrlWithVariables(String urlPattern, MediaPackage mp, String pubUUID); @Override WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context);  }