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

com.davidbracewell.Switch Maven / Gradle / Ivy

There is a newer version: 0.5
Show newest version
/*
 * (c) 2005 David B. Bracewell
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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 com.davidbracewell;

import com.davidbracewell.conversion.Cast;
import com.davidbracewell.function.CheckedFunction;
import com.davidbracewell.function.SerializablePredicate;
import com.google.common.base.Throwables;
import lombok.NonNull;
import lombok.Value;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * Converts a value to another based on a series of predicates. In essence allows for switch statements in
 * the form of complex predicate -> function pairs to be performed on any data type.
 *
 * @param  the type parameter being switched on
 * @param  the type parameter returned from the switch operation
 * @author David B. Bracewell
 */
public class Switch implements Serializable {
  private static final long serialVersionUID = 1L;

  private final List> statements = new LinkedList<>();
  protected CheckedFunction defaultStmt;

  protected Switch() {

  }

  /**
   * Instantiates a new Switch.
   *
   * @param statements  the case statements
   * @param defaultStmt the default stmt
   */
  private Switch(List> statements, CheckedFunction defaultStmt) {
    this.statements.addAll(statements);
    this.defaultStmt = defaultStmt;
  }

  public static  Builder builder() {
    return new Builder<>();
  }

  protected void $(@NonNull SerializablePredicate predicate, @NonNull CheckedFunction function) {
    this.statements.add(new PredFunc<>(predicate, function));
  }

  protected  void $(@NonNull SerializablePredicate predicate, @NonNull CheckedFunction mapper, @NonNull CheckedFunction function) {
    this.statements.add(new PredFunc<>(predicate, mapper.andThen(function)));
  }

  /**
   * Switch on r.
   *
   * @param argument the argument
   * @return the r
   */
  public R switchOn(T argument) throws Exception {
    for (PredFunc predFunc : statements) {
      if (predFunc.getPredicate().test(argument)) {
        try {
          return predFunc.getFunction().apply(argument);
        } catch (Throwable throwable) {
          throw toException(Throwables.getRootCause(throwable));
        }
      }
    }
    if (defaultStmt != null) {
      try {
        return defaultStmt.apply(argument);
      } catch (Throwable throwable) {
        throw toException(Throwables.getRootCause(throwable));
      }
    }
    return null;
  }

  private Exception toException(Throwable throwable) {
    if (throwable instanceof Exception) {
      return Cast.as(throwable);
    }
    return new Exception(throwable);
  }

  public static class Builder {
    private final List> caseStmts = new LinkedList<>();
    private CheckedFunction defaultStmt = null;

    public Builder defaultStatement(CheckedFunction defaultStmt) {
      this.defaultStmt = defaultStmt;
      return this;
    }

    public Builder caseStmt(@NonNull SerializablePredicate predicate, @NonNull CheckedFunction function) {
      this.caseStmts.add(new PredFunc<>(predicate, function));
      return this;
    }

    public  Builder caseStmt(@NonNull SerializablePredicate predicate, @NonNull CheckedFunction mapper, @NonNull CheckedFunction function) {
      this.caseStmts.add(new PredFunc<>(predicate, mapper.andThen(function)));
      return this;
    }

    public Switch build() {
      return new Switch<>(caseStmts, defaultStmt);
    }

  }


  @Value
  private static class PredFunc implements Serializable {
    private static final long serialVersionUID = 1L;
    SerializablePredicate predicate;
    CheckedFunction function;
  }


}//END OF Switch




© 2015 - 2025 Weber Informatics LLC | Privacy Policy