/* * Copyright (C) 2015 Artificial Intelligence * Laboratory @ University of Udine. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package it.uniud.ailab.dcore.utils; import java.util.Objects; /** * A class that can store a value that can be of type either A or either B. * * While not "pure" functional code, this class is mean to be a lightweight * implementation of the classic functional {@code Either} type. * * @author Marco Basaldella * @param <A> the left type * @param <B> the right type */ public abstract class Either<A, B> { /** * The stored value. */ protected Object value; /** * Private constructor, so that only Left and Right can be Either. */ private Either() { } /** * Check if the instance is a Left * * @return true if is a Left */ public abstract boolean isLeft(); /** * Check if the instance is a Right * * @return true if is a Right */ public abstract boolean isRight(); /** * Get the L-value. * * @return the left value. */ public abstract A getLeft(); /** * Get the R-value. * * @return the right value. */ public abstract B getRight(); /** * Concrete implementation of the Left element of the Either. * * No JavaDoc inside the class since it's self-explanatory. See the abstract * class for explanations. * * @param <L> the left type * @param <R> the right type */ public final static class Left<L, R> extends Either<L, R> { public Left(L l) { this.value = l; } @Override public boolean isLeft() { return true; } @Override public boolean isRight() { return false; } @Override public L getLeft() { return (L) value; } @Override public R getRight() { throw new UnsupportedOperationException( "Trying to extract r-value from a Left"); } } /** * Concrete implementation of the Right element of the Either. * * No javadoc inside the class since it's self-explanatory. See the abstract * class for explanations. * * @param <L> the left type * @param <R> the right type */ public final static class Right<L, R> extends Either<L, R> { public Right(R r) { this.value = r; } @Override public boolean isLeft() { return false; } @Override public boolean isRight() { return true; } @Override public L getLeft() { throw new UnsupportedOperationException( "Trying to extract l-value from a Right"); } @Override public R getRight() { return (R) value; } } @Override public int hashCode() { int hash = 3; hash = 47 * hash + Objects.hashCode(this.value); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Either<?, ?> other = (Either<?, ?>) obj; if (!(this.isLeft() == other.isLeft())) { return false; } if (!Objects.equals(this.value, other.value)) { return false; } return true; } @Override public String toString() { return "Either{" + (isLeft() ? "left " : "right ") + "value=" + value + '}'; } }