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

com.aol.cyclops.trycatch.TryT Maven / Gradle / Ivy

There is a newer version: 7.2.4
Show newest version
package com.aol.cyclops.trycatch;


import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jooq.lambda.function.Function1;

import com.aol.cyclops.lambda.monads.transformers.OptionalT;
import com.aol.cyclops.monad.AnyM;


/**
 * Monad transformer for JDK Try
 * 
 * TryT consists of an AnyM instance that in turns wraps another Monad type that contains an Try
 * 
 * TryT>>>
 * 
 * TryT allows the deeply wrapped Try to be manipulating within it's nested /contained context
 * 
 * 
 * @author johnmcclean
 *
 * @param  The type contained on the Try within
 */
public class TryT {
   
   private final AnyM> run;
   
   
   private TryT(final AnyM> run){
       this.run = run;
   }
   
	/**
	 * @return The wrapped AnyM
	 */
	public AnyM> unwrap() {
		return run;
	}

   
	/**
	 * Peek at the current value of the Try
	 * 
	 * {@code 
	 *    TryT.of(AnyM.fromStream(Success.of(10))
	 *             .peek(System.out::println);
	 *             
	 *     //prints 10        
	 * }
	 * 
* * @param peek Consumer to accept current value of Try * @return TryT with peek call */ public TryT peek(Consumer peek) { return of(run.peek(opt -> opt.map(a -> { peek.accept(a); return a; }))); } /** * Filter the wrapped Try *
	 * {@code 
	 *    TryT.of(AnyM.fromStream(Success.of(10))
	 *             .filter(t->t!=10);
	 *             
	 *     //TryT>>
	 * }
	 * 
* @param test Predicate to filter the wrapped Try * @return OptionalT that applies the provided filter */ public OptionalT filter(Predicate test) { return OptionalT.of(run.map(opt -> opt.filter(test))); } /** * Map the wrapped Try * *
	 * {@code 
	 *  TryT.of(AnyM.fromStream(Success.of(10))
	 *             .map(t->t=t+1);
	 *  
	 *  
	 *  //TryT>>
	 * }
	 * 
* * @param f Mapping function for the wrapped Try * @return TryT that applies the map function to the wrapped Try */ public TryT map(Function f) { return new TryT(run.map(o -> o.map(f))); } /** * Flat Map the wrapped Try *
	 * {@code 
	 *  TryT.of(AnyM.fromStream(Success.of(10))
	 *             .flatMap(t->Failure.of(new Exception());
	 *  
	 *  
	 *  //TryT>>
	 * }
	 * 
* @param f FlatMap function * @return TryT that applies the flatMap function to the wrapped Try */ public TryT flatMap(Function1> f) { return of(run.flatMap(opt -> { if (opt.isSuccess()) return f.apply(opt.get()).run; Try ret = (Try)opt; return run.unit(ret); })); } /** * Lift a function into one that accepts and returns an TryT * This allows multiple monad types to add functionality to existing functions and methods * * e.g. to add Exception Handling (via Try) and iteration (via Stream) to an existing function *
	 * {@code 
	 *  Function add2 = i -> i+2;
		Function, TryT> optTAdd2 = TryT.lift(add2);
		
		Stream withNulls = Stream.of(1,2,null);
		AnyM stream = AnyM.ofMonad(withNulls);
		AnyM> streamOpt = stream.map(this::toTry);
		List results = optTAdd2.apply(TryT.of(streamOpt))
										.unwrap()
										.>>unwrap()
										.filter(Try::isSuccess)
										.map(Try::get)
										.collect(Collectors.toList());
		
		//Arrays.asList(3,4);
	 * 
	 * 
	 * }
* * * @param fn Function to enhance with functionality from Try and another monad type * @return Function that accepts and returns an TryT */ public static Function, TryT> lift(Function fn) { return optTu -> optTu.map(input -> fn.apply(input)); } /** * Lift a BiFunction into one that accepts and returns TryTs * This allows multiple monad types to add functionality to existing functions and methods * * e.g. to add Exception handling (via Try), iteration (via Stream) and asynchronous execution (CompletableFuture) * to an existing function * *
	 * {@code 
	BiFunction add = (a,b) -> a+b;
		BiFunction,TryT, TryT> optTAdd2 = TryT.lift2(add);
		
		Stream withNulls = Stream.of(1,2,null);
		AnyM stream = AnyM.ofMonad(withNulls);
		AnyM> streamOpt = stream.map(this::toTry);
		
		CompletableFuture> two = CompletableFuture.completedFuture(Try.of(2));
		AnyM> future=  AnyM.ofMonad(two);
		List results = optTAdd2.apply(TryT.of(streamOpt),TryT.of(future))
										.unwrap()
										.>>unwrap()
										.filter(Try::isSuccess)
										.map(Try::get)
										.collect(Collectors.toList());
			//Arrays.asList(3,4);							
	  }
	  
* @param fn BiFunction to enhance with functionality from Try and another monad type * @return Function that accepts and returns an TryT */ public static BiFunction, TryT, TryT> lift2(BiFunction fn) { return (optTu1, optTu2) -> optTu1.flatMap(input1 -> optTu2.map(input2 -> fn.apply(input1, input2))); } /** * Construct an TryT from an AnyM that contains a monad type that contains type other than Try * The values in the underlying monad will be mapped to Try * * @param anyM AnyM that doesn't contain a monad wrapping an Try * @return TryT */ @SuppressWarnings("unchecked") public static TryT fromAnyM(AnyM anyM) { return (TryT) of(anyM.map(Success::of)); } /** * Construct an TryT from an AnyM that wraps a monad containing Trys * * @param monads AnyM that contains a monad wrapping an Try * @return TryT */ public static TryT of(AnyM> monads) { return new TryT<>(monads); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public String toString() { return run.toString(); } }