/*
 * File:     LinkedFileDescriptor.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.server.corpora.clomimpl.abstr;


/**
 * A descriptor for any kind of file that is linked to or associated with  a
 * transcription, other than audio and video files (or the subjects of
 * transcription).  All fields are public.
 * NB: an interface and abstract super class could/should be created that
 * is extended by this class and MediaDescriptors.
 *
 * @author Han Sloetjes
 */
public class LinkedFileDescriptor implements Cloneable {
    /** Holds value of constant unknown MIME type */
    public final static String UNKNOWN_MIME_TYPE = "unknown";

    /** text MIME type */
    public final static String TEXT_TYPE = "text/plain";

    /** xml MIME type */
    public final static String XML_TYPE = "text/xml";

    /** svg MIME type */
    public final static String SVG_TYPE = "image/svg+xml";

    /** the url of the linked file */
    public String linkURL;

    /** the mimetype string */
    public String mimeType;

    /** the time origin or offset */
    public long timeOrigin;

    /**
     * the url of a media file that this file is associated with  in whichever
     * way
     */
    public String associatedWith;

    /**
     * the url of a configuration file that might contain information  on how
     * to treat this file
     */
    public String configFile; //??

    /**
     * Constructor.
     *
     * @param linkURL the url of the linked file
     * @param mimeType a mimetype string
     *
     * @throws NullPointerException if the link url is null
     */
    public LinkedFileDescriptor(String linkURL, String mimeType) {
        if (linkURL == null) {
            throw new NullPointerException();
        }

        this.linkURL = linkURL;

        if (mimeType != null) {
            this.mimeType = mimeType;
        } else {
            this.mimeType = UNKNOWN_MIME_TYPE;
        }
    }

    /**
     * Returns a string representation of this descriptor
     *
     * @return a string representation of this descriptor
     */
    public String toString() {
        return linkURL + " " + mimeType + " " + timeOrigin + " " +
        associatedWith + " " + configFile;
    }

    /**
     * Returns a deep copy of this LinkedFileDescriptor.
     *
     * @return a deep copy of this LinkedFileDescriptor
     */
    public Object clone() {
        try {
            LinkedFileDescriptor cloneLFD = (LinkedFileDescriptor) super.clone();

            if (linkURL != null) {
                cloneLFD.linkURL = new String(linkURL);
            }

            if (mimeType != null) {
                cloneLFD.mimeType = new String(mimeType);
            }

            if (associatedWith != null) {
                cloneLFD.associatedWith = new String(associatedWith);
            }

            if (configFile != null) {
                cloneLFD.configFile = new String(configFile);
            }

            cloneLFD.timeOrigin = timeOrigin;

            return cloneLFD;
        } catch (CloneNotSupportedException cnse) {
            // should not happen
            // throw an exception?
            return null;
        }
    }

    /**
     * Overrides <code>Object</code>'s equals method by checking all  fields of
     * the other object to be equal to all fields in this  object.
     *
     * @param obj the reference object with which to compare
     *
     * @return true if this object is the same as the obj argument; false
     *         otherwise
     */
    public boolean equals(Object obj) {
        if (obj == null) {
            // null is never equal
            return false;
        }

        if (obj == this) {
            // same object reference 
            return true;
        }

        if (!(obj instanceof LinkedFileDescriptor)) {
            // it should be a LinkedFileDescriptor object
            return false;
        }

        // check the fields
        LinkedFileDescriptor other = (LinkedFileDescriptor) obj;

        if (((this.linkURL != null) && (other.linkURL == null)) ||
                ((this.linkURL == null) && (other.linkURL != null)) ||
                ((this.linkURL != null) && (other.linkURL != null) &&
                !this.linkURL.equals(other.linkURL))) {
            return false;
        }

        if (((this.mimeType != null) && (other.mimeType == null)) ||
                ((this.mimeType == null) && (other.mimeType != null)) ||
                ((this.mimeType != null) && (other.mimeType != null) &&
                !this.mimeType.equals(other.mimeType))) {
            return false;
        }

        if (((this.associatedWith != null) && (other.associatedWith == null)) ||
                ((this.associatedWith == null) &&
                (other.associatedWith != null)) ||
                ((this.associatedWith != null) &&
                (other.associatedWith != null) &&
                !this.associatedWith.equals(other.associatedWith))) {
            return false;
        }

        if (((this.configFile != null) && (other.configFile == null)) ||
                ((this.configFile == null) && (other.configFile != null)) ||
                ((this.configFile != null) && (other.configFile != null) &&
                !this.configFile.equals(other.configFile))) {
            return false;
        }

        if (this.timeOrigin != other.timeOrigin) {
            return false;
        }

        return true;
    }
}
