package cyclops.data; import com.oath.cyclops.hkt.Higher; import cyclops.control.Option; import com.oath.cyclops.hkt.DataWitness.lazyString; import cyclops.reactive.ReactiveSeq; import lombok.AccessLevel; import lombok.AllArgsConstructor; import org.reactivestreams.Publisher; import java.io.Serializable; import java.util.*; 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; @AllArgsConstructor(access = AccessLevel.PRIVATE) public final class LazyString implements ImmutableList<Character>,Higher<lazyString,Character>, Serializable { private static final long serialVersionUID = 1L; private final LazySeq<Character> string; private static final LazyString Nil = fromLazySeq(LazySeq.empty()); public static LazyString fromLazySeq(LazySeq<Character> string){ return new LazyString(string); } public static LazyString fromIterable(Iterable<Character> string){ return new LazyString(LazySeq.fromIterable(string)); } public static LazyString of(CharSequence seq){ return fromLazySeq(LazySeq.fromStream( seq.chars().mapToObj(i -> (char) i))); } static Collector<Character, List<Character>, LazyString> collector() { Collector<Character, ?, List<Character>> c = Collectors.toList(); return Collectors.<Character, List<Character>, Iterable<Character>,LazyString>collectingAndThen((Collector)c,LazyString::fromIterable); } @Override public<R> LazySeq<R> unitIterable(Iterable<R> it){ if(it instanceof LazySeq){ return (LazySeq<R>)it; } return LazySeq.fromIterable(it); } public static LazyString empty(){ return Nil; } public LazyString op(Function<? super LazySeq<Character>, ? extends LazySeq<Character>> custom){ return fromLazySeq(custom.apply(string)); } public LazyString substring(int start){ return drop(start); } public LazyString substring(int start, int end){ return drop(start).take(end-start); } public LazyString toUpperCase(){ return fromLazySeq(string.map(c->c.toString().toUpperCase().charAt(0))); } public LazyString toLowerCase(){ return fromLazySeq(string.map(c->c.toString().toLowerCase().charAt(0))); } public LazySeq<LazyString> words() { return string.split(t -> t.equals(' ')).map(l-> fromLazySeq(l)); } public LazySeq<LazyString> lines() { return string.split(t -> t.equals('\n')).map(l-> fromLazySeq(l)); } public LazyString mapChar(Function<Character,Character> fn){ return fromLazySeq(string.map(fn)); } public LazyString flatMapChar(Function<Character,LazyString> fn){ return fromLazySeq(string.flatMap(fn.andThen(s->s.string))); } @Override public LazyString filter(Predicate<? super Character> predicate) { return fromLazySeq(string.filter(predicate)); } @Override public <R> ImmutableList<R> map(Function<? super Character, ? extends R> fn) { return string.map(fn); } @Override public <R> ImmutableList<R> flatMap(Function<? super Character, ? extends ImmutableList<? extends R>> fn) { return string.flatMap(fn); } @Override public <R> ImmutableList<R> concatMap(Function<? super Character, ? extends Iterable<? extends R>> fn) { return string.concatMap(fn); } @Override public <R> ImmutableList<R> mergeMap(Function<? super Character, ? extends Publisher<? extends R>> fn) { return string.mergeMap(fn); } @Override public <R> ImmutableList<R> mergeMap(int maxConcurecy, Function<? super Character, ? extends Publisher<? extends R>> fn) { return string.mergeMap(maxConcurecy,fn); } @Override public <R> R fold(Function<? super Some<Character>, ? extends R> fn1, Function<? super None<Character>, ? extends R> fn2) { return string.fold(fn1,fn2); } @Override public LazyString onEmpty(Character value) { return fromLazySeq(string.onEmpty(value)); } @Override public LazyString onEmptyGet(Supplier<? extends Character> supplier) { return fromLazySeq(string.onEmptyGet(supplier)); } @Override public ImmutableList<Character> onEmptySwitch(Supplier<? extends ImmutableList<Character>> supplier) { return string.onEmptySwitch(supplier); } public ReactiveSeq<Character> stream(){ return string.stream(); } public LazyString take(final long n) { return fromLazySeq(string.take(n)); } @Override public <R> ImmutableList<R> unitStream(Stream<R> stream) { return LazySeq.fromStream(stream); } @Override public LazyString emptyUnit() { return empty(); } @Override public LazyString replaceFirst(Character currentElement, Character newElement) { return fromLazySeq(string.replaceFirst(currentElement,newElement)); } @Override public LazyString removeFirst(Predicate<? super Character> pred) { return fromLazySeq(string.removeFirst(pred)); } @Override public LazyString subList(int start, int end) { return fromLazySeq(string.subList(start,end)); } @Override public LazyString filterNot(Predicate<? super Character> predicate) { return fromLazySeq(string.filterNot(predicate)); } @Override public LazyString notNull() { return fromLazySeq(string.notNull()); } @Override public LazyString peek(Consumer<? super Character> c) { return fromLazySeq(string.peek(c)); } @Override public LazyString tailOrElse(ImmutableList<Character> tail) { return fromLazySeq(string.tailOrElse(LazySeq.fromIterable(tail))); } @Override public LazyString removeStream(Stream<? extends Character> stream) { return fromLazySeq(string.removeStream(stream)); } @Override public LazyString removeAt(long pos) { return fromLazySeq(string.removeAt(pos)); } @Override public LazyString removeAll(Character... values) { return fromLazySeq(string.removeAll(values)); } @Override public LazyString retainAll(Iterable<? extends Character> it) { return fromLazySeq(string.retainAll(it)); } @Override public LazyString retainStream(Stream<? extends Character> stream) { return fromLazySeq(string.retainStream(stream)); } @Override public LazyString retainAll(Character... values) { return fromLazySeq(string.retainAll(values)); } @Override public LazyString distinct() { return fromLazySeq(string.distinct()); } @Override public LazyString sorted() { return fromLazySeq(string.sorted()); } @Override public LazyString sorted(Comparator<? super Character> c) { return fromLazySeq(string.sorted(c)); } @Override public LazyString takeWhile(Predicate<? super Character> p) { return fromLazySeq(string.takeWhile(p)); } @Override public LazyString dropWhile(Predicate<? super Character> p) { return fromLazySeq(string.dropWhile(p)); } @Override public LazyString takeUntil(Predicate<? super Character> p) { return fromLazySeq(string.takeUntil(p)); } @Override public LazyString dropUntil(Predicate<? super Character> p) { return fromLazySeq(string.dropUntil(p)); } @Override public LazyString dropRight(int num) { return fromLazySeq(string.dropRight(num)); } @Override public LazyString takeRight(int num) { return fromLazySeq(string.takeRight(num)); } @Override public LazyString shuffle() { return fromLazySeq(string.shuffle()); } @Override public LazyString shuffle(Random random) { return fromLazySeq(string.shuffle(random)); } @Override public LazyString slice(long from, long to) { return fromLazySeq(string.slice(from,to)); } @Override public <U extends Comparable<? super U>> LazyString sorted(Function<? super Character, ? extends U> function) { return fromLazySeq(string.sorted(function)); } @Override public LazyString prependStream(Stream<? extends Character> stream) { return fromLazySeq(string.prependStream(stream)); } @Override public LazyString appendAll(Character... values) { return fromLazySeq(string.appendAll(values)); } @Override public LazyString prependAll(Character... values) { return fromLazySeq(string.prependAll(values)); } @Override public LazyString insertAt(int pos, Character... values) { return fromLazySeq(string.insertAt(pos,values)); } @Override public LazyString deleteBetween(int start, int end) { return fromLazySeq(string.deleteBetween(start,end)); } @Override public LazyString insertStreamAt(int pos, Stream<Character> stream) { return fromLazySeq(string.insertStreamAt(pos,stream)); } @Override public LazyString plusAll(Iterable<? extends Character> list) { return fromLazySeq(string.plusAll(list)); } @Override public LazyString plus(Character value) { return fromLazySeq(string.plus(value)); } @Override public LazyString removeValue(Character value) { return fromLazySeq(string.removeValue(value)); } @Override public LazyString removeAll(Iterable<? extends Character> value) { return fromLazySeq(string.removeAll(value)); } @Override public LazyString updateAt(int pos, Character value) { return fromLazySeq(string.updateAt(pos,value)); } @Override public LazyString insertAt(int pos, Iterable<? extends Character> values) { return fromLazySeq(string.insertAt(pos,values)); } @Override public LazyString insertAt(int i, Character value) { return fromLazySeq(string.insertAt(i,value)); } public LazyString drop(final long num) { return fromLazySeq(string.drop(num)); } public LazyString reverse() { return fromLazySeq(string.reverse()); } public Option<Character> get(int pos){ return string.get(pos); } @Override public Character getOrElse(int pos, Character alt) { return string.getOrElse(pos,alt); } @Override public Character getOrElseGet(int pos, Supplier<? extends Character> alt) { return string.getOrElseGet(pos,alt); } public LazyString prepend(Character value){ return fromLazySeq(string.prepend(value)); } @Override public LazyString append(Character value) { return fromLazySeq(string.append(value)); } @Override public LazyString prependAll(Iterable<? extends Character> value) { return fromLazySeq(string.prependAll(value)) ; } @Override public LazyString appendAll(Iterable<? extends Character> value) { return fromLazySeq(string.appendAll(value)) ; } public LazyString prependAll(LazyString value){ return fromLazySeq(string.prependAll(value.string)); } public LazyString append(String s){ return fromLazySeq(string.appendAll(LazySeq.fromStream( s.chars().mapToObj(i -> (char) i)))); } public int size(){ return length(); } @Override public boolean isEmpty() { return string.isEmpty(); } public int length(){ return string.size(); } public String toString(){ return string.stream().join(""); } @Override public int hashCode() { return this.string.hashCode(); } @Override public boolean equals(Object obj) { return this.string.equals(obj); } }