WaveformWorkflowOperationHandler extends AbstractWorkflowOperationHandler { @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { MediaPackage mediaPackage = workflowInstance.getMediaPackage(); logger.info("Start waveform workflow operation for mediapackage {}", mediaPackage); String sourceFlavorProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(SOURCE_FLAVOR_PROPERTY)); String sourceTagsProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(SOURCE_TAGS_PROPERTY)); if (StringUtils.isEmpty(sourceFlavorProperty) && StringUtils.isEmpty(sourceTagsProperty)) { throw new WorkflowOperationException( String.format("Required property %s or %s not set", SOURCE_FLAVOR_PROPERTY, SOURCE_TAGS_PROPERTY)); } String targetFlavorProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(TARGET_FLAVOR_PROPERTY)); if (targetFlavorProperty == null) { throw new WorkflowOperationException(String.format("Required property %s not set", TARGET_FLAVOR_PROPERTY)); } String targetTagsProperty = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(TARGET_TAGS_PROPERTY)); int pixelsPerMinute = NumberUtils.toInt( StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(PIXELS_PER_MINUTE_PROPERTY)), DEFAULT_PIXELS_PER_MINUTE ); int minWidth = NumberUtils.toInt( StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(MIN_WIDTH_PROPERTY)), DEFAULT_MIN_WIDTH ); int maxWidth = NumberUtils.toInt( StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(MAX_WIDTH_PROPERTY)), DEFAULT_MAX_WIDTH ); int height = NumberUtils.toInt( StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(HEIGHT_PROPERTY)), DEFAULT_HEIGHT ); String color = StringUtils.trimToNull(workflowInstance.getCurrentOperation().getConfiguration(COLOR_PROPERTY)); try { TrackSelector trackSelector = new TrackSelector(); for (String flavor : asList(sourceFlavorProperty)) { trackSelector.addFlavor(flavor); } for (String tag : asList(sourceTagsProperty)) { trackSelector.addTag(tag); } Collection<Track> sourceTracks = trackSelector.select(mediaPackage, false); if (sourceTracks.isEmpty()) { logger.info("No tracks found in mediapackage {} with specified {} = {}", mediaPackage, SOURCE_FLAVOR_PROPERTY, sourceFlavorProperty); return createResult(mediaPackage, WorkflowOperationResult.Action.SKIP); } List<Job> waveformJobs = new ArrayList<>(sourceTracks.size()); for (Track sourceTrack : sourceTracks) { if (!sourceTrack.hasAudio()) { logger.info("Skipping waveform extraction of track {} since it has no audio", sourceTrack.getIdentifier()); continue; } try { logger.info("Creating waveform extraction job for track '{}' in mediapackage '{}'", sourceTrack.getIdentifier(), mediaPackage); Job waveformJob = waveformService.createWaveformImage(sourceTrack, pixelsPerMinute, minWidth, maxWidth, height, color); waveformJobs.add(waveformJob); } catch (MediaPackageException | WaveformServiceException e) { logger.error("Creating waveform extraction job for track '{}' in media package '{}' failed", sourceTrack.getIdentifier(), mediaPackage, e); } } logger.debug("Waiting for waveform jobs for media package {}", mediaPackage); if (!waitForStatus(waveformJobs.toArray(new Job[waveformJobs.size()])).isSuccess()) { throw new WorkflowOperationException(String.format("Waveform extraction jobs for media package '%s' have not completed successfully", mediaPackage.getIdentifier())); } for (Job job : waveformJobs) { String jobPayload = job.getPayload(); if (StringUtils.isEmpty(jobPayload)) { continue; } MediaPackageElement waveformMpe = null; try { waveformMpe = MediaPackageElementParser.getFromXml(jobPayload); URI newURI = workspace.moveTo(waveformMpe.getURI(), mediaPackage.getIdentifier().toString(), waveformMpe.getIdentifier(), "waveform.png"); waveformMpe.setURI(newURI); } catch (MediaPackageException ex) { throw new WorkflowOperationException("Can't parse waveform attachment from job " + job.getId()); } catch (NotFoundException ex) { throw new WorkflowOperationException("Waveform image file '" + waveformMpe.getURI() + "' not found", ex); } catch (IOException ex) { throw new WorkflowOperationException("Can't get workflow image file '" + waveformMpe.getURI() + "' from workspace"); } MediaPackageElementFlavor targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorProperty); if ("*".equals(targetFlavor.getType())) { targetFlavor = new MediaPackageElementFlavor(waveformMpe.getFlavor().getType(), targetFlavor.getSubtype()); } if ("*".equals(targetFlavor.getSubtype())) { targetFlavor = new MediaPackageElementFlavor(targetFlavor.getType(), waveformMpe.getFlavor().getSubtype()); } waveformMpe.setFlavor(targetFlavor); for (String tag : asList(targetTagsProperty)) { waveformMpe.addTag(tag); } mediaPackage.add(waveformMpe); } logger.info("Waveform workflow operation for mediapackage {} completed", mediaPackage); return createResult(mediaPackage, WorkflowOperationResult.Action.CONTINUE); } finally { try { workspace.cleanup(mediaPackage.getIdentifier(), true); } catch (IOException e) { throw new WorkflowOperationException(e); } } }  @Override void activate(ComponentContext cc); @Override WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context); void setWaveformService(WaveformService waveformService); void setWorkspace(Workspace workspace);  }
@Test public void testStart() throws Exception { EasyMock.expect(instance.getConfiguration("source-flavor")).andReturn("*/source").anyTimes(); EasyMock.replay(instance); Assert.assertTrue(handler.start(workflow, null).allowsContinue()); }
@Test public void testNoTracks() throws Exception { EasyMock.expect(instance.getConfiguration("source-flavor")).andReturn("*/nothing").anyTimes(); EasyMock.replay(instance); Assert.assertTrue(handler.start(workflow, null).allowsContinue()); }
@Test public void testNoAudio() throws Exception { track.setAudio(new LinkedList<>()); EasyMock.expect(instance.getConfiguration("source-flavor")).andReturn("*/source").anyTimes(); EasyMock.replay(instance); Assert.assertTrue(handler.start(workflow, null).allowsContinue()); }
@Test public void testMissingSource() throws Exception { EasyMock.replay(instance); try { handler.start(workflow, null); Assert.fail(); } catch (WorkflowOperationException e) { Assert.assertTrue(e.getMessage().startsWith("Required property ")); } }