/*
 * File:     LinguisticType.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.type;


/**
 * DOCUMENT ME!
 * $Id: LinguisticType.java,v 1.3 2005/07/26 13:45:50 hasloe Exp $
 * @author $Author: hasloe $
 * @version $Revision: 1.3 $
 */
public class LinguisticType {
    /** Holds value of property DOCUMENT ME! */
    String typeName;

    /** Holds value of property DOCUMENT ME! */
    Constraint constraints; // can be composite

    /** Holds value of property DOCUMENT ME! */
    boolean timeAlignable = true;

    /** Holds value of property DOCUMENT ME! */
    boolean graphicReferences = false;

    /* HS: added jun 04 support for controlled vocabularies */

    /** the identifier of the Controlled Vocabulary in use by this lin. type */
    String controlledVocabularyName;

    /**
     * Creates a new LinguisticType instance
     *
     * @param theName DOCUMENT ME!
     */
    public LinguisticType(String theName) {
        typeName = theName;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String toString() {
        String stereotype = "";

        if (constraints != null) {
            stereotype = Constraint.stereoTypes[constraints.getStereoType()];
        }

        return typeName + ", " + timeAlignable + ", " + stereotype;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getLinguisticTypeName() {
        return typeName;
    }

    /**
     * DOCUMENT ME!
     *
     * @param theName DOCUMENT ME!
     */
    public void setLinguisticTypeName(String theName) {
        typeName = theName;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean hasConstraints() {
        if (constraints != null) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public Constraint getConstraints() {
        return constraints;
    }

    /**
     * DOCUMENT ME!
     *
     * @param theConstraint DOCUMENT ME!
     */
    public void addConstraint(Constraint theConstraint) {
        //MK:02/06/30 removed println. If you need debug output, use debugln.
        //System.out.println("add Constraint of stereotype: " + theConstraint.getStereoType() + " to LinguisticType: " + typeName);
        if (constraints == null) {
            constraints = theConstraint;
        } else {
            constraints.addConstraint(theConstraint);
        }
    }

    /**
     * DOCUMENT ME!
     */
    public void removeConstraints() {
        constraints = null;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean isTimeAlignable() {
        return timeAlignable;
    }

    /**
     * DOCUMENT ME!
     *
     * @param isTimeAlignable DOCUMENT ME!
     */
    public void setTimeAlignable(boolean isTimeAlignable) {
        timeAlignable = isTimeAlignable;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public boolean hasGraphicReferences() {
        return graphicReferences;
    }

    /**
     * DOCUMENT ME!
     *
     * @param b DOCUMENT ME!
     */
    public void setGraphicReferences(boolean b) {
        graphicReferences = b;
    }

    /**
     * Returns whether or not annotation values on tiers using this LinguisticType
     * are restricted by a ControlledVocabulary.<br>
     * Current implementation is very loose; the value returned only depends
     * on the presence of a non-null reference string. Could be more strict
     * by keeping a flag independent from a reference string or object reference.
     *
     * @return true if there is a reference to a ControlledVocabulary
     */
    public boolean isUsingControlledVocabulary() {
        return ((controlledVocabularyName == null) ||
        (controlledVocabularyName.length() == 0)) ? false : true;
    }

    /**
     * Returns the name (identifier) of the ControlledVocabulary in use by
     * this type.<br>
     * The actual CV objects are stored in and managed by the Transcription.
     * (Candidate for change: might store a reference to the CV object itself
     * instead of using a reference to it.)
     *
     * @return the name/identifier of the cv
     */
    public String getControlledVocabylaryName() {
        return controlledVocabularyName;
    }

    /**
     * Sets the name of the ControlledVocabulary to be used by this type.
     *
     * @see #getControlledVocabylaryName()
     * @param name the name/identifier of the cv
     */
    public void setControlledVocabularyName(String name) {
        controlledVocabularyName = name;
    }

    /**
     * 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 LinguisticType)) {
            // it should be a MediaDescriptor object
            return false;
        }

        LinguisticType other = (LinguisticType) obj;

        if ((typeName != null) &&
                !typeName.equals(other.getLinguisticTypeName())) {
            return false;
        } else if ((other.getLinguisticTypeName() != null) &&
                !other.getLinguisticTypeName().equals(typeName)) {
            return false;
        }

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

        if (hasConstraints() != other.hasConstraints()) {
            return false;
        } else {
            if (hasConstraints() &&
                    !getConstraints().equals(other.getConstraints())) {
                return false;
            }
        }

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

        if (isUsingControlledVocabulary() != other.isUsingControlledVocabulary()) {
            return false;
        } else {
            if (isUsingControlledVocabulary()) {
                // can compare CV only by their name
                return getControlledVocabylaryName().equals(other.getControlledVocabylaryName());
            }
        }

        return true;
    }
}
