/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.message.broker.api.assetmanager; import static com.entwinemedia.fn.Prelude.chuck; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageException; import org.opencastproject.mediapackage.MediaPackageParser; import org.opencastproject.message.broker.api.MessageItem; import org.opencastproject.metadata.dublincore.DublinCoreCatalog; import org.opencastproject.metadata.dublincore.DublinCoreUtil; import org.opencastproject.metadata.dublincore.DublinCores; import org.opencastproject.security.api.AccessControlList; import org.opencastproject.security.api.AccessControlParser; import org.opencastproject.util.RequireUtil; import org.opencastproject.workspace.api.Workspace; import com.entwinemedia.fn.Fn; import com.entwinemedia.fn.data.Opt; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.Date; import javax.annotation.ParametersAreNonnullByDefault; /** * {@link Serializable} class that represents all of the possible messages sent through an AssetManager queue. */ @ParametersAreNonnullByDefault public abstract class AssetManagerItem implements MessageItem, Serializable { private static final long serialVersionUID = 5440420510139202434L; public static final String ASSETMANAGER_QUEUE_PREFIX = "ASSETMANAGER."; public static final String ASSETMANAGER_QUEUE = ASSETMANAGER_QUEUE_PREFIX + "QUEUE"; public enum Type { Update, Delete } // common fields private final String mediaPackageId; private final Date date; private AssetManagerItem(String mediaPackageId, Date date) { this.mediaPackageId = RequireUtil.notNull(mediaPackageId, "mediaPackageId"); this.date = RequireUtil.notNull(date, "date"); } public abstract Type getType(); public abstract <A> A decompose(Fn<? super TakeSnapshot, ? extends A> takeSnapshot, Fn<? super DeleteSnapshot, ? extends A> deleteSnapshot, Fn<? super DeleteEpisode, ? extends A> deleteEpisode); public final Date getDate() { return date; } @Override public final String getId() { return mediaPackageId; } /* * ------------------------------------------------------------------------------------------------------------------ */ /** * An event for taking a snapshot of a media package. */ public static final class TakeSnapshot extends AssetManagerItem { private static final long serialVersionUID = 3530625835200867594L; private final String mediapackage; private final String acl; private final long version; private final String episodeDublincore; private TakeSnapshot(String mediaPackageId, String mediapackage, String episodeDublincore, String acl, long version, Date date) { super(mediaPackageId, date); this.mediapackage = mediapackage; this.episodeDublincore = episodeDublincore; this.acl = acl; this.version = version; } @Override public <A> A decompose(Fn<? super TakeSnapshot, ? extends A> takeSnapshot, Fn<? super DeleteSnapshot, ? extends A> deleteSnapshot, Fn<? super DeleteEpisode, ? extends A> deleteEpisode) { return takeSnapshot.apply(this); } @Override public Type getType() { return Type.Update; } public MediaPackage getMediapackage() { try { return MediaPackageParser.getFromXml(mediapackage); } catch (MediaPackageException e) { return chuck(e); } } public AccessControlList getAcl() { return AccessControlParser.parseAclSilent(acl); } public Opt<DublinCoreCatalog> getEpisodeDublincore() { if (episodeDublincore == null) return Opt.none(); try (InputStream is = IOUtils.toInputStream(episodeDublincore, "UTF-8")) { return Opt.some(DublinCores.read(is)); } catch (IOException e) { return chuck(e); } } public long getVersion() { return version; } // public static final Fn<TakeSnapshot, MediaPackage> getMediaPackage = new Fn<TakeSnapshot, MediaPackage>() { @Override public MediaPackage apply(TakeSnapshot a) { return a.getMediapackage(); } }; public static final Fn<TakeSnapshot, Opt<DublinCoreCatalog>> getEpisodeDublincore = new Fn<TakeSnapshot, Opt<DublinCoreCatalog>>() { @Override public Opt<DublinCoreCatalog> apply(TakeSnapshot a) { return a.getEpisodeDublincore(); } }; public static final Fn<TakeSnapshot, AccessControlList> getAcl = new Fn<TakeSnapshot, AccessControlList>() { @Override public AccessControlList apply(TakeSnapshot a) { return a.getAcl(); } }; public static final Fn<TakeSnapshot, Long> getVersion = new Fn<TakeSnapshot, Long>() { @Override public Long apply(TakeSnapshot a) { return a.getVersion(); } }; } /* * ------------------------------------------------------------------------------------------------------------------ */ /** * An event for deleting a single version of a media package (aka snapshot). */ public static final class DeleteSnapshot extends AssetManagerItem { private static final long serialVersionUID = 4797196156230502250L; private final long version; private DeleteSnapshot(String mediaPackageId, long version, Date date) { super(mediaPackageId, date); this.version = version; } @Override public <A> A decompose(Fn<? super TakeSnapshot, ? extends A> takeSnapshot, Fn<? super DeleteSnapshot, ? extends A> deleteSnapshot, Fn<? super DeleteEpisode, ? extends A> deleteEpisode) { return deleteSnapshot.apply(this); } @Override public Type getType() { return Type.Delete; } public String getMediaPackageId() { return getId(); } public long getVersion() { return version; } public static final Fn<DeleteSnapshot, String> getMediaPackageId = new Fn<DeleteSnapshot, String>() { @Override public String apply(DeleteSnapshot a) { return a.getMediaPackageId(); } }; public static final Fn<DeleteSnapshot, Long> getVersion = new Fn<DeleteSnapshot, Long>() { @Override public Long apply(DeleteSnapshot a) { return a.getVersion(); } }; } /* * ------------------------------------------------------------------------------------------------------------------ */ /** * A event that will be sent when all versions of a media package (aka the whole episode) have been deleted. */ public static final class DeleteEpisode extends AssetManagerItem { private static final long serialVersionUID = -4906056424740181256L; private DeleteEpisode(String mediaPackageId, Date date) { super(mediaPackageId, date); } @Override public <A> A decompose(Fn<? super TakeSnapshot, ? extends A> takeSnapshot, Fn<? super DeleteSnapshot, ? extends A> deleteSnapshot, Fn<? super DeleteEpisode, ? extends A> deleteEpisode) { return deleteEpisode.apply(this); } @Override public Type getType() { return Type.Delete; } public String getMediaPackageId() { return getId(); } public static final Fn<DeleteEpisode, String> getMediaPackageId = new Fn<DeleteEpisode, String>() { @Override public String apply(DeleteEpisode a) { return a.getMediaPackageId(); } }; } /* * ------------------------------------------------------------------------------------------------------------------ */ // // constructor methods // /** * @param workspace * The workspace * @param mp * The media package to update. * @param acl * The access control list of the media package to update. * @param version * The version of the media package. * @param date * The modification date. * @return Builds a {@link AssetManagerItem} for taking a media package snapshot. */ public static TakeSnapshot add(Workspace workspace, MediaPackage mp, AccessControlList acl, long version, Date date) { String dc = null; Opt<DublinCoreCatalog> episodeDublincore = DublinCoreUtil.loadEpisodeDublinCore(workspace, mp); if (episodeDublincore.isSome()) { try { dc = episodeDublincore.get().toXmlString(); } catch (IOException e) { throw new IllegalStateException( String.format("Not able to serialize the episode dublincore catalog %s.", episodeDublincore.get()), e); } } return new TakeSnapshot(mp.getIdentifier().compact(), MediaPackageParser.getAsXml(mp), dc, AccessControlParser.toJsonSilent(acl), version, date); } /** * @param mediaPackageId * The unique id of the media package to delete. * @param version * The episode's version. * @param date * The modification date. * @return Builds {@link AssetManagerItem} for deleting a snapshot from the asset manager. */ public static AssetManagerItem deleteSnapshot(String mediaPackageId, long version, Date date) { return new DeleteSnapshot(mediaPackageId, version, date); } /** * @param mediaPackageId * The unique id of the media package to delete. * @param date * The modification date. * @return Builds {@link AssetManagerItem} for deleting an episode from the asset manager. */ public static AssetManagerItem deleteEpisode(String mediaPackageId, Date date) { return new DeleteEpisode(mediaPackageId, date); } }