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

com.aol.cyclops.lambda.tuple.CachedValues Maven / Gradle / Ivy

The newest version!
package com.aol.cyclops.lambda.tuple;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.AllArgsConstructor;

import com.aol.cyclops.closures.mutable.Mutable;
import com.aol.cyclops.comprehensions.donotation.Doable;
import com.aol.cyclops.matcher.builders.CheckValues;
import com.aol.cyclops.matcher.builders.MatchingInstance;
import com.aol.cyclops.matcher.builders.PatternMatcher;
import com.aol.cyclops.matcher.builders._Simpler_Case;
import com.aol.cyclops.matcher.recursive.Matchable;
import com.aol.cyclops.sequence.Monoid;
import com.aol.cyclops.sequence.streamable.ToStream;
import com.aol.cyclops.value.ValueObject;
import com.nurkiewicz.lazyseq.LazySeq;



public interface CachedValues extends Iterable, ValueObject, ToStream, Doable, Matchable, Comparable{

	
	
	default Object getMatchable(){
		return getCachedValues();
	}
	public List getCachedValues();
	
	CachedValues withArity(int arity);
	@AllArgsConstructor
	public static class ConvertStep{
		private final T c;
		public  X to(Class to){
			return (X)c.to(to);
		}
	}
	
	default  ConvertStep convert(){
		return new ConvertStep(this);
	}
	default  X to(Class to){
		Constructor cons = (Constructor)Stream.of(to.getConstructors())
							.filter(c -> c.getParameterCount()==arity())
							.findFirst()
							.get();
		try {
			
			return cons.newInstance(getCachedValues().toArray());
		} catch (InstantiationException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			return new ParamMatcher().create(to, arity(), getCachedValues(),e);
			
		}
		
		
		
	}
	/**
	 * Wrap multiple reducers or monoids into a single reducer instance,
	 * that can be used to reduce a given steam to multiple different values simultanously
	 * 
	 * {@code
	 * 
	 * Monoid sum = Monoid.of(0,(a,b)->a+b);
	 * Monoid mult = Monoid.of(1,(a,b)->a*b);
	   val result = tuple(sum,mult).>asReducer()
											.mapReduce(Stream.of(1,2,3,4)); 
		 
		assertThat(result,equalTo(tuple(10,24)));
	 * 
	 * }
	 * 
	 * Or alternatively 
	 * 
	 * {@code
	 * 
	 * Monoid concat = Monoid.of("",(a,b)->a+b);
	   Monoid join = Monoid.of("",(a,b)->a+","+b);
	   Monoid reducer = PowerTuples.tuple(concat,join).asReducer(); 
	 * 
	 * 
	 * assertThat(Stream.of("hello", "world", "woo!").map(CachedValues::of)
		                  .reduce(reducer.zero(),reducer.reducer())
		                  ,equalTo(tuple("helloworldwoo!",",hello,world,woo!")));
	 * }
	 * @return
	 */
	default  Monoid asReducer(){
		List reducers = (List)getCachedValues().stream().filter(c-> c instanceof Monoid).collect(Collectors.toList());
		return new Monoid(){
			public CachedValues zero(){
				return new TupleImpl(reducers.stream().map(r->r.zero()).collect(Collectors.toList()),arity());
			}
			public BiFunction combiner(){
				return (c1,c2) -> { 
					List l= new ArrayList<>();
					
					
					for(int i=0;i,List> res = Stream.of(1, 2, 2)
                       .collect(tuple(Collectors.toSet(),Collectors.toList()).asCollector());
	 * 
	 * }
	 * 
	 * Filters all non-Collector instances out of the Tuple
	 * 
	 * @return Collector
	 */
	default  Collector asCollector(){

		List collectors = (List)getCachedValues().stream().filter(c-> c instanceof Collector).collect(Collectors.toList());
		final Supplier supplier =  ()-> collectors.stream().map(c->c.supplier().get()).collect(Collectors.toList());
		final BiConsumer accumulator = (acc,next) -> {  LazySeq.of(collectors.stream().iterator()).>zip(LazySeq.of((List)acc),(a,b)->PowerTuples.tuple(a,b))
													
													.forEach( t -> t.v1().accumulator().accept(t.v2(),next));
		};
		final BinaryOperator combiner = (t1,t2)-> new TupleImpl(collectors.stream().map(c->c.combiner().apply(t1,t2)).collect(Collectors.toList()),arity());
		
		return (Collector) Collector.of( supplier,
                accumulator ,
		 combiner,
		values-> new TupleImpl(LazySeq.of(collectors.stream().iterator()).>zip(LazySeq.of((List)values),(a,b)->PowerTuples.tuple(a,b)).map(t->t.v1().finisher().apply(t.v2())).toList(),arity()));
	}


	@Override
	default int compareTo(CachedValues o){
		if(o==null)
			return 1;
		if(o.getCachedValues()==null){
			if(getCachedValues()==null){
				return 0;
			}
			return 1;
		}
		else if(getCachedValues()==null)
			return -1;
		for(int i=0;i=getCachedValues().size())
				return 1;
			int res = Objects.compare(getCachedValues().get(i), o.getCachedValues().get(i), (a,b) ->  a==null ? (b==null ? 0 : -1) : b==null? 1 : ((Comparable)a).compareTo(b) );
			if(res!=0)
				return res;
			
		}
			return 0;
	}
	
	default void forEach(Consumer c){
		getCachedValues().forEach(c);
	}
	
	default  T filter(Predicate> p){
		Mutable index = new Mutable(-1);
		List newList = getCachedValues().stream().map(v-> PowerTuples.tuple(index.set(index.get()+1).get(),v))
						.filter(p).map(PTuple2::v2).collect(Collectors.toList());
		return (T)new TupleImpl(newList,newList.size());
	}
	default  List toList(){
		return (List)getCachedValues();
	}
	default  Map toMap(){
		Map result = new HashMap<>();
		Iterator it = getCachedValues().iterator();
		if(arity()%2==0){
			for(int i=0;i+1> T asFlattenedStream(){
		return (T)asStreams().flatMap(s->s);
	}
	/**
	 * Will attempt to convert each element in the tuple into a Stream
	 * 
	 * Collection::stream
	 * CharSequence to stream
	 * File to Stream
	 * URL to Stream
	 * 
	 * @return Stream of Streams
	 */
	default > Stream asStreams(){
		//each value where stream can't be called, should just be an empty Stream
		return (Stream)getCachedValues().stream()
					.filter(o->o!=null)
					.map(o->DynamicInvoker.invokeStream(o.getClass(), o));
	}
	default Stream asStreamOfStrings(){
		
		return (Stream)getCachedValues().stream()
					.filter(o->o!=null)
					.map(Object::toString);
					
	}
	@Override
	default Iterator iterator(){
		return getCachedValues().iterator();
	}
	
	default Stream stream(){
		return getCachedValues().stream();
	}
	
	default  T append(X value){
		List list = new ArrayList(getCachedValues());
		list.add(value);
		return (T)new TupleImpl(list,list.size());
		
	}
	default  T appendAll(CachedValues values){
		List list = new ArrayList(getCachedValues());
		list.addAll(values.getCachedValues());
		return (T)new TupleImpl(list,list.size());
		
	}
	default  T flatMap(Function fn){
		return fn.apply((X)this);
	}
	
	default  T map(Function fn){
		List list = fn.apply(getCachedValues());
		return (T)new TupleImpl(list,list.size());
	}
	 
	public static  CachedValues of(T value){
		return new TupleImpl(Arrays.asList(value),1);
	}
	public static  CachedValues  of(Object... values){
		return new TupleImpl(Arrays.asList(values),values.length);
	}
}