/*
 * Copyright 2004-2005 The Trix Development Team.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.trix.cuery.filter;

import org.w3c.css.sac.Condition;
import org.w3c.css.sac.ConditionalSelector;
import org.w3c.css.sac.DescendantSelector;
import org.w3c.css.sac.Selector;
import org.w3c.css.sac.SiblingSelector;

/**
 * DOCUMENT.
 * 
 * @author <a href="mailto:Teletha.T@gmail.com">Teletha Testarossa</a>
 * @version $ Id: FilterUtil.java,v 1.0 2005/12/19 5:04:08 Teletha Exp $
 */
public final class FilterUtil {

    /**
     * Avoid creating FilterUtil instance.
     */
    private FilterUtil() {
    }

    /**
     * Check whether the given condition has the given filter or not.
     * 
     * @param condition A target condition.
     * @param clazz A target filter class.
     * @return A result.
     */
    public static boolean hasFilter(Condition condition, Class clazz) {
        // assert null
        if (condition == null || clazz == null) {
            return false;
        }

        if (clazz.isAssignableFrom(condition.getClass())) {
            return true;
        }

        if (condition instanceof MultipleFilter) {
            MultipleFilter filter = (MultipleFilter) condition;

            if (hasFilter(filter.getFirstCondition(), clazz)) {
                return true;
            }

            if (hasFilter(filter.getSecondCondition(), clazz)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check whether the given selector has the given filter or not.
     * 
     * @param selector A target selector.
     * @param clazz A target filter class.
     * @return A result.
     */
    public static boolean hasFilter(Selector selector, Class clazz) {
        // assert null
        if (selector == null || clazz == null) {
            return false;
        }

        switch (selector.getSelectorType()) {
        case Filter.SAC_CONDITIONAL_SELECTOR:
            ConditionalSelector conditional = (ConditionalSelector) selector;
            return hasFilter(conditional.getCondition(), clazz);

        case Filter.SAC_CHILD_SELECTOR:
        case Filter.SAC_DESCENDANT_SELECTOR:
            DescendantSelector descendant = (DescendantSelector) selector;

            if (hasFilter(descendant.getSimpleSelector(), clazz)) {
                return true;
            }
            return hasFilter(descendant.getAncestorSelector(), clazz);

        case Filter.SAC_DIRECT_ADJACENT_SELECTOR:
        case Filter.SAC_INDIRECT_ADJACENT_SELECTOR:
            SiblingSelector sibling = (SiblingSelector) selector;

            if (hasFilter(sibling.getSiblingSelector(), clazz)) {
                return true;
            }
            return hasFilter(sibling.getSelector(), clazz);

        default:
            return false;
        }
    }
}
