All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.shapesecurity.functional.data.Either Maven / Gradle / Ivy

There is a newer version: 2.2.0
Show newest version
/*
 * Copyright 2014 Shape Security, Inc.
 *
 * 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 com.shapesecurity.functional.data;

import com.shapesecurity.functional.F;

import org.jetbrains.annotations.NotNull;

public abstract class Either {
  // class local
  private Either() {
    super();
  }

  @NotNull
  public static  Left left(@NotNull A a) {
    return new Left<>(a);
  }

  @NotNull
  public static  Right right(@NotNull B b) {
    return new Right<>(b);
  }

  @NotNull
  public static  A extract(Either e) {
    return e.either(x -> x, x -> x);
  }

  public abstract boolean isLeft();

  public final boolean isRight() {
    return !this.isLeft();
  }

  public abstract  X either(F f1, F f2);

  @NotNull
  public abstract  Either map(F f1, F f2);

  @NotNull
  public abstract  Either mapLeft(@NotNull F f);

  @NotNull
  public abstract  Either mapRight(@NotNull F f);

  @NotNull
  public abstract Maybe left();

  @NotNull
  public abstract Maybe right();

  public abstract boolean eq(Either either);

  @Override
  public abstract int hashCode();

  @SuppressWarnings("unchecked")
  @Override
  public final boolean equals(Object object) {
    return this == object || object instanceof Either && this.eq((Either) object);
  }

  public static final class Left extends Either {
    @NotNull
    public final A a;

    private Left(@NotNull A a) {
      super();
      this.a = a;
    }

    @Override
    public int hashCode() {
      return this.a.hashCode();
    }

    @Override
    public boolean isLeft() {
      return true;
    }

    @Override
    public  X either(F f1, F f2) {
      return f1.apply(this.a);
    }

    @NotNull
    @Override
    public  Left map(F f1, F f2) {
      return Either.left(f1.apply(this.a));
    }

    @NotNull
    @Override
    public  Left mapLeft(@NotNull F f) {
      return Either.left(f.apply(this.a));
    }

    @NotNull
    @Override
    public Maybe left() {
      return Maybe.just(this.a);
    }

    @NotNull
    @Override
    public Maybe right() {
      return Maybe.nothing();
    }

    @Override
    public boolean eq(Either either) {
      return either instanceof Left && this.a.equals(((Left) either).a);
    }

    @SuppressWarnings("unchecked")
    @NotNull
    @Override
    public  Left mapRight(@NotNull F f) {
      return (Left) this;
    }
  }

  public static final class Right extends Either {
    @NotNull
    public final B b;

    private Right(@NotNull B b) {
      super();
      this.b = b;
    }

    @Override
    public boolean isLeft() {
      return false;
    }

    @Override
    public int hashCode() {
      return this.b.hashCode();
    }

    @Override
    public  X either(F f1, F f2) {
      return f2.apply(this.b);
    }

    @NotNull
    @Override
    public  Either map(F f1, F f2) {
      return Either.right(f2.apply(this.b));
    }

    @SuppressWarnings("unchecked")
    @NotNull
    @Override
    public  Right mapLeft(@NotNull F f) {
      return (Right) this;
    }

    @NotNull
    @Override
    public  Right mapRight(@NotNull F f) {
      return Either.right(f.apply(this.b));
    }

    @NotNull
    @Override
    public Maybe left() {
      return Maybe.nothing();
    }

    @NotNull
    @Override
    public Maybe right() {
      return Maybe.just(this.b);
    }

    @Override
    public boolean eq(Either either) {
      return either instanceof Right && this.b.equals(((Right) either).b);
    }
  }
}