DiscreteDomain.java

/* Copyright 2015 Laurent COCAULT
 * Licensed to Laurent COCAULT under one or more contributor license agreements.
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. Laurent COCAULT licenses this file to You
 * 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.csp.constraint.model;

import java.util.Iterator;
import java.util.TreeSet;

/**
 * Represents a domain as a set of values.
 */
public class DiscreteDomain<T extends Value<T>> implements Domain<T> {

    /**
     * Values of the domain.
     */
    private TreeSet<T> values_;

    /**
     * Default constructor.
     */
    public DiscreteDomain() {
        values_ = new TreeSet<T>();
    }

    /**
     * Add a value to the domain.
     * @param value
     *            Value to add
     */
    public void addValue(final T value) {
        values_.add(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean contains(final Value<T> value) {
        return values_.contains(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Domain<T> copy() {
        final DiscreteDomain<T> copy = new DiscreteDomain<T>();
        copy.values_ = new TreeSet<T>(values_);
        return copy;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Value<T> getFirstValue() throws EmptyDomainException {
        if (values_.isEmpty()) {
            throw new EmptyDomainException();
        }
        return values_.first();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getSize() {
        return values_.size();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Value<T> getValue() throws UnboundDomainException {
        if (!hasSingleValue()) {
            throw new UnboundDomainException();
        }
        return getFirstValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasSingleValue() {
        return values_.size() == 1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEmpty() {
        return values_.isEmpty();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInDomain(final Value<T> value) {
        return values_.contains(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterator<T> iterator() {
        return values_.iterator();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean reduceToDomainIntersection(final Domain<T> other) {
        boolean domainChanged = false;
        final Iterator<T> values = values_.iterator();
        // Run through the possible values of the domain and check if it also in
        // the other domain. If a value is not found in the other domain it is
        // removed.
        while (values.hasNext()) {
            final Value<T> value = values.next();
            if (!other.isInDomain(value)) {
                // The value is not in the other domain, remove it
                values.remove();
                domainChanged = true;
            }
        }
        return domainChanged;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean removeValue(final Value<T> value) {
        return values_.remove(value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean setValue(final Value<T> value) {
        final boolean domainChanged = !(hasSingleValue() && isInDomain(value));
        if (domainChanged) {
            // The domain is reduced to only one value
            values_.clear();
            values_.add(value.value());
        }
        return domainChanged;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return values_.toString();
    }

}