SeriesWorkflowOperationHandler extends AbstractWorkflowOperationHandler { @Override public WorkflowOperationResult start(final WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { logger.debug("Running series workflow operation"); MediaPackage mediaPackage = workflowInstance.getMediaPackage(); Opt<String> optSeries = getOptConfig(workflowInstance.getCurrentOperation(), SERIES_PROPERTY); Opt<String> optAttachFlavors = getOptConfig(workflowInstance.getCurrentOperation(), ATTACH_PROPERTY); Boolean applyAcl = getOptConfig(workflowInstance.getCurrentOperation(), APPLY_ACL_PROPERTY).map(toBoolean) .getOr(false); Opt<String> optCopyMetadata = getOptConfig(workflowInstance.getCurrentOperation(), COPY_METADATA_PROPERTY); String defaultNamespace = getOptConfig(workflowInstance.getCurrentOperation(), DEFAULT_NS_PROPERTY) .getOr(DublinCore.TERMS_NS_URI); logger.debug("Using default namespace: '{}'", defaultNamespace); if (optSeries.isSome() && !optSeries.get().equals(mediaPackage.getSeries())) { logger.info("Changing series id from '{}' to '{}'", StringUtils.trimToEmpty(mediaPackage.getSeries()), optSeries.get()); mediaPackage.setSeries(optSeries.get()); } String seriesId = mediaPackage.getSeries(); if (seriesId == null) { logger.info("No series set, skip operation"); return createResult(mediaPackage, Action.SKIP); } DublinCoreCatalog series; try { series = seriesService.getSeries(seriesId); } catch (NotFoundException e) { logger.info("No series with the identifier '{}' found, skip operation", seriesId); return createResult(mediaPackage, Action.SKIP); } catch (UnauthorizedException e) { logger.warn("Not authorized to get series with identifier '{}' found, skip operation", seriesId); return createResult(mediaPackage, Action.SKIP); } catch (SeriesException e) { logger.error("Unable to get series with identifier '{}', skip operation:", seriesId, e); throw new WorkflowOperationException(e); } mediaPackage.setSeriesTitle(series.getFirst(DublinCore.PROPERTY_TITLE)); HashSet<EName> extraMetadata = new HashSet<>(); if (optCopyMetadata.isSome()) { for (String strEName : optCopyMetadata.get().split(",+\\s*")) try { if (!strEName.isEmpty()) { extraMetadata.add(EName.fromString(strEName, defaultNamespace)); } } catch (IllegalArgumentException iae) { logger.warn("Ignoring incorrect dublincore metadata property: '{}'", strEName); } } for (Catalog episodeCatalog : mediaPackage.getCatalogs(MediaPackageElements.EPISODE)) { DublinCoreCatalog episodeDublinCore = DublinCoreUtil.loadDublinCore(workspace, episodeCatalog); episodeDublinCore.addBindings( XmlNamespaceContext.mk(XmlNamespaceBinding.mk(DublinCore.TERMS_NS_PREFIX, DublinCore.TERMS_NS_URI))); episodeDublinCore.addBindings(XmlNamespaceContext .mk(XmlNamespaceBinding.mk(DublinCore.ELEMENTS_1_1_NS_PREFIX, DublinCore.ELEMENTS_1_1_NS_URI))); episodeDublinCore.addBindings(XmlNamespaceContext .mk(XmlNamespaceBinding.mk(DublinCores.OC_PROPERTY_NS_PREFIX, DublinCores.OC_PROPERTY_NS_URI))); episodeDublinCore.set(DublinCore.PROPERTY_IS_PART_OF, seriesId); for (EName property : extraMetadata) { if (!episodeDublinCore.hasValue(property) && series.hasValue(property)) { episodeDublinCore.set(property, series.get(property)); } } try (InputStream in = IOUtils.toInputStream(episodeDublinCore.toXmlString(), "UTF-8")) { String filename = FilenameUtils.getName(episodeCatalog.getURI().toString()); URI uri = workspace.put(mediaPackage.getIdentifier().toString(), episodeCatalog.getIdentifier(), filename, in); episodeCatalog.setURI(uri); episodeCatalog.setChecksum(null); } catch (Exception e) { logger.error("Unable to update episode catalog isPartOf field", e); throw new WorkflowOperationException(e); } } if (optAttachFlavors.isSome()) { AbstractMediaPackageElementSelector<Catalog> catalogSelector = new CatalogSelector(); String[] seriesFlavors = StringUtils.split(optAttachFlavors.get(), ","); for (String flavor : seriesFlavors) { if ("*".equals(flavor)) { catalogSelector.addFlavor("**"); } else { flavor = MediaPackageElementFlavor.parseFlavor(flavorString); } for (SeriesCatalogUIAdapter a : adapters) { MediaPackageElementFlavor adapterFlavor = MediaPackageElementFlavor.parseFlavor(a.getFlavor().toString()); if (flavor.matches(adapterFlavor)) { if (MediaPackageElements.SERIES.eq(a.getFlavor().toString())) { addDublinCoreCatalog(series, MediaPackageElements.SERIES, mediaPackage); } else { try { Opt<byte[]> seriesElementData = seriesService.getSeriesElementData(seriesId, adapterFlavor.getType()); if (seriesElementData.isSome()) { DublinCoreCatalog catalog = DublinCores.read(new ByteArrayInputStream(seriesElementData.get())); addDublinCoreCatalog(catalog, adapterFlavor, mediaPackage); } else { logger.warn("No extended series catalog found for flavor '{}' and series '{}', skip adding catalog", adapterFlavor.getType(), seriesId); } } catch (SeriesException e) { logger.error("Unable to load extended series metadata for flavor {}", adapterFlavor.getType()); throw new WorkflowOperationException(e); } } } } } } if (applyAcl) { try { AccessControlList acl = seriesService.getSeriesAccessControl(seriesId); if (acl != null) authorizationService.setAcl(mediaPackage, AclScope.Series, acl); } catch (Exception e) { logger.error("Unable to update series ACL", e); throw new WorkflowOperationException(e); } } return createResult(mediaPackage, Action.CONTINUE); }  void setSeriesService(SeriesService seriesService); void setWorkspace(Workspace workspace); void setSecurityService(SecurityService securityService); void addCatalogUIAdapter(SeriesCatalogUIAdapter catalogUIAdapter); void removeCatalogUIAdapter(SeriesCatalogUIAdapter catalogUIAdapter); @Override WorkflowOperationResult start(final WorkflowInstance workflowInstance, JobContext context); static final String SERIES_PROPERTY; static final String ATTACH_PROPERTY; static final String APPLY_ACL_PROPERTY; static final String COPY_METADATA_PROPERTY; static final String DEFAULT_NS_PROPERTY; }
@Test public void testNoSeries() throws Exception { WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, "*"); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "true"); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.SKIP, result.getAction()); }
@Test public void testAclOnly() throws Exception { WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); operation.setConfiguration(SeriesWorkflowOperationHandler.SERIES_PROPERTY, "series1"); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, ""); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "true"); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.CONTINUE, result.getAction()); }
@Test public void testChangeSeries() throws Exception { WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); MediaPackage clone = (MediaPackage) mp.clone(); operation.setConfiguration(SeriesWorkflowOperationHandler.SERIES_PROPERTY, "series1"); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, "*"); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "false"); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.CONTINUE, result.getAction()); MediaPackage resultingMediapackage = result.getMediaPackage(); Assert.assertEquals("series1", resultingMediapackage.getSeries()); Assert.assertEquals("Series 1", resultingMediapackage.getSeriesTitle()); Assert.assertEquals(clone.getElements().length + 1, resultingMediapackage.getElements().length); }
@Test public void testAttachExtendedOnly() throws Exception { WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); MediaPackage clone = (MediaPackage) mp.clone(); operation.setConfiguration(SeriesWorkflowOperationHandler.SERIES_PROPERTY, "series1"); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, "creativecommons/*"); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "false"); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.CONTINUE, result.getAction()); MediaPackage resultingMediapackage = result.getMediaPackage(); Assert.assertEquals("series1", resultingMediapackage.getSeries()); Assert.assertEquals("Series 1", resultingMediapackage.getSeriesTitle()); Assert.assertEquals(clone.getElements().length + 1, resultingMediapackage.getElements().length); }
@Test public void testExtraMetadata() throws WorkflowOperationException { final EName otherProperty = new EName(DublinCore.TERMS_NS_URI, "my-custom-property"); final String otherValue = "foobar"; seriesCatalog.set(DublinCore.PROPERTY_LANGUAGE, "Opencastian"); seriesCatalog.set(otherProperty, otherValue); seriesCatalog.set(DublinCore.PROPERTY_CONTRIBUTOR, Arrays.asList( new DublinCoreValue[] { DublinCoreValue.mk("Mr. Contry Bute"), DublinCoreValue.mk("Mrs. Jane Doe") })); String[] extraMetadata = { DublinCore.PROPERTY_LANGUAGE.toString(), DublinCore.PROPERTY_CONTRIBUTOR.getLocalName(), otherProperty.toString(), "does-not-exist" }; WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); MediaPackage clone = (MediaPackage) mp.clone(); operation.setConfiguration(SeriesWorkflowOperationHandler.SERIES_PROPERTY, "series1"); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, "*"); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "false"); operation.setConfiguration(SeriesWorkflowOperationHandler.COPY_METADATA_PROPERTY, StringUtils.join(extraMetadata, ", ")); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.CONTINUE, result.getAction()); MediaPackage resultingMediapackage = result.getMediaPackage(); DublinCoreCatalog episodeCatalog = DublinCores.read(capturedStream.getValue()); Assert.assertEquals("series1", resultingMediapackage.getSeries()); Assert.assertEquals("Series 1", resultingMediapackage.getSeriesTitle()); Assert.assertEquals(clone.getElements().length + 1, resultingMediapackage.getElements().length); Assert.assertTrue(episodeCatalog.hasValue(DublinCore.PROPERTY_CONTRIBUTOR)); Assert.assertEquals(seriesCatalog.get(DublinCore.PROPERTY_CONTRIBUTOR), episodeCatalog.get(DublinCore.PROPERTY_CONTRIBUTOR)); Assert.assertTrue(episodeCatalog.hasValue(DublinCore.PROPERTY_LANGUAGE)); Assert.assertEquals(seriesCatalog.get(DublinCore.PROPERTY_LANGUAGE), episodeCatalog.get(DublinCore.PROPERTY_LANGUAGE)); Assert.assertTrue(episodeCatalog.hasValue(otherProperty)); Assert.assertEquals(seriesCatalog.get(otherProperty), episodeCatalog.get(otherProperty)); Assert.assertFalse(episodeCatalog.hasValue(new EName(DublinCore.TERMS_NS_URI, "does-not-exist"))); }
@Test public void testExtraMetadataDefaultNS() throws WorkflowOperationException { final EName customProperty = new EName(DublinCores.OC_PROPERTY_NS_URI, "my-custom-property"); final String customValue = "my-custom-value"; seriesCatalog.set(DublinCore.PROPERTY_LANGUAGE, "Opencastian"); seriesCatalog.set(DublinCore.PROPERTY_CONTRIBUTOR, Arrays.asList( new DublinCoreValue[] { DublinCoreValue.mk("Mr. Contry Bute"), DublinCoreValue.mk("Mrs. Jane Doe") })); seriesCatalog.set(customProperty, customValue); String[] extraMetadata = { DublinCore.PROPERTY_LANGUAGE.getLocalName(), DublinCore.PROPERTY_CONTRIBUTOR.getLocalName(), customProperty.getLocalName() }; WorkflowInstanceImpl instance = new WorkflowInstanceImpl(); List<WorkflowOperationInstance> ops = new ArrayList<WorkflowOperationInstance>(); WorkflowOperationInstanceImpl operation = new WorkflowOperationInstanceImpl("test", OperationState.INSTANTIATED); ops.add(operation); instance.setOperations(ops); instance.setMediaPackage(mp); MediaPackage clone = (MediaPackage) mp.clone(); operation.setConfiguration(SeriesWorkflowOperationHandler.SERIES_PROPERTY, "series1"); operation.setConfiguration(SeriesWorkflowOperationHandler.ATTACH_PROPERTY, "*"); operation.setConfiguration(SeriesWorkflowOperationHandler.APPLY_ACL_PROPERTY, "false"); operation.setConfiguration(SeriesWorkflowOperationHandler.COPY_METADATA_PROPERTY, StringUtils.join(extraMetadata, ", ")); operation.setConfiguration(SeriesWorkflowOperationHandler.DEFAULT_NS_PROPERTY, DublinCores.OC_PROPERTY_NS_URI); WorkflowOperationResult result = operationHandler.start(instance, null); Assert.assertEquals(Action.CONTINUE, result.getAction()); MediaPackage resultingMediapackage = result.getMediaPackage(); Assert.assertEquals("series1", resultingMediapackage.getSeries()); Assert.assertEquals("Series 1", resultingMediapackage.getSeriesTitle()); Assert.assertEquals(clone.getElements().length + 1, resultingMediapackage.getElements().length); DublinCoreCatalog episodeCatalog = DublinCores.read(capturedStream.getValue()); Assert.assertFalse(episodeCatalog.hasValue(DublinCore.PROPERTY_CONTRIBUTOR)); Assert.assertFalse(episodeCatalog.hasValue(DublinCore.PROPERTY_LANGUAGE)); Assert.assertTrue(episodeCatalog.hasValue(customProperty)); Assert.assertEquals(seriesCatalog.get(customProperty), episodeCatalog.get(customProperty)); }