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

com.wantedtech.common.xpresso.helpers.XUtils Maven / Gradle / Ivy

The newest version!
package com.wantedtech.common.xpresso.helpers;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.wantedtech.common.xpresso.x;
import com.wantedtech.common.xpresso.functional.Function;
import com.wantedtech.common.xpresso.functional.Predicate;
import com.wantedtech.common.xpresso.types.list;
import com.wantedtech.common.xpresso.types.set;
import com.wantedtech.common.xpresso.types.str;
import com.wantedtech.common.xpresso.types.tuple;
import com.wantedtech.common.xpresso.types.tuples.tuple0;
import com.wantedtech.common.xpresso.types.tuples.tuple1;
import com.wantedtech.common.xpresso.types.tuples.tuple2;
import com.wantedtech.common.xpresso.types.tuples.tuple3;
import com.wantedtech.common.xpresso.types.tuples.tuple4;

public class XUtils {

	public static  Function asKey(final Map map){
		return new Function() {
			public O apply(Object key) {
					try{
						return ((Map)(map)).get(key);	
					}catch(Exception e1){
						throw new IllegalArgumentException("asKeyOn could not interpret the input object as a container of values.");
					}
			}
		};
	}
	
	public static Function joinOn(final String separator){
		return new Function() {
			public String apply(Object iterable) {
				if(iterable instanceof String && separator.equals("")){
					return (String)iterable;
				}
				try{
					return x.String(separator).join((Iterable)iterable);	
				}catch(Exception e){
					throw new IllegalArgumentException("Could not interpret the input object as an Iterable.");
				}
			}
		};
	}
	
	@SafeVarargs
	public static  Function chain(final Function... functions){
		return new Function(){
			@SuppressWarnings("unchecked")
			@Override
			public O apply(I value) {
				Object newValue = x.doNothing.apply(value);
				for (Function func : functions) {
					newValue = func.apply(newValue);
				}
				return (O)newValue;
			}
		};
	}
	
	@SafeVarargs
	public static  Iterable chain(final Iterable iterable0, final Iterable iterable1, final Iterable... iterables){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				final ArrayList> iterators = new ArrayList>();
				iterators.add(iterable0.iterator());
				iterators.add(iterable1.iterator());
				int i = 2;
				for(Iterable iterable : iterables){
					iterators.add(iterable.iterator());
					i++;
				}
				final int numberOfInputIters = i;
				return new Iterator(){
					int currentIter = 0;
					@Override
					public boolean hasNext() {
						if(currentIter < numberOfInputIters){
							if(iterators.get(currentIter).hasNext()){
								return true;
							}
						}
						return false;
					}

					@Override
					public T next() {
						currentIter++;
						return iterators.get(currentIter).next();
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	@SafeVarargs
	public static Iterable chain(final String string0,final String string1,final String... otherStrings){
		String[] stingArr = otherStrings;
		str[] strArr = new str[stingArr.length];
		int counter = 0;
		for(String string : otherStrings){
			strArr[counter] = x.str(string);
			counter++;
		}
		return chain(x.str(string0),x.str(string1),strArr);
	}
	
	public static  tuple tupleOf(list lst) {
		switch (x.len(lst)) {
			case 0:
				return new tuple0();
			case 1:
				return x.tuple(lst.get(0));
			case 2:
				return x.tuple(lst.get(0), lst.get(1));
			case 3:
				return x.tuple(lst.get(0), lst.get(1), lst.get(2));
			case 4:
			default:
				return x.tuple(lst.get(0), lst.get(1), lst.get(2), lst.get(3));
		}
    }
	
	public static int len(Object value){
		if(value instanceof Iterable){
			int counter = 0;
			for(@SuppressWarnings("unused") Object element : (Iterable)value){
				counter++;
			}
			return counter;
		}
		if(value instanceof String){
			return ((String)value).length();
		}
		if(value instanceof Number){
			return 0;
		}
		if(value instanceof Boolean){
			return 0;
		}
		if(value instanceof Lengthful){
			return ((Lengthful)value).len();
		}
		if(value instanceof Map){
			return ((Map)value).size();
		}
		try{
			return (Integer)(value.getClass().getMethod("length").invoke(value));
		}catch(Exception e){
			//e.printStackTrace();
			
		}
		try{
			return ((Object[])value).length;
		}catch(Exception e){
			//e.printStackTrace();
		}
		try{
			return (Integer)(value.getClass().getField("length").getInt(value));
		}catch(Exception e){
			//e.printStackTrace();
		}
		try{
			return (Integer)(value.getClass().getMethod("size").invoke(value));
		}catch(Exception e){
			
		}
		try{
			return (Integer)(value.getClass().getMethod("len").invoke(value));
		}catch(Exception e){
			
		}
		return 0;
	}
	
	@SuppressWarnings("unchecked")
	public static  T avg(Iterable iterable){
		x.assertNotEmpty(iterable);
		double result = (x.reduce(x.add(), iterable)).doubleValue()/x.len(iterable);
		Class cls = iterable.iterator().next().getClass();
		if(cls.equals(Double.class)){
			return (T)(Object)result;
		}else if(cls.equals(Float.class)){
			return (T)(Object)result;
		}else{
			return (T)(Object)(int)Math.round(result);
		}
	}
	
	public static Iterable count(final int min,final int max,final int step){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					int currentValue = min-step;
					@Override
					public boolean hasNext() {
						if(currentValue < max-1){
							return true;
						}
						return false;
					}

					@Override
					public Integer next() {
						currentValue += step;
						return currentValue;
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static Iterable countFrom(final int min){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					int currentValue = min-1;
					@Override
					public boolean hasNext() {
						return true;
					}

					@Override
					public Integer next() {
						currentValue += 1;
						return currentValue;
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static Iterable countReal(final double min,final double max,final double step){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					double currentValue = min-step;
					@Override
					public boolean hasNext() {
						if(currentValue < max-1){
							return true;
						}
						return false;
					}

					@Override
					public Double next() {
						currentValue += step;
						return currentValue;
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static Iterable countTo(int max){
		return count(0,max,1);
	}
	
	public static  Iterable count(final Iterable iterable, final int step){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					Iterator iter = iterable.iterator();
					int currentValue = 0-step;
					@Override
					public boolean hasNext() {
						return iter.hasNext();
					}

					@Override
					public Integer next() {
						currentValue += step;
						for(Integer i : countTo(step)){
							currentValue+=i;
							iter.next();
						}
						return currentValue;
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static  Iterable map(Function function, Iterable iterable){
		if(iterable instanceof set){
			set newSet = new set();
			for (I element : iterable){
				newSet.put(function.apply(element));
			}
			return newSet;
		}else{
			list newList = new list();
			for (I element : iterable){
				newList.append(function.apply(element));
			}
			return newList;
		}
	}
	
	public static  O reduce(Function function, Iterable iterable, O initializer){
		x.assertNotNull(initializer);
		if(x.len(iterable) == 0) {
			return initializer;
		}
		Iterator iter = iterable.iterator();
		O output = function.apply(tuple2.valueOf(initializer, iter.next()));
		while(iter.hasNext()){
			output = function.apply(tuple2.valueOf(output, iter.next()));
		}
		return output;
	}
	
	public static  I reduce(Function,I> function, Iterable iterable){
		if(x.len(iterable) == 1) {
			return iterable.iterator().next();
		}
		Iterator iter = iterable.iterator();
		I output = function.apply(tuple2.valueOf(iter.next(), iter.next()));
		while(iter.hasNext()){
			output = function.apply(tuple2.valueOf(output, iter.next()));
		}
		return output;
	}
	
	public static  Iterable filter(Predicate predicate, Iterable iterable){
		if(iterable instanceof set){
			set newSet = new set();
			for (T element : iterable){
				if(predicate.apply(element)){
					newSet.put(element);	
				}
			}
			return newSet;
		}else{
			list newList = new list();
			for (T element : iterable){
				if(predicate.apply(element)){
					newList.append(element);	
				}
			}
			return newList;
		}
	}
	
	@SafeVarargs
	public static  set union(Iterable... iterables){
		set result = x.set(iterables[0]);
		if (iterables.length > 1){
			for (int i = 1;i Iterable> enumerate(final Iterable iterable, final int startCount){
		Iterable> generator = new Iterable>(){
			public Iterator> iterator(){
				return new Iterator>(){
					int currentCount = startCount-1;
					Iterator iter = iterable.iterator();
					@Override
					public boolean hasNext() {
						return iter.hasNext();
					}
					@Override
					public tuple2 next() {
						currentCount++;
						return tuple2.valueOf(currentCount, iter.next());
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static  Iterable cycle(final Iterable iterable, final Integer maxCount){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					Iterator iter = iterable.iterator();
					int currentCount = 0;
					@Override
					public boolean hasNext() {
						if(currentCount < maxCount || maxCount == null){
							if (!iter.hasNext()){
								iter = iterable.iterator();
							}
							return iter.hasNext();	
						}
						return false;
					}
					@Override
					public T next() {
						currentCount++;
						return iter.next();
					}
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static  list> divise(Iterable iterable, int numberOfPieces) {
		list iterableAsList = x.list(iterable);
		if (numberOfPieces > x.len(iterableAsList)) {
			return divise(iterableAsList, x.len(iterableAsList));
		}
		int avg = (int)(x.len(iterableAsList) / (double)(numberOfPieces));
		list> out = x.list();
		double last = 0.0;
		
		while (last < x.len(iterableAsList)) {
			out.append(iterableAsList.slice((int)last,(int)(last + avg)));
			last += avg;
		}
		return out;
	}
	
	public static  Iterable repeat(final T value, final Integer maxCount){
		Iterable generator = new Iterable(){
			public Iterator iterator(){
				return new Iterator(){
					int currentCount = 0;
					@Override
					public boolean hasNext() {
						if(currentCount < maxCount || maxCount == null){
							return true;	
						}
						return false;
					}
					@Override
					public T next() {
						currentCount++;
						return value;
					}
					
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
		return generator;
	}
	
	public static Random Random = new Random();
	
	public static  Iterable shuffle(Iterable iterable) {
        int size = x.len(iterable);
        list lst = x.list(iterable);
		if (size < 5) {
			for (int i=size; i>1; i--)
				lst.swap(i-1, Random.nextInt(i));
		} else {
			// Shuffle array
		    for (int i=size; i>1; i--)
		    	lst.swap(i-1, Random.nextInt(i));
		}
		return lst;
	}
	
	@SuppressWarnings({ "unchecked" })
	public static > Iterable sort(Iterable iterable,Function function,boolean reverse){
		class KeyValue implements Comparable, Serializable {
			/**
			 * 
			 */
			private static final long serialVersionUID = -6209178251903971368L;
			
			private K key;
			private V value;
			
			public KeyValue(K key, V value){
				this.key = key;
				this.value = value;
			}
			
			public K getKey(){
				return this.key;
			}
			
			public V getValue(){
				return this.value;
			}
			
			public int compareTo(KeyValue keyValue){
				return this.key.compareTo(keyValue.getKey());
			}
			
			@Override
			public String toString(){
				return this.key.toString() + '~' + this.value.toString();
			}
		}

		List keyValues = new ArrayList();
		for (V element: iterable){
			if(function != null){
				keyValues.add(new KeyValue(function.apply(element),element));	
			}else{
				keyValues.add(new KeyValue((K)element,element));
			}
		}
		
		Collections.sort(keyValues);
		
		if(reverse){
			Collections.reverse(keyValues);
		}
		ArrayList resultList = new ArrayList();
		for (KeyValue keyValue : keyValues){
			resultList.add(keyValue.getValue());
		}
		if(iterable instanceof list){
			return x.list(resultList);
		}
		return resultList;
	}
	
	public static  Iterable takeWhile(final Predicate predicate, final Iterable iterable){
		return new Iterable() {

			@Override
			public Iterator iterator() {
				return new Iterator() {

					Iterator inputIter = iterable.iterator();
					
					T next = null;
					
					@Override
					public boolean hasNext() {
						next = inputIter.next();
						return inputIter.hasNext() && predicate.apply(next);
					}

					@Override
					public T next() {
						return next;
					}	
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
	}
	
	public static  Iterable dropWhile(final Predicate predicate, final Iterable iterable){
		return new Iterable() {

			@Override
			public Iterator iterator() {
				return new Iterator() {

					Iterator inputIter = iterable.iterator();
					
					Predicate pred = predicate;
					
					T next = null;
					
					@Override
					public boolean hasNext() {
						while (inputIter.hasNext()) {
							next = inputIter.next();
							if (pred.apply(next)) {
								continue;
							} else {
								pred = x.FALSE;
							}
						}
						return false;
					}

					@Override
					public T next() {
						return next;
					}		
					
					@Override
					public void remove() {

					}
					
				};
			}
		};
	}
	
	public static  boolean contains(Iterable iterable, T value){
		if (iterable instanceof Collection) {
			  return ((Collection)iterable).contains(value);
		}else{
			for (T val : iterable){
				if (val.equals(value)){
					return true;
				}
			}
			return false;
		}
	}
	
	public static  list zip(Iterable iterable0){
		list result = x.list();
		try{
			for(tuple index__value : x.enumerate(iterable0)){
				@SuppressWarnings("unchecked")
				T0 value = (T0)index__value.get(1);
				result.append(x.tuple(value));
			}	
		}catch(Exception e){
			
		}
		return result;
	}
	
	public static  list zip(Iterable iterable0,Iterable iterable1){
		list result = x.list();
		list list1 = x.list(iterable1);
		try{
			for(tuple index__value : x.enumerate(iterable0)){
				int index = (int)index__value.get(0);
				@SuppressWarnings("unchecked")
				T0 value = (T0)index__value.get(1);
				result.append(x.tuple(value,list1.get(index)));
			}	
		}catch(Exception e){
			
		}
		return result;
	}
	
	public static  list zip(Iterable iterable0,Iterable iterable1,Iterable iterable2){
		list result = x.list();
		list list1 = x.list(iterable1);
		list list2 = x.list(iterable2);
		try{
			for(tuple index__value : x.enumerate(iterable0)){
				int index = (int)index__value.get(0);
				@SuppressWarnings("unchecked")
				T0 value = (T0)index__value.get(1);
				result.append(x.tuple(value,list1.get(index),list2.get(index)));
			}	
		}catch(Exception e){
			
		}
		return result;
	}
	
	public static  list zip(Iterable iterable0,Iterable iterable1,Iterable iterable2,Iterable iterable3){
		list result = x.list();
		list list1 = x.list(iterable1);
		list list2 = x.list(iterable2);
		list list3 = x.list(iterable3);
		try{
			for(tuple index__value : x.enumerate(iterable0)){
				int index = (int)index__value.get(0);
				@SuppressWarnings("unchecked")
				T0 value = (T0)index__value.get(1);
				result.append(x.tuple(value,list1.get(index),list2.get(index),list3.get(index)));
			}	
		}catch(Exception e){
			
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static  tuple1> unzip(Iterable iterable,Class class0){
		list list0 = x.list();
		for (tuple T0__ : iterable){
			list0.append((T0)T0__.get(0));
		}
		return tuple1.valueOf(list0);
	}
	
	public static  tuple2,list> unzip(Iterable iterable,Class class0,Class class1){
		list list0 = x.list();
		list list1 = x.list();
		for (tuple T0__T1 : iterable){
			list0.append((T0)T0__T1.get(0));
			list1.append((T1)T0__T1.get(1));
		}
		return tuple2.valueOf(list0,list1);
	}
	
	public static  tuple3,list,list> unzip(Iterable iterable,Class class0,Class class1,Class class2){
		list list0 = x.list();
		list list1 = x.list();
		list list2 = x.list();
		for (tuple T0__T1__T2 : iterable){
			list0.append((T0)T0__T1__T2.get(0));
			list1.append((T1)T0__T1__T2.get(1));
			list2.append((T2)T0__T1__T2.get(2));
		}
		return tuple3.valueOf(list0,list1,list2);
	}
	
	@SuppressWarnings("unchecked")
	public static  tuple4,list,list,list>  unzip(Iterable iterable,Class class0,Class class1,Class class2,Class class3){
		list list0 = x.list();
		list list1 = x.list();
		list list2 = x.list();
		list list3 = x.list();
		for (tuple T0__T1__T2__T3 : iterable){
			list0.append((T0)T0__T1__T2__T3.get(0));
			list1.append((T1)T0__T1__T2__T3.get(1));
			list2.append((T2)T0__T1__T2__T3.get(2));
			list3.append((T3)T0__T1__T2__T3.get(3));
		}
		return tuple4.valueOf(list0,list1,list2,list3);
	}
	
	public static boolean isTrue(Object value){
		if (value == null) {
			return false;
		}
		try{
			if((Boolean)value == false){
				return false;
			}	
		}catch(Exception e){
			
		}
		if(value instanceof Truthful){
			return ((Truthful)value).isTrue();
		}
		if(value instanceof Iterable && len(value) == 0){
			return false;
		}
		if(value instanceof tuple && len(value) == 0){
			return false;
		}
		if(value instanceof String && len(value) == 0){
			return false;
		}
		try{
			if((Integer)value <= 0){
				return false;
			}	
		}catch(Exception e){
			
		}
		try{
			if((Double)value <= 0.0){
				return false;
			}	
		}catch(Exception e){
			
		}
		try{
			if((Float)value <= 0.0){
				return false;
			}	
		}catch(Exception e){
			
		}
		return true;
	}
	
	public static  Function invoke(final String methodName, final Object... methodParams){
		return new Function() {
			public T apply(Object obj) throws IllegalArgumentException{
				
				list methodParamsList;
				if(methodParams != null) {
					methodParamsList = x.list(methodParams);					
				} else{
					methodParamsList = x.list();
				}

				list> methodParamsTypes = x.list();
				for (tuple item : x.enumerate(methodParamsList)){
					item.name("idx","param");
					Class currentType = item.get("param").getClass();
					if (currentType.equals(Integer.class)){
						currentType = int.class;
					}else if(currentType.equals(Double.class)){
						currentType = double.class;
					}else if(currentType.equals(Long.class)){
						currentType = long.class;
					}else if(currentType.equals(Float.class)){
						currentType = float.class;
					}
					methodParamsTypes.append(currentType); 
				}
				try{
					if(x.len(methodParams) > 0){
						Class[] typesArr = new Class[x.len(methodParamsTypes)];
						typesArr = methodParamsTypes.toArrayList().toArray(typesArr);
						return (T)(obj.getClass().getMethod(methodName, typesArr).invoke(obj, methodParamsList.toArrayList().toArray()));	
					}else{
						return (T)(obj.getClass().getMethod(methodName).invoke(obj));
					}
				}catch(Exception e){
					throw new IllegalArgumentException();
				}
			}
		};
	}
	
	public static  Function, T> add(){
		return new Function,T>() {
			public T apply(tuple2 values) throws IllegalArgumentException{
				T op1 = values.value0;
				T op2 = values.value1;

			    if( !(op1 instanceof Number) || !(op2 instanceof Number) ){
			        throw new IllegalArgumentException("Invalid operands for mathematical operator [+]");
			    }

			    if(op1 instanceof Double || op2 instanceof Double){
			        return (T)(Object)(((Number)op1).doubleValue() + ((Number)op2).doubleValue());
			    }

			    if(op1 instanceof Float || op2 instanceof Float){
			        return (T)(Object)(((Number)op1).floatValue() + ((Number)op2).floatValue());
			    }

			    if(op1 instanceof Long || op2 instanceof Long){
			        return (T)(Object)(((Number)op1).longValue() + ((Number)op2).longValue());
			    }

			    return (T)(Object)(((Number)op1).intValue() + ((Number)op2).intValue());
			}
		};
	}
	
	public static  Function, T> avg(){
		return new Function,T>() {
			public T apply(tuple2 values) throws IllegalArgumentException{
				T op1 = values.value0;
				T op2 = values.value1;

			    if( !(op1 instanceof Number) || !(op2 instanceof Number) ){
			        throw new IllegalArgumentException("Invalid operands for mathematical operator [+]");
			    }

			    if(op1 instanceof Double || op2 instanceof Double){
			        return (T)(Object)((((Number)op1).doubleValue() + ((Number)op2).doubleValue())/2);
			    }

			    if(op1 instanceof Float || op2 instanceof Float){
			        return (T)(Object)((((Number)op1).floatValue() + ((Number)op2).floatValue())/2);
			    }

			    if(op1 instanceof Long || op2 instanceof Long){
			        return (T)(Object)((((Number)op1).longValue() + ((Number)op2).longValue())/2);
			    }

			    return (T)(Object)((((Number)op1).intValue() + ((Number)op2).intValue())/2);
			}
		};
	}

}