org.opencastproject.mediapackage.AbstractMediaPackageElement Maven / Gradle / Ivy
/*
* 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.mediapackage;
import org.opencastproject.util.Checksum;
import org.opencastproject.util.IoSupport;
import org.opencastproject.util.MimeType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlTransient;
/**
* This class provides base functionality for media package elements.
*/
@XmlTransient
@XmlAccessorType(XmlAccessType.NONE)
public abstract class AbstractMediaPackageElement implements MediaPackageElement, Serializable {
/** Serial version uid */
private static final long serialVersionUID = 1L;
/** The element identifier */
@XmlID
@XmlAttribute(name = "id")
protected String id = null;
/** The element's type whithin the manifest: Track, Catalog etc. */
protected Type elementType = null;
/** The element's description */
protected String description = null;
/** The element's mime type, e. g. 'audio/mp3' */
@XmlElement(name = "mimetype")
protected MimeType mimeType = null;
/** The element's type, e. g. 'track/slide' */
@XmlAttribute(name = "type")
protected MediaPackageElementFlavor flavor = null;
/** The tags */
@XmlElementWrapper(name = "tags")
@XmlElement(name = "tag")
protected SortedSet tags = new TreeSet();
/** The element's location */
@XmlElement(name = "url")
protected URI uri = null;
/** Size in bytes */
@XmlElement(name = "size")
protected Long size = null;
/** The element's checksum */
@XmlElement(name = "checksum")
protected Checksum checksum = null;
/** The parent media package */
protected MediaPackage mediaPackage = null;
/** The optional reference to other elements or series */
@XmlAttribute(name = "ref")
protected MediaPackageReference reference = null;
/** Needed by JAXB */
protected AbstractMediaPackageElement() {
}
/**
* Creates a new media package element.
*
* @param elementType
* the type, e. g. Track, Catalog etc.
* @param flavor
* the flavor
* @param uri
* the elements location
*/
protected AbstractMediaPackageElement(Type elementType, MediaPackageElementFlavor flavor, URI uri) {
this(null, elementType, flavor, uri, null, null, null);
}
/**
* Creates a new media package element.
*
* @param elementType
* the type, e. g. Track, Catalog etc.
* @param flavor
* the flavor
* @param uri
* the elements location
* @param size
* the element size in bytes
* @param checksum
* the element checksum
* @param mimeType
* the element mime type
*/
protected AbstractMediaPackageElement(Type elementType, MediaPackageElementFlavor flavor, URI uri, Long size,
Checksum checksum, MimeType mimeType) {
this(null, elementType, flavor, uri, size, checksum, mimeType);
}
/**
* Creates a new media package element.
*
* @param id
* the element identifier withing the package
* @param elementType
* the type, e. g. Track, Catalog etc.
* @param flavor
* the flavor
* @param uri
* the elements location
* @param size
* the element size in bytes
* @param checksum
* the element checksum
* @param mimeType
* the element mime type
*/
protected AbstractMediaPackageElement(String id, Type elementType, MediaPackageElementFlavor flavor, URI uri,
Long size, Checksum checksum, MimeType mimeType) {
if (elementType == null)
throw new IllegalArgumentException("Argument 'elementType' is null");
this.id = id;
this.elementType = elementType;
this.flavor = flavor;
this.mimeType = mimeType;
this.uri = uri;
this.size = size;
this.checksum = checksum;
this.tags = new TreeSet();
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setIdentifier(String)
*/
@Override
public void setIdentifier(String id) {
this.id = id;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getIdentifier()
*/
@Override
public String getIdentifier() {
return id;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setTags(java.lang.String[])
*/
@Override
public void setTags(String[] tags) {
this.tags = new TreeSet(Arrays.asList(tags));
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#addTag(java.lang.String)
*/
@Override
public void addTag(String tag) {
if (tag == null)
throw new IllegalArgumentException("Tag must not be null");
tags.add(tag);
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#removeTag(java.lang.String)
*/
@Override
public void removeTag(String tag) {
if (tag == null)
return;
tags.remove(tag);
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#containsTag(java.lang.String)
*/
@Override
public boolean containsTag(String tag) {
if (tag == null || tags == null)
return false;
return tags.contains(tag);
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#containsTag(java.util.Collection)
*/
@Override
public boolean containsTag(Collection tags) {
if (tags == null || tags.size() == 0)
return true;
for (String tag : tags) {
if (containsTag(tag))
return true;
}
return false;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getTags()
*/
@Override
public String[] getTags() {
return tags.toArray(new String[tags.size()]);
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#clearTags()
*/
@Override
public void clearTags() {
if (tags != null)
tags.clear();
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getMediaPackage()
*/
@Override
public MediaPackage getMediaPackage() {
return mediaPackage;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getElementType()
*/
@Override
public Type getElementType() {
return elementType;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getElementDescription()
*/
@Override
public String getElementDescription() {
return (description != null) ? description : uri.toString();
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setElementDescription(String)
*/
@Override
public void setElementDescription(String name) {
this.description = name;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getReference()
*/
@Override
public MediaPackageReference getReference() {
return reference;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setReference(MediaPackageReference)
*/
@Override
public void setReference(MediaPackageReference reference) {
this.reference = reference;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getURI()
*/
@Override
public URI getURI() {
return uri;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setURI(java.net.URI)
*/
@Override
public void setURI(URI uri) {
this.uri = uri;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getChecksum()
*/
@Override
public Checksum getChecksum() {
return checksum;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setChecksum(org.opencastproject.util.Checksum)
*/
@Override
public void setChecksum(Checksum checksum) {
this.checksum = checksum;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getMimeType()
*/
@Override
public MimeType getMimeType() {
return mimeType;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setMimeType(org.opencastproject.util.MimeType)
*/
@Override
public void setMimeType(MimeType mimeType) {
this.mimeType = mimeType;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setFlavor(MediaPackageElementFlavor)
*/
@Override
public void setFlavor(MediaPackageElementFlavor flavor) {
this.flavor = flavor;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getFlavor()
*/
@Override
public MediaPackageElementFlavor getFlavor() {
return flavor;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#getSize()
*/
@Override
public long getSize() {
return size != null ? size : -1;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#setSize(long)
*/
@Override
public void setSize(long size) {
this.size = size;
}
/**
* Sets the parent media package.
*
* Note This method is only used by the media package and should not be called from elsewhere.
*
* @param mediaPackage
* the parent media package
*/
void setMediaPackage(MediaPackage mediaPackage) {
this.mediaPackage = mediaPackage;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#referTo(org.opencastproject.mediapackage.MediaPackageElement)
*/
@Override
public void referTo(MediaPackageElement element) {
referTo(new MediaPackageReferenceImpl(element));
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#referTo(org.opencastproject.mediapackage.MediaPackageReference)
*/
@Override
public void referTo(MediaPackageReference reference) {
// TODO: Check reference consistency
this.reference = reference;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#clearReference()
*/
@Override
public void clearReference() {
this.reference = null;
}
/**
* @see org.opencastproject.mediapackage.MediaPackageElement#verify()
*/
@Override
public void verify() throws MediaPackageException {
// TODO: Check availability at url
// TODO: Download (?) and check checksum
// Checksum c = calculateChecksum();
// if (checksum != null && !checksum.equals(c)) {
// throw new MediaPackageException("Checksum mismatch for " + this);
// }
// checksum = c;
}
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(MediaPackageElement o) {
return uri.toString().compareTo(o.getURI().toString());
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof MediaPackageElement))
return false;
MediaPackageElement e = (MediaPackageElement) obj;
if (mediaPackage != null && e.getMediaPackage() != null && !mediaPackage.equals(e.getMediaPackage()))
return false;
if (id != null && !id.equals(e.getIdentifier()))
return false;
if (uri != null && !uri.equals(e.getURI()))
return false;
return true;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((mediaPackage == null) ? 0 : mediaPackage.hashCode());
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
return result;
}
/**
* @see org.opencastproject.mediapackage.ManifestContributor#toManifest(org.w3c.dom.Document,
* org.opencastproject.mediapackage.MediaPackageSerializer)
*/
@Override
public Node toManifest(Document document, MediaPackageSerializer serializer) throws MediaPackageException {
Element node = document.createElement(elementType.toString().toLowerCase());
if (id != null)
node.setAttribute("id", id);
// Flavor
if (flavor != null)
node.setAttribute("type", flavor.toString());
// Reference
if (reference != null)
if (mediaPackage == null || !reference.matches(new MediaPackageReferenceImpl(mediaPackage)))
node.setAttribute("ref", reference.toString());
// Description
if (description != null) {
Element descriptionNode = document.createElement("description");
descriptionNode.appendChild(document.createTextNode(description));
node.appendChild(descriptionNode);
}
// Tags
if (tags.size() > 0) {
Element tagsNode = document.createElement("tags");
node.appendChild(tagsNode);
for (String tag : tags) {
Element tagNode = document.createElement("tag");
tagsNode.appendChild(tagNode);
tagNode.appendChild(document.createTextNode(tag));
}
}
// Url
Element urlNode = document.createElement("url");
String urlValue;
try {
urlValue = (serializer != null) ? serializer.encodeURI(uri).toString() : uri.toString();
} catch (URISyntaxException e) {
throw new MediaPackageException(e);
}
urlNode.appendChild(document.createTextNode(urlValue));
node.appendChild(urlNode);
// MimeType
if (mimeType != null) {
Element mimeNode = document.createElement("mimetype");
mimeNode.appendChild(document.createTextNode(mimeType.toString()));
node.appendChild(mimeNode);
}
// Size
if (size != null && size != -1) {
Element sizeNode = document.createElement("size");
sizeNode.appendChild(document.createTextNode(Long.toString(size)));
node.appendChild(sizeNode);
}
// Checksum
if (checksum != null) {
Element checksumNode = document.createElement("checksum");
checksumNode.setAttribute("type", checksum.getType().getName());
checksumNode.appendChild(document.createTextNode(checksum.getValue()));
node.appendChild(checksumNode);
}
return node;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
String s = (description != null) ? description : uri.toString();
return s.toLowerCase();
}
/**
* Attention: The media package reference is not being cloned so that calling getMediaPackage()
on the
* clone yields null.
*/
@Override
public Object clone() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = null;
try {
Marshaller marshaller = MediaPackageImpl.context.createMarshaller();
marshaller.marshal(this, out);
Unmarshaller unmarshaller = MediaPackageImpl.context.createUnmarshaller();
in = new ByteArrayInputStream(out.toByteArray());
// CHECKSTYLE:OFF
// in was already parsed and is therefore save
return unmarshaller.unmarshal(in);
// CHECKSTYLE:ON
} catch (JAXBException e) {
throw new RuntimeException(e.getLinkedException() != null ? e.getLinkedException() : e);
} finally {
IoSupport.closeQuietly(in);
}
}
}