/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in 
 * compliance with the License.  You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is Protege-2000.
 *
 * The Initial Developer of the Original Code is Stanford University. Portions
 * created by Stanford University are Copyright (C) 2007.  All Rights Reserved.
 *
 * Protege was developed by Stanford Medical Informatics
 * (http://www.smi.stanford.edu) at the Stanford University School of Medicine
 * with support from the National Library of Medicine, the National Science
 * Foundation, and the Defense Advanced Research Projects Agency.  Current
 * information about Protege can be obtained at http://protege.stanford.edu.
 *
 */

package edu.stanford.smi.protege.model.framestore;

import java.util.*;

import edu.stanford.smi.protege.model.*;
import edu.stanford.smi.protege.util.*;

/**
 * TODO Class Comment
 * 
 * @author Ray Fergerson <fergerson@smi.stanford.edu>
 */
public class Record {
    private Frame frame;
    private Slot slot;
    private Facet facet;
    private boolean isTemplate;
    private List values;
    private int hashCode;

    public Record(Frame frame, Slot slot, Facet facet, boolean isTemplate, Collection values) {
        set(frame, slot, facet, isTemplate);
        setValues(values);
    }

    Record() {
    }

    void set(Frame frame, Slot slot, Facet facet, boolean isTemplate) {
        this.frame = frame;
        this.slot = slot;
        this.facet = facet;
        this.isTemplate = isTemplate;
        this.hashCode = HashUtils.getHash(frame, slot, facet, isTemplate);
    }

    public int hashCode() {
        return hashCode;
    }

    public Frame getFrame() {
        return frame;
    }

    public Slot getSlot() {
        return slot;
    }

    public Facet getFacet() {
        return facet;
    }

    public boolean isTemplate() {
        return isTemplate;
    }

    public List getInternalValues() {
        //ESCA-JAVA0259 
        return values;
    }

    public int getValueCount() {
        return values.size();
    }

    public List getValues() {
        return (values.isEmpty()) ? Collections.EMPTY_LIST : new ArrayList(values);
    }

    public void setValues(Collection values) {
        this.values = new ArrayList(values);
    }

    public void addValue(Object o) {
        values.add(o);
    }

    public boolean removeValue(Object o) {
        return values.remove(o);
    }

    public void moveValue(int from, int to) {
        Object value = values.remove(from);
        values.add(to, value);
    }

    @SuppressWarnings("unchecked")
    public void replaceFrameReference(Frame replacementFrame) {
        if (replacementFrame.equals(frame)) {
            frame = replacementFrame;
        }
        if (replacementFrame.equals(slot)) {
            slot = (Slot) replacementFrame;
        }
        if (replacementFrame.equals(facet)) {
            facet = (Facet) replacementFrame;
        }
    }

    public void replaceFrameValue(Frame replacementFrame) {
        ListIterator i = values.listIterator();
        while (i.hasNext()) {
            Object o = i.next();
            if (replacementFrame.equals(o)) {
                i.set(replacementFrame);
            }
        }
    }

    public boolean isEmpty() {
        return values.isEmpty();
    }
    
    public String toString() {
      return "<Record " + frame.getFrameID().getName() + ":" + slot.getFrameID().getName()
                 + ":" + (facet == null ? "null" : facet.getFrameID().getName())
                 + ":" + isTemplate + ">";
    }

    public boolean equals(Object o) {
        boolean areEqual = false;
        if (o instanceof Record) {
            Record otherRecord = (Record) o;
            areEqual = equals(frame, otherRecord.frame) && equals(slot, otherRecord.slot)
                    && equals(facet, otherRecord.facet) && isTemplate == otherRecord.isTemplate;
        }
        return areEqual;
    }

    private static boolean equals(Object o1, Object o2) {
        return SystemUtilities.equals(o1, o2);
    }
}