/*
 * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * 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.
 *
 */
package com.arsdigita.search;

import com.arsdigita.util.Assert;

import java.util.Map;
import java.util.HashMap;

/**
 * A filter specification defines the parameters for 
 * a plugging into a condition defined by a filter type.
 * For example a 'list of category ids' would be used
 * in a 'restrict by category' filter condition..
 * These values are typically obtained from the user
 * via a web form.
 *
 * @see com.arsdigita.search.FilterType
 */
public abstract class FilterSpecification {
    
    private Map m_values;
    private FilterType m_type;
    
    /**
     * Creates a new filter specification, initializing
     * the value map from the array of values. The values
     * array should have an even number of elements, the
     * off elements are String keys, the even eleements 
     * are the corresponding Object values.
     *
     * @param type the filter type 
     * @param values the values for the filter type
     */
    protected FilterSpecification(Object[] values,
                                  FilterType type) {
        Assert.exists(values, Object.class);
        Assert.exists(type, FilterType.class);
        Assert.truth(values.length % 2 == 0, "length of value list is even");

        m_values = new HashMap();
        for (int i = 0 ; i < (values.length / 2) ; i++) {
            m_values.put((String)values[i*2], values[(i*2)+1]);
        }

        m_type = type;
    }
    
    /**
     * Get the values for the filter specification
     * @param key the value
     * @return the filter values
     */
    protected Object get(String key) {
        return m_values.get(key);
    }
    
    /**
     * Set the value for the specified key
     * @param key the key
     * @param value the value
     */
    protected void set(String key,
                       Object value) {
        m_values.put(key, value);
    }
    
    /**
     * Get the filter type
     * @return the filter type
     */
    public FilterType getType() {
        return m_type;
    }
    
    /**
     * Two filter specifications are considered equal
     * if they refer to the same filter type
     * and their parameter sets contain the same
     * (key, value) pairs
     */
    public boolean equals(Object o) {
        if (!(o instanceof FilterSpecification)) {
            return false;
        }
        
        FilterSpecification spec = (FilterSpecification)o;

        if (!m_type.equals(spec.getType())) {
            return false;
        }

        return m_values.equals(spec.m_values);
    }
    
    /**
     * Returns a hashcode compatible with the
     * definition of the equals() method
     */
    public int hashCode() {
        return m_values.hashCode();
    }
        
}
