/*
 * File:     AbstractConstraint.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.search.content.query.model;

import java.util.HashMap;


/**
 * Super class for AnchorConstraint and DepedentConstraint
 *
 * @author Alexander Klassmann
 * @version November 2004
 */
abstract public class AbstractConstraint implements Constraint {
    /** Holds value of property DOCUMENT ME! */
    private final int nr;

    /** Holds value of property DOCUMENT ME! */
    protected final String[] tierNames;

    /** Holds value of property DOCUMENT ME! */
    private final String patternString;

    /** Holds value of property DOCUMENT ME! */
    private final long lowerBoundary;

    /** Holds value of property DOCUMENT ME! */
    private final long upperBoundary;

    /** Holds value of property DOCUMENT ME! */
    private final String unit;

    /** Holds value of property DOCUMENT ME! */
    private final boolean isRegEx;

    /** Holds value of property DOCUMENT ME! */
    private final boolean isCaseSensitive;

    /** Holds value of property DOCUMENT ME! */
    private final HashMap attributes;

    /**
     * DOCUMENT ME!
     *
     * @param index constraint number within a query
     * @param type CGN or EAF
     * @param fieldType fieldType resp. Track
     * @param patternString string/regular expression to be searched
     * @param lowerBoundary negative number (of units) (e.g. 0, -1, -2, ... -X)
     * @param upperBoundary positive number (of units) (e.g. 0, 1, 2 ... +X)
     * @param unit search unit in which should be searched (in respect to
     *        referential constraint)
     * @param refConstraint referential constraint
     * @param isRegEx string or regular expression ?
     * @param isCaseSensitive case sensitive string search ?
     * @param attributes should contain (as strings) attribute names (key) and
     *        values (value)
     */
    public AbstractConstraint(int index, String[] tierNames,
        String patternString, long lowerBoundary, long upperBoundary,
        String unit, boolean isRegEx, boolean isCaseSensitive,
        HashMap attributes) {
        this.nr = index;
        this.tierNames = tierNames;
        this.patternString = patternString;
        this.lowerBoundary = lowerBoundary;
        this.upperBoundary = upperBoundary;
        this.unit = unit;
        this.isRegEx = isRegEx;
        this.isCaseSensitive = isCaseSensitive;
        this.attributes = attributes;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#addAttribute(String, String)
     */
    public void addAttribute(String name, String value) {
        attributes.put(name, value);
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getAttributes()
     */
    public HashMap getAttributes() {
        return attributes;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getName()
     */
    public String getName() {
        return "Q" + (nr + 1);
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getNr()
     */
    public int getNr() {
        return nr;
    }

    /**
     * returns Quantifier like ("ANY" or "NONE")
     * @return String
     */
    public String getQuantifier() {
        return Constraint.ANY;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getPattern()
     */
    public String getPattern() {
        return patternString;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getUnit()
     */
    public String getUnit() {
        return unit;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getLowerBoundary()
     */
    public long getLowerBoundary() {
        return lowerBoundary;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getLowerBoundaryAsString()
     */
    public String getLowerBoundaryAsString() {
        return (lowerBoundary == Long.MIN_VALUE) ? "-X" : ("" + lowerBoundary);
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getUpperBoundary()
     */
    public long getUpperBoundary() {
        return upperBoundary;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getUpperBoundaryAsString()
     */
    public String getUpperBoundaryAsString() {
        return (upperBoundary == Long.MAX_VALUE) ? "+X" : ("" + upperBoundary);
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#isRegEx()
     */
    public boolean isRegEx() {
        return isRegEx;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#isCaseSensitive()
     */
    public boolean isCaseSensitive() {
        return isCaseSensitive;
    }

    /**
     *
     * @see mpi.search.content.query.model.Constraint#getMode()
     */
    public String getMode() {
        return Constraint.TEMPORAL;
    }

    /**
     *
     * @see java.lang.Object#equals(Object)
     */
    public boolean equals(Object object) {
        if (!(object instanceof AbstractConstraint)) {
            return false;
        }

        AbstractConstraint constraint = (AbstractConstraint) object;

        if (constraint.isCaseSensitive() != isCaseSensitive()) {
            return false;
        }

        if (constraint.isRegEx() != isRegEx()) {
            return false;
        }

        if (!constraint.getPattern().equals(getPattern())) {
            return false;
        }

        if (constraint.getLowerBoundary() != getLowerBoundary()) {
            return false;
        }

        if (constraint.getUpperBoundary() != getUpperBoundary()) {
            return false;
        }

        if (!constraint.getQuantifier().equals(getQuantifier())) {
            return false;
        }

        if (!constraint.getUnit().equals(getUnit())) {
            return false;
        }

        if (((constraint.getAttributes() == null) &&
                (constraint.getAttributes() != null)) ||
                ((constraint.getAttributes() != null) &&
                !constraint.getAttributes().equals(getAttributes()))) {
            return false;
        }

        return true;
    }
}
