001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.functor.range;
018
019import org.apache.commons.lang3.Validate;
020
021/**
022 * Represent an endpoint of a range. This can be the left endpoint or the right
023 * endpoint. It is also called left limit or right limit, and can be open
024 * (exclusive, unbounded) or closed (inclusive, bounded).
025 *
026 * @param <T> type of the value held by this endpoint
027 * @since 1.0
028 * @version $Revision$ $Date$
029 */
030public class Endpoint<T extends Comparable<?>> {
031
032    /**
033     * The endpoint value.
034     */
035    private final T value;
036
037    /**
038     * The endpoint bound type.
039     */
040    private final BoundType boundType;
041
042    /**
043     * Create an endpoint.
044     *
045     * @param value value
046     * @param boundType bound type
047     */
048    public Endpoint(T value, BoundType boundType) {
049        this.value = value;
050        this.boundType = Validate.notNull(boundType, "bound type must not be null");
051    }
052
053    /**
054     * @return Object
055     */
056    public T getValue() {
057        return value;
058    }
059
060    /**
061     * @return BoundType
062     */
063    public BoundType getBoundType() {
064        return boundType;
065    }
066
067    /**
068     * {@inheritDoc}
069     */
070    @Override
071    public String toString() {
072        String boundType = this.boundType == BoundType.OPEN ? "OPEN" : "CLOSED";
073        return "Endpoint<" + this.value + ", " + boundType + ">";
074    }
075
076    /**
077     * {@inheritDoc}
078     */
079    @Override
080    public boolean equals(Object obj) {
081        if (obj == this) {
082            return true;
083        }
084        if (!(obj instanceof Endpoint)) {
085            return false;
086        }
087        Endpoint<?> that = (Endpoint<?>) obj;
088        return this.boundType == that.boundType
089                && this.value.equals(that.value);
090    }
091
092    /**
093     * {@inheritDoc}
094     */
095    @Override
096    public int hashCode() {
097        int hash = "Endpoint".hashCode();
098        hash <<= 2;
099        hash ^= this.value.toString().hashCode();
100        hash <<= 2;
101        hash ^= Boolean.valueOf(this.boundType == BoundType.OPEN).hashCode();
102        return hash;
103    }
104
105    /**
106     * Print the left endpoint and bound type.
107     *
108     * @return String
109     */
110    public String toLeftString() {
111        return (this.boundType == BoundType.OPEN ? "(" : "[") + this.value;
112    }
113
114    /**
115     * Print the right endpoint and bound type.
116     *
117     * @return String
118     */
119    public String toRightString() {
120        return this.value + (this.boundType == BoundType.OPEN ? ")" : "]");
121    }
122
123}