diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml new file mode 100644 index 0000000..005bc3d --- /dev/null +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -0,0 +1,10 @@ +name: "Validate Gradle Wrapper" +on: [push, pull_request] + +jobs: + validation: + name: "Validation" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: gradle/wrapper-validation-action@v1.0.4 diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..5fdc663 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,41 @@ +# This workflow will build a Java project with Gradle +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ 1.x ] + pull_request: + branches: [ 1.x ] + +jobs: + build: + + runs-on: ubuntu-latest + env: + CI_PULL_REQUEST: ${{ github.event.number }} + JAVADOCS_TOKEN: ${{ secrets.JAVADOCS_TOKEN }} + CI_BUILD_NUMBER: ${{ github.run_number }} + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Grant execute permission for push + run: chmod +x push.sh + - name: Build with Gradle + run: ./gradlew build javadoc --stacktrace + - name: Upload to Codecov + uses: codecov/codecov-action@v1 + - name: Push Javadocs + run: ./push.sh diff --git a/.gitignore b/.gitignore index e3779c2..e7611fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,22 @@ -*.class - -# Package Files # -*.jar -*.war -*.ear -/build/ - -.gradle -.m2 +*.class + +# Package Files # +*.jar +*.war +*.ear +/build/ + +.gradle +.m2 /.nb-gradle/ /bin/ -.settings/ -.nb-gradle-properties -.classpath -.project -.settings -.metadata -.checkstyle -bin/ -!/gradle/wrapper/gradle-wrapper.jar \ No newline at end of file +.settings/ +.nb-gradle-properties +.classpath +.project +.settings +.metadata +.checkstyle +bin/ +!/gradle/wrapper/gradle-wrapper.jar +.idea \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index de0ba35..fa63c80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,17 @@ language: java jdk: - - oraclejdk7 + - openjdk8 before_install: - - chmod +x gradlew \ No newline at end of file + - chmod +x gradlew + +after_success: + - bash <(curl -s https://codecov.io/bash) + - bash ./push.sh + + # cache between builds +cache: + directories: + - $HOME/.m2 + - $HOME/.gradle diff --git a/README.md b/README.md index 899002a..f1f3240 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,62 @@ ixjava ================= -Interactive Extensions for Java, the dual of RxJava. Originally implemented in the Reactive4Java framework, now converted to work with RxJava. + +[![codecov.io](http://codecov.io/github/akarnokd/ixjava/coverage.svg?branch=1.x)](http://codecov.io/github/akarnokd/ixjava?branch=1.x) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/ixjava/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/ixjava) -The aim is to provide pull-based datastream support with the same naming as in RxJava mainly for the pre-Java-8 world. The Stream API in Java 8 is not exactly the same thing because Streams can be only consumed once while Iterables can be consumed many times. Google Guava features a lot of Iterable operators but without method chaining support. +Iterable Extensions for Java, the dual of RxJava. Originally implemented in the Reactive4Java framework, now standalone; no dependencies on any reactive library. -# Releases - - +The aim is to provide, lazily evaluated, pull-based datastream support with the same naming as in RxJava mainly for the pre-Java-8 world. The Stream API in Java 8 is not exactly the same thing because Streams can be only consumed once while `Iterable`s can be consumed many times. Google Guava features a lot of Iterable operators, plus now they have the `FluentIterable` with similar setup +but far less operators available. -You can download any necessary JAR files manually from +**This branch starts from scratch by reimplementing `ix.Ix` and all of its operators based on the +5 year experience with reactive +and interactive dataflows.** -https://oss.sonatype.org/content/groups/public/com/github/akarnokd/ixjava/ +# Releases -Alternatively, you can use the usual maven dependency management to get the files: +Javadoc: https://akarnokd.github.io/ixjava/javadoc/index.html **gradle** -``` +```groovy dependencies { - compile "com.github.akarnokd:ixjava:0.92.6" + implementation 'com.github.akarnokd:ixjava:1.0.0' } ``` -**ivy** +Maven search: + +[http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.akarnokd%22) + +# Examples + +The main (and only) entry point is the class `ix.Ix` which features a bunch of static factory methods: +```java +List list = Arrays.asList(1, 2, 3, 4, 5); + +Ix seq = Ix.from(list); ``` - - - + +Now we can apply instance methods on the `seq` sequence, just like in RxJava. Not all operators are available though due to the synchronous-pull nature of IxJava. + +```java +seq +.map(v -> v + 1) +.filter(v -> v % 2 == 0) +.flatMap(v -> Ix.fromArray(v * 10, v * 100))) +.subscribe(System.out::println) +; ``` -or the maven search facility +Since `Ix` implements `Iterable`, you can use the for-each loop to consume it: -[http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.akarnokd%22) +```java + +for (Integer v : Ix.fromArray(5, 10).skip(1).concatWith(Ix.just(20))) { + System.out.println("Value: " + v); +} +``` + +For further details on the possibilities, please study the javadoc of `Ix`. diff --git a/build.gradle b/build.gradle index 07f3b69..79c1fe2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,25 @@ +buildscript { + repositories { + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + + dependencies { + classpath 'gradle.plugin.nl.javadude.gradle.plugins:license-gradle-plugin:0.13.1' + classpath "me.champeau.gradle:jmh-gradle-plugin:0.2.0" + classpath 'ru.vyarus:gradle-animalsniffer-plugin:1.1.0' + } +} + apply plugin: 'java' apply plugin: 'eclipse' +apply plugin: "me.champeau.gradle.jmh" +apply plugin: 'pmd' +apply plugin: 'jacoco' +apply plugin: 'ru.vyarus.animalsniffer' +apply plugin: "com.github.hierynomus.license" sourceCompatibility = '1.6' targetCompatibility = '1.6' @@ -13,19 +33,17 @@ if (!hasProperty('mainClass')) { ext.mainClass = '' } - - -apply from: file('gradle/maven.gradle') - repositories { mavenCentral() } +apply from: file('gradle/maven.gradle') apply plugin: 'maven' apply plugin: 'osgi' dependencies { - compile "io.reactivex:rxjava:1.1.6" + signature 'org.codehaus.mojo.signature:java16:1.1@signature' + testCompile group: 'junit', name: 'junit', version: '4.12' } @@ -55,16 +73,107 @@ jar { } } -buildscript { - repositories { - mavenCentral() +apply plugin: 'maven-publish' + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact (sourcesJar) { + classifier = 'sources' + } + } } +} - dependencies { - classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.9.0' +jmh { + jmhVersion = '1.17.4' + humanOutputFile = null + if (project.hasProperty('jmh')) { + include = ".*" + project.jmh + ".*" + } else { + include = ".*" } } -apply plugin: 'license' +plugins.withType(EclipsePlugin) { + project.eclipse.classpath.plusConfigurations += [ configurations.jmh ] +} + +javadoc { + failOnError = false + options.links( + "https://docs.oracle.com/javase/7/docs/api/" + ) + +} -apply from: file('gradle/license.gradle') +test { + maxHeapSize = "2g" + testLogging { + events "started", "failed" // "skipped", "passed" + // showStandardStreams = true + } +} + +license { + header rootProject.file('HEADER') + ext.year = Calendar.getInstance().get(Calendar.YEAR) + skipExistingHeaders true + ignoreFailures true + excludes(["**/*.md", "**/*.txt"]) +} + +jacoco { + toolVersion = '0.7.9' // See http://www.eclemma.org/jacoco/. +} + +jacocoTestReport { + reports { + xml.enabled = true + html.enabled = true + } +} + +build.dependsOn jacocoTestReport + +check.dependsOn jacocoTestReport + +pmd { + toolVersion = '5.4.2' + ignoreFailures = true + sourceSets = [sourceSets.main] + ruleSets = [] + ruleSetFiles = files('pmd.xml') +} + +pmdMain { + reports { + html.enabled = true + xml.enabled = true + } +} + +task pmdPrint(dependsOn: 'pmdMain') << { + File file = rootProject.file('build/reports/pmd/main.xml') + if (file.exists()) { + + println("Listing first 100 PMD violations") + + file.eachLine { line, count -> + if (count <= 100) { + println(line) + } + } + + } else { + println("PMD file not found.") + } +} + +build.dependsOn pmdPrint +check.dependsOn pmdPrint + +animalsniffer { + annotation = 'ix.SuppressAnimalSniffer' +} diff --git a/gradle.properties b/gradle.properties index 75a7dc5..aef125e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=0.92.6 +version=1.0.0 diff --git a/gradle/license.gradle b/gradle/license.gradle deleted file mode 100644 index c1a5658..0000000 --- a/gradle/license.gradle +++ /dev/null @@ -1,6 +0,0 @@ -license { - header rootProject.file('HEADER') - ext.year = Calendar.getInstance().get(Calendar.YEAR) - skipExistingHeaders true - ignoreFailures true -} diff --git a/pmd.xml b/pmd.xml new file mode 100644 index 0000000..339af7d --- /dev/null +++ b/pmd.xml @@ -0,0 +1,223 @@ + + + RxJava PMD ruleset + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/push.sh b/push.sh new file mode 100644 index 0000000..83054b4 --- /dev/null +++ b/push.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# ---------------------------------------------------------- +# Automatically push back the generated JavaDocs to gh-pages +# ---------------------------------------------------------- +# based on https://gist.github.com/willprice/e07efd73fb7f13f917ea + +# specify the common address for the repository +targetRepo=github.com/akarnokd/ixjava.git +# ======================================================================= + +# only for main pushes, for now +if [ "$CI_PULL_REQUEST" == "true" ]; then + echo -e "Pull request detected, skipping JavaDocs pushback." + exit 0 +fi + +# check if the token is actually there +if [ "$JAVADOCS_TOKEN" == "" ]; then + echo -e "No access to GitHub, skipping JavaDocs pushback." + exit 0 +fi + +# prepare the git information +git config --global user.email "akarnokd@gmail.com" +git config --global user.name "akarnokd" + +# setup the remote +git remote add origin-pages https://${JAVADOCS_TOKEN}@${targetRepo} > /dev/null 2>&1 + +# stash changes due to chmod +git stash + +# get the gh-pages +git fetch --all +git branch -a +git checkout -b gh-pages origin-pages/gh-pages + +# remove old dir +rm -rf javadoc + +# copy and overwrite new doc +yes | cp -rfv ./build/docs/javadoc/ javadoc/ + +# stage all changed and new files +git add --all --verbose +#git add *.html --verbose +#git add *.css --verbose +#git add *.js --verbose +#git add javadoc/package-list --verbose + +# commit all +git commit --message "CI build: $CI_BUILD_NUMBER" + + +# push it +git push --quiet --set-upstream origin-pages gh-pages + +# we are done diff --git a/src/jmh/java/ix/FlattenIterableArrayPerf.java b/src/jmh/java/ix/FlattenIterableArrayPerf.java new file mode 100644 index 0000000..e58efff --- /dev/null +++ b/src/jmh/java/ix/FlattenIterableArrayPerf.java @@ -0,0 +1,93 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Example benchmark. Run from command line as + *
+ * gradle jmh -Pjmh='IxPerf' + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 1) +@State(Scope.Thread) +public class FlattenIterableArrayPerf implements IxFunction> { + + @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) + public int count; + + Ix source; + + Ix inner; + + Ix flatMapJust; + + @Override + public Iterable apply(Integer t) { + return inner; + } + + @Setup + public void setup(Blackhole bh) { + + int d = 1000000 / count; + + Integer[] countArray = new Integer[count]; + Arrays.fill(countArray, 777); + + inner = Ix.fromArray(countArray); + + Integer[] sourceArray = new Integer[d]; + Arrays.fill(sourceArray, 777); + + source = Ix.fromArray(sourceArray).flatMap(this); + + flatMapJust = inner.flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.just(v); + } + }); + } + + @Benchmark + public Object xrangeLast() { + return source.last(); + } + + @Benchmark + public void xrangeEach(Blackhole bh) { + for (Integer i : source) { + bh.consume(i); + } + } + + @Benchmark + public void flatMapJust(Blackhole bh) { + for (Integer i : flatMapJust) { + bh.consume(i); + } + } +} diff --git a/src/jmh/java/ix/FlattenIterablePerf.java b/src/jmh/java/ix/FlattenIterablePerf.java new file mode 100644 index 0000000..cbc4cf9 --- /dev/null +++ b/src/jmh/java/ix/FlattenIterablePerf.java @@ -0,0 +1,86 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Example benchmark. Run from command line as + *
+ * gradle jmh -Pjmh='IxPerf' + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 1) +@State(Scope.Thread) +public class FlattenIterablePerf implements IxFunction> { + + @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) + public int count; + + Ix source; + + Ix inner; + + Ix flatMapJust; + + @Override + public Iterable apply(Integer t) { + return inner; + } + + @Setup + public void setup(Blackhole bh) { + + int d = 1000000 / count; + + inner = Ix.range(1, count); + + source = Ix.range(1, d).flatMap(this); + + flatMapJust = Ix.range(1, count).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.just(v); + } + }); + } + + @Benchmark + public Object xrangeLast() { + return source.last(); + } + + @Benchmark + public void xrangeEach(Blackhole bh) { + for (Integer i : source) { + bh.consume(i); + } + } + + @Benchmark + public void flatMapJust(Blackhole bh) { + for (Integer i : flatMapJust) { + bh.consume(i); + } + } +} diff --git a/src/jmh/java/ix/IxPerf.java b/src/jmh/java/ix/IxPerf.java new file mode 100644 index 0000000..a15b697 --- /dev/null +++ b/src/jmh/java/ix/IxPerf.java @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Example benchmark. Run from command line as + *
+ * gradle jmh -Pjmh='IxPerf' + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 1) +@State(Scope.Thread) +public class IxPerf { + +// @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) +// public int count; + + @Setup + public void setup(Blackhole bh) { + + } + + @Benchmark + public Object just() { + return new IxJust(1).iterator().next(); + } + +} diff --git a/src/jmh/java/ix/RangePerf.java b/src/jmh/java/ix/RangePerf.java new file mode 100644 index 0000000..985d01a --- /dev/null +++ b/src/jmh/java/ix/RangePerf.java @@ -0,0 +1,79 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Example benchmark. Run from command line as + *
+ * gradle jmh -Pjmh='IxPerf' + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 1) +@State(Scope.Thread) +public class RangePerf implements IxFunction> { + + @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) + public int count; + + Ix source; + + Ix inner; + + Ix flatMapJust; + + @Override + public Iterable apply(Integer t) { + return inner; + } + + @Setup + public void setup(Blackhole bh) { + + int d = 1000000 / count; + + inner = Ix.range(1, count); + + source = Ix.range(1, d).flatMap(this); + + flatMapJust = Ix.range(1, count).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.just(v); + } + }); + } + + @Benchmark + public Object rangeLast() { + return inner.last(); + } + + @Benchmark + public void rangeEach(Blackhole bh) { + for (Integer i : inner) { + bh.consume(i); + } + } +} diff --git a/src/jmh/java/ix/ReducePerf.java b/src/jmh/java/ix/ReducePerf.java new file mode 100644 index 0000000..40947a7 --- /dev/null +++ b/src/jmh/java/ix/ReducePerf.java @@ -0,0 +1,61 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Example benchmark. Run from command line as + *
+ * gradle jmh -Pjmh='IxPerf' + */ +@BenchmarkMode(Mode.Throughput) +@Warmup(iterations = 5) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) +@Fork(value = 1) +@State(Scope.Thread) +public class ReducePerf { + + @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) + public int count; + + Ix sum; + + @Setup + public void setup(Blackhole bh) { + Integer[] array = new Integer[count]; + Arrays.fill(array, 1); + + sum = Ix.fromArray(array).sumInt(); + } + + @Benchmark + public Object sumLast() { + return sum.last(); + } + + @Benchmark + public Object sumFirst() { + return sum.first(); + } + +} diff --git a/src/main/java/ix/Enumerator.java b/src/main/java/ix/Enumerator.java deleted file mode 100644 index 40431ea..0000000 --- a/src/main/java/ix/Enumerator.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -/** - * The base interface for an Enumerable-Enumerator - * pair of iteration method where the - * enumerator has next() to - * advance the iteration and current() - * to return the current element. An example - * from normal Java for such - * kind of iteration is the java.sql.ResultSet. - * @param the element type - */ -public interface Enumerator { - /** - * Tries to move to the next element. - * Only this method may throw an exception. - * @return false if there are no more elements - */ - boolean next(); - /** - * Returns the current element. If the - * enumeration was not started via the next() - * method, or the enumeration has already finished and next() - * returned false, a NoSuchElementException is thrown. - * Other than these, this method should not throw any exception. - * @return the current element. - */ - T current(); -} diff --git a/src/main/java/ix/package-info.java b/src/main/java/ix/EqualityHelper.java similarity index 73% rename from src/main/java/ix/package-info.java rename to src/main/java/ix/EqualityHelper.java index 00133ff..d901495 100644 --- a/src/main/java/ix/package-info.java +++ b/src/main/java/ix/EqualityHelper.java @@ -1,19 +1,26 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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. - */ -/** - * Contains exception classes. - */ -package ix; \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +enum EqualityHelper implements IxPredicate2 { + INSTANCE; + + @Override + public boolean test(Object t, Object u) { + return (t == u) || (t != null && t.equals(u)); + } +} diff --git a/src/main/java/ix/GroupedIterable.java b/src/main/java/ix/GroupedIterable.java deleted file mode 100644 index 8c3fbc6..0000000 --- a/src/main/java/ix/GroupedIterable.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import java.util.LinkedList; -import java.util.List; - -/** - * Contains a sequence values with an associated key used by the groupBy operator. - * @param the group key type - * @param the value type - */ -public final class GroupedIterable extends Ix { - /** The group key. */ - protected final K key; - /** The values in the group. */ - protected final List values; - /** - * Constructs a new grouped iterable with the given key. - * @param key the group key - */ - public GroupedIterable(K key) { - super(new LinkedList()); - this.key = key; - this.values = (List)this.it; - } - /** - * Returns the key associated with this group. - * @return the key associated with this group - */ - public K getKey() { - return key; - } - /** - * Adds one element to the values. - * @param value the value - */ - public void add(V value) { - values.add(value); - } - /** - * Add the values of the target iterable. - * @param values the values to add - */ - public void add(Iterable values) { - for (V v : values) { - this.values.add(v); - } - } -} diff --git a/src/main/java/ix/GroupedIx.java b/src/main/java/ix/GroupedIx.java new file mode 100644 index 0000000..1dda83b --- /dev/null +++ b/src/main/java/ix/GroupedIx.java @@ -0,0 +1,49 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * An Iterable plus a key representing a group for the + * operator {@code groupBy()}. + * + * @param the key type + * @param the value type + */ +public abstract class GroupedIx extends Ix { + + /** + * The group key. + */ + protected final K key; + + /** + * Constructs a GroupedIx with the given group key. + * @param key the group key + */ + public GroupedIx(K key) { + this.key = key; + } + + /** + * Returns this group's key. + * @return the key + */ + public final K key() { + return key; + } + +} diff --git a/src/main/java/ix/IdentityHelper.java b/src/main/java/ix/IdentityHelper.java new file mode 100644 index 0000000..f3358b9 --- /dev/null +++ b/src/main/java/ix/IdentityHelper.java @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +enum IdentityHelper implements IxFunction { + INSTANCE + ; + + @SuppressWarnings("unchecked") + public static IxFunction instance() { + return (IxFunction)INSTANCE; + } + + @Override + public Object apply(Object t) { + return t; + } +} \ No newline at end of file diff --git a/src/main/java/ix/Ix.java b/src/main/java/ix/Ix.java index be7575d..2911710 100644 --- a/src/main/java/ix/Ix.java +++ b/src/main/java/ix/Ix.java @@ -1,1479 +1,2819 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import java.math.*; -import java.util.*; - -import ix.internal.operators.*; -import ix.internal.util.IxHelperFunctions; -import rx.*; -import rx.Observable; -import rx.functions.*; - -/** - * An iterable builder which offers methods to chain the - * sequence of some Interactive operations. - *

This builder is the dual of the - * {@link rx.Observable} class.

- * @param the element type - */ -public class Ix implements Iterable { - /** - * Creates an iterable builder which contains the concatenation - * of all the iterables returned by the iterable. - * @param the value type - * @param sources the source iterables - * @return the created iterable - */ - public static Ix concat(Iterable> sources) { - return from(Interactive.concat(sources)); - } - - /** - * Concatenates the array of Iterable sources into a single Iterable sequence. - * @param the value type - * @param sources the sources to concatenate - * @return the created iterable - * @since 0.92.3 - */ - public static Ix concat(Iterable... sources) { - return from(Interactive.concat(Arrays.asList(sources))); - } - - /** - * Defers the source iterable creation to registration time and - * calls the given func for the actual source. - * @param the element type - * @param func the function that returns an iterable. - * @return the new iterable - */ - public static Ix defer( - final Func0> func) { - return from(Interactive.defer(func)); - } - /** - * Creates a new iterable builder instance by wrapping the given - * source sequence, if not already a builder. - * @param the element type - * @param source the source sequence - * @return the created iterable builder - */ - public static Ix from(final Iterable source) { - if (source instanceof Ix) { - return (Ix)source; - } - return new Ix(source); - } - /** - * Creates a new iterable builder by wrapping the given observable. - *

The resulting iterable does not support the {@code remove()} method.

- * @param the element type - * @param source the source observable - * @return the created iterable builder - */ - public static Ix from(Observable source) { - return from(new ToIterable(source)); - } - /** - * Creates a new iterable builder instance by wrapping the given - * array. Changes to the array will be visible through - * the iterator. - * @param the element type - * @param ts the array of ts - * @return the created iterable builder - */ - public static Ix from(final T... ts) { - return from(Interactive.toIterable(ts)); - } - /** - * Creates an iterable which returns only a single element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param value the value to return - * @return the new iterable - */ - public static Ix just(final T value) { - return from(Interactive.just(value)); - } - /** - * Returns an iterator which will throw the given - * Throwable exception when the client invokes - * next() the first time. Any subsequent - * next() call will simply throw a NoSuchElementException. - * Calling remove() will always throw a IllegalStateException. - * If the given Throwable instance extends a RuntimeException, it is throws - * as is, but when the throwable is a checked exception, it is wrapped - * into a RuntimeException. - * @param the element type, irrelevant - * @param t the exception to throw - * @return the new iterable - */ - public static Ix error( - final Throwable t) { - return from(Interactive.error(t)); - } - - /** - * The singleton instance of an empty Ix. - */ - static final Ix EMPTY = from(Interactive.empty()); - - /** - * Returns an empty iterable which will not produce elements. - * Its hasNext() returns always false, - * next() throws a NoSuchElementException - * and remove() throws an IllegalStateException. - * Note that the Collections.emptyIterable() static method is introduced by Java 7. - * @param the element type, irrelevant - * @return the iterable - */ - @SuppressWarnings("unchecked") - public static Ix empty() { - return (Ix)EMPTY; - } - /** - * Creates a new iterable builder instance by wrapping the given - * array. Changes to the array will be visible through - * the iterator. - * @param the element type - * @param from the source index inclusive - * @param to the destination index exclusive - * @param ts the array of ts - * @return the created iterable builder - */ - public static Ix fromPart(int from, int to, final T... ts) { - return from(Interactive.toIterablePart(from, to, ts)); - } - /** - * A generator function which returns Ts based on the termination condition and the way it computes the next values. - * This is equivalent to: - *

-     * T value = seed;
-     * while (predicate(value)) {
-     *     yield value;
-     *     value = next(value);
-     * }
-     * 
- *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param seed the initial value - * @param predicate the predicate to terminate the process - * @param next the function that computes the next value. - * @return the new iterable - */ - public static Ix generate(T seed, Func1 predicate, Func1 next) { - return from(Interactive.generate(seed, predicate, next)); - } - /** - * Creates a new iterable builder instance by wrapping the given - * source sequence. - * @param the element type - * @param source the source sequence - * @return the created iterable builder - */ - public static Ix newBuilder(final Iterable source) { - return new Ix(source); - } - /** - * Creates an integer iteratable builder which returns numbers from the start position in the count size. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param start the starting value. - * @param count the number of elements to return, negative count means counting down from the start. - * @return the iterator. - */ - public static Ix range(int start, int count) { - return from(Interactive.range(start, count)); - } - /** - * Creates an long iterable builder which returns numbers from the start position in the count size. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param start the starting value. - * @param count the number of elements to return, negative count means counting down from the start. - * @return the iterator. - */ - public static Ix range(long start, long count) { - return from(Interactive.range(start, count)); - } - - /** - * Creates an iterable builder which repeats the given - * value indefinitely. - *

The resulting iterable does not support the {@code remove()} method.

- * @param the element type - * @param t the value to repeat - * @return the created iterable builder - */ - public static Ix repeat(final T t) { - return from(Interactive.repeat(t)); - } - /** - * Returns an iterable builder which repeats the given single value the specified number of times. - *

The returned iterable does not support the {@code remove()} method.

- * @param the value type - * @param t the value to repeat - * @param count the repeat amount - * @return the iterable - */ - public static Ix repeat(final T t, int count) { - return from(Interactive.repeat(t, count)); - } - /** - * @param the element type - * @return a function which wraps its iterable parameter into an iterablebuilder instance - */ - public static Func1, Ix> toBuilder() { - return new Func1, Ix>() { - @Override - public Ix call(Iterable param1) { - return from(param1); - } - }; - } - /** The backing iterable. */ - protected final Iterable it; - /** - * Constructor. - * @param source the backing iterable - */ - protected Ix(Iterable source) { - this.it = source; - } - /** - * Creates an iterable which traverses the source iterable and maintains a running sum value based - * on the sum function parameter. Once the source is depleted, it - * applies the divide function and returns its result. - * This operator is a general base for averaging (where {@code sum(u, t) => u + t}, {@code divide(u, index) => u / index}), - * summing (where {@code sum(u, t) => u + t}, and {@code divide(u, index) => u)}), - * minimum, maximum, etc. - * If the traversal of the source fails due an exception, that exception is reflected on the - * {@code next()} call of the returned iterator. - * The returned iterator will throw an UnsupportedOperationException - * for its remove() method. - * @param the itermediate aggregation type - * @param the resulting aggregation type - * @param sum the function which takes the current itermediate value, - * the current source value and should produce a new intermediate value. - * for the first element of T, the U parameter will receive null - * @param divide the function which takes the last intermediate value and a total count of Ts seen and should return the final aggregation value. - * @return the new iterable - */ - public final Ix aggregate( - final Func2 sum, - final Func2 divide) { - return from(Interactive.aggregate(it, sum, divide)); - } - /** - * Returns an iterable which contains true if all - * elements of the source iterable satisfy the predicate. - * The operator might return a false before fully iterating the source. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param predicate the predicate - * @return the new iterable - */ - public final Ix all(final Func1 predicate) { - return from(Interactive.all(it, predicate)); - } - /** - * Determines if the given source has any elements at all. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable with a single true or false - */ - public final Ix any() { - return from(Interactive.any(it)); - } - /** - * Tests if there is any element of the source that satisfies the given predicate function. - * @param predicate the predicate tester function - * @return the new iterable - */ - public final Ix any( - final Func1 predicate - ) { - return from(Interactive.any(it, predicate)); - } - /** - * Returns a pair of the maximum argument and value from the given sequence. - * @param the value type for the comparison, must be self comparable - * @param valueSelector the value selector function - * @return the pair of the first maximum element and value, null if the sequence was empty - */ - public final > Pair argAndMax( - Func1 valueSelector) { - return Interactive.argAndMax(it, valueSelector); - } - /** - * Returns a pair of the maximum argument and value from the given sequence. - * @param the value type - * @param valueSelector the selector to extract the value from T - * @param valueComparator the comparator to compare two values - * @return the first pair of max argument and value or null if the source sequence was empty - */ - public final Pair argAndMax( - Func1 valueSelector, - Comparator valueComparator) { - return Interactive.argAndMax(it, valueSelector, valueComparator); - } - /** - * Returns a pair of the minimum argument and value from the given sequence. - * @param the value type for the comparison, must be self comparable - * @param valueSelector the value selector function - * @return the pair of the first minimum element and value, null if the sequence was empty - */ - public final > Pair argAndMin( - Func1 valueSelector) { - return Interactive.argAndMin(it, valueSelector); - } - /** - * Returns a pair of the minimum argument and value from the given sequence. - * @param the value type - * @param valueSelector the selector to extract the value from T - * @param valueComparator the comparator to compare two values - * @return the first pair of minimum argument and value or null if the source sequence was empty - */ - public final Pair argAndMin( - Func1 valueSelector, - Comparator valueComparator) { - return Interactive.argAndMin(it, valueSelector, valueComparator); - } - /** - * Computes and signals the average value of the BigDecimal source. - * The source may not send nulls. - *

Note that it uses forced cast of this sequence. If T != BigDecimal this - * method is guaranteed to throw ClassCastException.

- * @return the observable for the average value - */ - @SuppressWarnings("unchecked") - public final Ix averageBigDecimal() { - return from(Interactive.averageBigDecimal((Iterable)it)); - } - /** - * Computes and signals the average value of the BigInteger source. - * The source may not send nulls. - *

Note that it uses forced cast of this sequence. If T != BigInteger this - * method is guaranteed to throw ClassCastException.

- * @return the observable for the average value - */ - - @SuppressWarnings("unchecked") - public final Ix averageBigInteger() { - return from(Interactive.averageBigInteger((Iterable)it)); - } - /** - * Computes and signals the average value of the Double source. - * The source may not send nulls. - * @return the observable for the average value - */ - - @SuppressWarnings("unchecked") - public final Ix averageDouble() { - return from(Interactive.averageDouble((Iterable)it)); - } - /** - * Computes and signals the average value of the Float source. - * The source may not send nulls. - * @return the observable for the average value - */ - - @SuppressWarnings("unchecked") - public final Ix averageFloat() { - return from(Interactive.averageFloat((Iterable)it)); - } - /** - * Computes and signals the average value of the integer source. - * The source may not send nulls. - * The intermediate aggregation used double values. - * @return the observable for the average value - */ - - @SuppressWarnings("unchecked") - public final Ix averageInt() { - return from(Interactive.averageInt((Iterable)it)); - - } - /** - * Computes and signals the average value of the Long source. - * The source may not send nulls. - * The intermediate aggregation used double values. - * @return the observable for the average value - */ - - @SuppressWarnings("unchecked") - public final Ix averageLong() { - return from(Interactive.averageLong((Iterable)it)); - } - /** - * Returns an iterable which buffers the source elements - * into bufferSize lists. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param bufferSize the buffer size. - * @return the new iterable - */ - public final Ix> buffer(int bufferSize) { - return from(Interactive.buffer(it, bufferSize)); - } - - /** - * Collects all values from this sequence into a custom collection via the collector - * action and returns the collection as a single element. - * @param collectionSupplier the function that creates a collection for individual iterations - * @param collector the action that is called by the collection instance and the current - * element in the sequence - * @return the new iterable - * @since 0.92.3 - */ - public final Ix collect(Func0 collectionSupplier, Action2 collector) { - return from(new CollectIterable(this, collectionSupplier, collector)); - } - - /** - * Concatenate this iterable with the other iterable in a way, that calling the second iterator() - * only happens when there is no more element in the first iterator. - *

The returned iterator forwards all remove() calls - * to the current source (first or next). - * @param other the second iterable - * @return the new iterable - */ - public final Ix concatWith(Iterable other) { - return from(Interactive.concat(it, other)); - } - /** - * Concatenate this iterable with the sequence of array values. - * @param values the array values - * @return the created iterable builder - */ - public final Ix concatWith(final T... values) { - return concatWith(Interactive.toIterable(values)); - } - /** - * Creates an iterable builder which contains the concatenation - * of this iterable and the rest iterable provided. - * @param others the other iterables - * @return the created iterable - */ - @SuppressWarnings("unchecked") - public final Ix concatWithAll(Iterable> others) { - return from(Interactive.concat(Interactive.startWith(others, it))); - } - /** - * Returns an iterable which checks for the existence of the supplied - * value by comparing the elements of the source iterable using reference - * and equals(). The iterable then returns a single true or false. - * @param value the value to check - * @return the new iterable - */ - public final Ix contains(final Object value) { - return from(Interactive.contains(it, value)); - } - /** - * Counts the elements of the iterable source by using a 32 bit int. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable - */ - public final Ix count() { - return from(Interactive.count(it)); - } - /** - * Counts the elements of the iterable source by using a 64 bit long. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable - */ - public final Ix countLong() { - return from(Interactive.countLong(it)); - } - /** - * Convert the source materialized elements into normal iterator behavior. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final Ix dematerialize() { - return from(Interactive.dematerialize((Iterable>)it)); - } - /** - * Returns an iterable which filters its elements based if they vere ever seen before in - * the current iteration. - * Value equality is computed by reference equality and equals() - * @return the new iterable - */ - public final Ix distinct() { - return from(Interactive.distinct(it)); - } - /** - * Returns an iterable which filters its elements by an unique key - * in a way that when multiple source items produce the same key, only - * the first one ever seen gets relayed further on. - * Key equality is computed by reference equality and equals() - * @param the key element type - * @param keySelector the key selector for only-once filtering - * @return the new iterable - */ - public final Ix distinct(Func1 keySelector) { - return from(Interactive.distinct(it, keySelector, IxHelperFunctions.identity())); - } - /** - * Creates an iterable which ensures that subsequent values of T are not equal - * (reference and equals). - * @return the new iterable - */ - public final Ix distinctNext() { - return from(Interactive.distinctNext(it)); - } - /** - * Creates an iterable which ensures that subsequent values of - * T are not equal in respect to the extracted keys (reference and equals). - * @param the key type - * @param keySelector the function to extract the keys which will be compared - * @return the new iterable - */ - public final Ix distinctNext(final Func1 keySelector) { - return from(Interactive.distinctNext(it, keySelector)); - } - /** - * Returns an iterable which executes the given action after - * the stream completes. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param action the action to invoke - * @return the new iterable - */ - public final Ix doOnCompleted(Action0 action) { - return from(Interactive.doOnCompleted(it, action)); - } - /** - * Construct a new iterable which will invoke the specified action - * before the source value gets relayed through it. - * Can be used to inject side-effects before returning a value. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param action the action to invoke before each next() is returned. - * @return the new iterable - */ - public final Ix doOnNext(Action1 action) { - return from(Interactive.doOnNext(it, action)); - } - /** - * Returns an iterable which reiterates over and over again on source - * as long as the gate is true. The gate function is checked only - * when a pass over the source stream was completed. - * Note that using this operator on an empty iterable may result - * in a direct infinite loop in hasNext() or next() calls depending on the gate function. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param gate the gate function to stop the repeat - * @return the new iterable - */ - - public final Ix doWhile( - final Func0 gate) { - return from(Interactive.doWhile(it, gate)); - } - /** - * Creates an iterable sequence which returns all elements from source - * followed by the supplied value as last. - *

The returned iterable forwards all {@code remove()} - * methods to the source iterable, except the last element where it - * throws UnsupportedOperationException.

- * @param value the value to append - * @return the new iterable - */ - public final Ix endWith(final T value) { - return from(Interactive.endWith(it, value)); - } - /** - * Creates an iterable which filters this iterable with the - * given predicate factory function. The predicate returned by the factory receives an index - * telling how many elements were processed thus far. - * Use this construct if you want to use some memorizing predicat function (e.g., filter by subsequent distinct, filter by first occurrences only) - * which need to be invoked per iterator() basis. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param predicate the predicate function - * @return the new iterable - */ - public final Ix filter(final Func1 predicate) { - return from(Interactive.filter(it, predicate)); - } - /** - * Creates an iterable which filters this iterable with the - * given predicate factory function. The predicate returned by the factory receives an index - * telling how many elements were processed thus far. - * @param predicate the predicate - * @return the new iterable - */ - public final Ix filterIndexed(final Func2 predicate) { - return from(Interactive.filterIndexed(it, predicate)); - } - /** - * Returns the first element from the iterable sequence or - * throws a NoSuchElementException. - * @return the first element - */ - public final T first() { - return Interactive.first(it); - } - - /** - * Returns the first element from the sequence or the default - * value if this sequence is empty - * @param defaultValue the default value to return - * @return the first or default value - * @since 0.91.2 - */ - public final T firstOrDefault(T defaultValue) { - return Interactive.firstOrDefault(it, defaultValue); - } - - /** - * Creates an iterable which returns a stream of Us for each source Ts. - * The iterable stream of Us is returned by the supplied selector function. - *

The returned iterator forwards all remove() calls - * to the current source (which might not accept it). - * @param the output element type - * @param selector the selector for multiple Us for each T - * @return the new iterable - */ - public final Ix flatMap(final Func1> selector) { - return from(Interactive.flatMap(it, selector)); - } - /** - * Iterate over the source and submit each value to the - * given action. Basically, a for-each loop with pluggable - * action. - * This method is useful when the concrete values from the iterator - * are not needed but the iteration itself implies some side effects. - * @param action the action to invoke on with element - */ - public final void forEach( - final Action1 action) { - Interactive.forEach(it, action); - } - /** - * Creates an iterable which traverses the source iterable, - * and based on the key selector, groups values the elements into GroupedIterables, - * which can be interated over later on. - * The equivalence of the keys are determined via reference - * equality and equals() equality. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the result group element type - * @param keySelector the key selector - * @return the new iterable - */ - public final Ix> groupBy( - final Func1 keySelector) { - return from(Interactive.groupBy(it, keySelector, IxHelperFunctions.identity())); - } - /** - * Creates an iterable which traverses the source iterable, - * and based on the key selector, groups values extracted by valueSelector into GroupedIterables, - * which can be interated over later on. - * The equivalence of the keys are determined via reference - * equality and equals() equality. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the result group element type - * @param the result group keys - * @param keySelector the key selector - * @param valueSelector the value selector - * @return the new iterable - */ - public final Ix> groupBy( - final Func1 keySelector, - final Func1 valueSelector) { - return from(Interactive.groupBy(it, keySelector, valueSelector)); - } - /** - * Add the elements of the sequence into the supplied collection. - * @param a collection type - * @param out the output collection - * @return the same out value - */ - public final > U into(U out) { - Iterator it = iterator(); - try { - while (it.hasNext()) { - out.add(it.next()); - } - } finally { - Interactive.unsubscribe(it); - } - return out; - } - /** - * Returns a single true if the target iterable is empty. - * @return the new iterable - */ - public final Ix isEmpty() { - return from(Interactive.isEmpty(it)); - } - @Override - public final Iterator iterator() { - return it.iterator(); - } - /** - * Concatenates the source strings one after another and uses the given separator. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param separator the separator to use - * @return the new iterable - */ - public final Ix join(String separator) { - return from(Interactive.join(it, separator)); - } - /** - * Returns the last element of the iterable or throws a - * NoSuchElementException if the iterable is empty. - * @return the last value - */ - public final T last() { - return Interactive.last(it); - } - - /** - * Returns the last element of this sequence or the default value if - * this sequence is empty. - * @param defaultValue the default value to return if this sequence is empty - * @return the last or default value - */ - public final T lastOrDefault(T defaultValue) { - return Interactive.lastOrDefault(it, defaultValue); - } - - /** - * Creates an iterable which is a transforms the source - * elements by using the selector function. - * The function receives the current element. - * @param the output element type - * @param selector the selector function - * @return the new iterable - */ - public final Ix map(final Func1 selector) { - return from(Interactive.map(it, selector)); - } - /** - * Creates an iterable which is a transforms the source - * elements by using the selector function. - * The function receives the current index and the current element. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the output element type - * @param selector the selector function - * @return the new iterable - */ - public final Ix mapIndexed(final Func2 selector) { - return from(Interactive.mapIndexed(it, selector)); - } - /** - * Transforms the sequence of the source iterable into an option sequence of - * Option.some(), Option.none() and Option.error() values, depending on - * what the source's hasNext() and next() produces. - * The returned iterator will throw an UnsupportedOperationException for its remove() method. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable - */ - public final Ix> materialize() { - return from(Interactive.materialize(it)); - } - /** - * Returns the maximum value of the given iterable source. - * @param the self comparable type - * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final > Ix max() { - return from(Interactive.max((Iterable)it)); - } - /** - * Returns the maximum value of the given iterable source in respect to the supplied comparator. - * @param comparator the comparator to use - * @return the new iterable - */ - public final Ix max(Comparator comparator) { - return from(Interactive.max(it, comparator)); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied key selector. - * @param the source element type, which must be self comparable - * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final > Ix> maxBy() { - return from(Interactive.maxBy((Iterable)it)); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied comparator. - * @param comparator the key comparator - * @return the new iterable - */ - public final Ix> maxBy(Comparator comparator) { - return from(Interactive.maxBy(it, comparator)); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied key selector. - * @param the key type, which must be self-comparable - * @param keySelector the selector for keys - * @return the new iterable - */ - public final > Ix> mayBy(Func1 keySelector) { - return from(Interactive.maxBy(it, keySelector)); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector and comparator. - * @param the key type - * @param keySelector the selector for keys - * @param keyComparator the key comparator - * @return the new iterable - */ - public final Ix> mayBy(Func1 keySelector, Comparator keyComparator) { - return from(Interactive.maxBy(it, keySelector, keyComparator)); - } - /** - * Enumerates the source iterable once and caches its results. - * Any iterator party will basically drain this cache, e.g., - * reiterating over this iterable will produce no results. - * Note: the name is not a misspelling, see Memoization. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param bufferSize the size of the buffering - * @return the new iterable - */ - public final Ix memoize(int bufferSize) { - return from(Interactive.memoize(it, bufferSize)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the values. - * Note: the name is not a misspelling, see Memoization. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the new iterable - */ - public final Ix memoizeAll() { - return from(Interactive.memoizeAll(it)); - } - /** - * Returns the maximum value of the given iterable source. - * @param the self comparable type - * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final > Ix min() { - return from(Interactive.min((Iterable)it)); - } - /** - * Returns the minimum value of the given iterable source in respect to the supplied comparator. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param comparator the comparator to use - * @return the new iterable - */ - public final Ix min(Comparator comparator) { - return from(Interactive.min(it, comparator)); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied comparator. - * @param comparator the key comparator - * @return the new iterable - */ - public final Ix> minBy(Comparator comparator) { - return from(Interactive.minBy(it, comparator)); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the key type, which must be self-comparable - * @param keySelector the selector for keys - * @return the new iterable - */ - public final > Ix> minBy(Func1 keySelector) { - return from(Interactive.minBy(it, keySelector)); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector and comparator. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the key type - * @param keySelector the selector for keys - * @param keyComparator the key comparator - * @return the new iterable - */ - public final Ix> minBy(Func1 keySelector, Comparator keyComparator) { - return from(Interactive.minBy(it, keySelector, keyComparator)); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type, which must be self comparable - * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final > Ix> minxBy() { - return from(Interactive.minBy((Iterable)it)); - } - /** - * Casts the source iterable into a different typ by using a type token. - * If the source contains a wrong element, the next() - * will throw a ClassCastException. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the result element type - * @param token the type token - * @return the new iterable - */ - public final Ix ofType(final Class token) { - return from(Interactive.ofType(it, token)); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - *

Note: the element type should be self comparable or a ClassCastException is thrown.

- * @param the source element type, which must be self comparable - * @return the new iterable - */ - @SuppressWarnings("unchecked") - public final > Ix orderBy() { - return from(Interactive.orderBy((Iterable)it)); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param comparator the value comparator - * @return the new iterable - */ - public final Ix orderBy(Comparator comparator) { - return from(Interactive.orderBy(it, comparator)); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the key type for the ordering, must be self comparable - * @param keySelector the key selector for comparison - * @return the new iterable - */ - public final > Ix orderBy(Func1 keySelector) { - return from(Interactive.orderBy(it, keySelector)); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the key type for the ordering - * @param keySelector the key selector for comparison - * @param keyComparator the key comparator function - * @return the new iterable - */ - public final Ix orderBy(Func1 keySelector, Comparator keyComparator) { - return from(Interactive.orderBy(it, keySelector, keyComparator)); - } - /** - * Runs this iterable and prints the values. - *

Is the same as using {@code this.run(Interactive.print())}.

- */ - public final void print() { - Interactive.forEach(it, Interactive.print()); - } - /** - * Runs this iterable and prints the values. - *

Is the same as using {@code this.run(Interactive.println())}.

- */ - public final void println() { - Interactive.forEach(it, Interactive.println()); - } - /** - * Applies the func function for a shared instance of the source, - * e.g., func.invoke(share(source)). - * @param the return types - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - */ - public final Ix prune(Func1, ? extends Iterable> func) { - return from(Interactive.prune(it, func)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the same cached values. - *

The returned iterator will throw an UnsupportedOperationException - * for remove() method of its first element, then it might throw for any - * subsequent element, depending on the source iterable.

- * @param the return types - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @param initial the initial value to append to the output stream - * @return the new iterable - */ - public final Ix publish(final Func1, ? extends Iterable> func, - final U initial) { - return from(Interactive.publish(it, func, initial)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the return types - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - */ - public final Ix publish(final Func1, ? extends Iterable> func) { - return from(Interactive.publish(it, func)); - } - /** - * Reduces the values of this sequence into a single value by using a - * reducer function. - * @param reducer the reducer function that receives the first item or - * the result of the previous application of the function as the first parameter - * and the current item as the second parameter. - * @return the new Iterable - * @since 0.92.3 - */ - public final Ix reduce(Func2 reducer) { - return from(new ReduceIterable(this, reducer)); - } - /** - * Consumes the sequence and removes all items via the Iterator.remove(). - */ - public final void removeAll() { - Iterator it = iterator(); - try { - while (it.hasNext()) { - it.next(); - it.remove(); - } - } finally { - Interactive.unsubscribe(it); - } - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator may only see one source element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the return types - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - */ - public final Ix replay(final Func1, ? extends Iterable> func) { - return from(Interactive.replay(it, func)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the some cached values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the return types - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @param bufferSize the buffer size - * @return the new iterable - */ - public final Ix replay(final Func1, ? extends Iterable> func, - final int bufferSize) { - return from(Interactive.replay(it, func, bufferSize)); - } - /** - * Iterates over the given source without using its returned value. - * This method is useful when the concrete values from the iterator - * are not needed but the iteration itself implies some side effects. - */ - public final void run() { - Interactive.run(it); - } - /** - * Generates an iterable which acts like a running sum when iterating over the source iterable, e.g., - * For each element in T, it computes a value by using the current aggregation value and returns it. - * The first call to the aggregator function will receive a zero for its first argument. - * @param the destination element type - * @param aggregator the function which takes the current running aggregation value, the current element and produces a new aggregation value. - * @return the new iterable - */ - public final Ix scan(final Func2 aggregator) { - return from(Interactive.scan(it, aggregator)); - } - /** - * Generates an iterable which acts like a running sum when iterating over the source iterable, e.g., - * For each element in T, it computes a value by using the current aggregation value and returns it. - * The first call to the aggregator function will receive a zero for its first argument. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the destination element type - * @param seed the initial value of the running aggregation - * @param aggregator the function which takes the current running aggregation value, the current element and produces a new aggregation value. - * @return the new iterable - */ - public final Ix scan(final U seed, - final Func2 aggregator) { - return from(Interactive.scan(it, seed, aggregator)); - } - /** - * Returns an iterable which ensures the source iterable is - * only traversed once and clients may take values from each other, - * e.g., they share the same iterator. - * @return the new iterable - */ - public final Ix share() { - return from(Interactive.share(it)); - } - - /** - * Skips the specified amount of items at the beginning of the source sequence. - * @param num the number of elements to skip - * @return the new iterable - */ - public final Ix skip(final int num) { - return from(Interactive.skip(it, num)); - } - - /** - * Returns an iterable which skips the last num elements from the - * source iterable. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param num the number of elements to skip at the end - * @return the new iterable - */ - public final Ix skipLast(final int num) { - return from(Interactive.skipLast(it, num)); - } - /** - * Returns an iterable which prefixes the source iterable values - * by a constant. - * It is equivalent to concat(singleton(value), source). - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method for the first element, and might - * throw for subsequent elements, depending on the source iterable.

- * @param value the value to prefix - * @return the new iterable. - */ - @SuppressWarnings("unchecked") - public final Ix startWith(T value) { - return from(Interactive.startWith(it, value)); - } - /** - * Returns each pair of subsequent elements as pairs. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @return the iterable builder - */ - public final Ix> subsequent() { - return from(Interactive.subsequent(it)); - } - /** - * Returns each pair of subsequent elements as pairs. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param count the number of subsequent elements - * @return the iterable builder - */ - public final Ix> subsequent(int count) { - return from(Interactive.subsequent(it, count)) - .map(Ix.toBuilder()); - } - /** - * Computes and signals the sum of the values of the BigDecimal source. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumBigDecimal() { - return from(Interactive.sumBigDecimal((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the BigInteger source. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumBigInteger() { - return from(Interactive.sumBigInteger((Iterable)it)); - } - - /** - * Computes and signals the sum of the values of the Double source. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumDouble() { - return from(Interactive.sumDouble((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the Float source. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumFloat() { - return from(Interactive.sumFloat((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the Integer source. - * The source may not send nulls. An empty source produces an empty sum - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumInt() { - return from(Interactive.sumInt((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the Integer source by using - * a double intermediate representation. - * The source may not send nulls. An empty source produces an empty sum - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumIntAsDouble() { - return from(Interactive.sumIntAsDouble((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the Long source. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumLong() { - return from(Interactive.sumLong((Iterable)it)); - } - /** - * Computes and signals the sum of the values of the Long sourceby using - * a double intermediate representation. - * The source may not send nulls. - * @return the observable for the sum value - */ - - @SuppressWarnings("unchecked") - public final Ix sumLongAsDouble() { - return from(Interactive.sumLongAsDouble((Iterable)it)); - } - /** - * Returns the iterable which returns the first num element. - * from the source iterable. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param num the number of items to take - * @return the new iterable - */ - public final Ix take(int num) { - return from(Interactive.take(it, num)); - } - /** - * Returns an iterable which takes only the last num elements from the - * source iterable. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param num the number of elements to skip at the end - * @return the new iterable - */ - public final Ix takeLast(int num) { - return from(Interactive.takeLast(it, num)); - } - /** - * Returns an object array of all elements in this - * iterable. - * @return the object array - */ - public final Object[] toArray() { - return toList().toArray(); - } - /** - * Returns all elements from this iterable into either - * the given array or a new array if the size requires. - * @param a the output array - * @return the output array - */ - public final T[] toArray(T[] a) { - return toList().toArray(a); - } - /** - * Convinience method to create a hashmap from the elements. - * @param the key type - * @param keySelector the key selector - * @return the map - */ - public final Map toHashMap(Func1 keySelector) { - return toMap(keySelector, IxHelperFunctions.identity(), IxHelperFunctions.hashMapProvider()); - } - /** - * Convinience method to create a hash-multimap with list from the elements. - * @param the key type - * @param keySelector the key selector - * @return the multimap - */ - public final Map> toHashMultimap(Func1 keySelector) { - return toMultimap( - keySelector, - IxHelperFunctions.identity(), - IxHelperFunctions.>hashMapProvider(), - IxHelperFunctions.arrayListProvider()); - } - /** - * Iterates over and returns all elements in a list. - * @return the list of the values from this iterable - */ - public final List toList() { - List result = new ArrayList(); - into(result); - return result; - } - /** - * Convert the iterable values into a map representation. - *

If an element maps to the same key, the existing value will be overwritten.

- *

See Functions.hashMapProvider() and others for some standard map implementations.

- * @param the key type - * @param keySelector the function to extract a key from an element - * @param mapProvider the map provider - * @return the filled-in map. - */ - public final Map toMap( - Func1 keySelector, - Func0> mapProvider) { - return toMap(keySelector, IxHelperFunctions.identity(), mapProvider); - } - /** - * Convert the iterable values into a map representation. - *

If an element maps to the same key, the existing value will be overwritten.

- * @param the key type - * @param the value type - * @param keySelector the function to extract a key from an element - * @param valueSelector the function to extract a value from an element - * @param mapProvider the map provider - * @return the filled-in map. - */ - public final Map toMap( - Func1 keySelector, - Func1 valueSelector, - Func0> mapProvider) { - Map map = mapProvider.call(); - Iterator it = iterator(); - try { - while (it.hasNext()) { - T t = it.next(); - K key = keySelector.call(t); - V value = valueSelector.call(t); - map.put(key, value); - } - } finally { - Interactive.unsubscribe(it); - } - return map; - } - /** - * Convert the values into a multimap representation where each - * key can have multiple values. - *

See Functions.hashMapProvider(), Functions.arrayListProvider() - * and others for some standard map implementations.

- * @param the key type - * @param the value type - * @param the collection type - * @param keySelector the key selector - * @param valueSelector the value selector - * @param mapProvider the provider for the base map - * @param collectionProvider the provider for the value collection - * @return the multimap - */ - public final > Map toMultimap( - Func1 keySelector, - Func1 valueSelector, - Func0> mapProvider, - Func0 collectionProvider) { - Map result = mapProvider.call(); - Iterator it = iterator(); - try { - while (it.hasNext()) { - T t = it.next(); - K key = keySelector.call(t); - V value = valueSelector.call(t); - - C coll = result.get(key); - if (coll == null) { - coll = collectionProvider.call(); - result.put(key, coll); - } - coll.add(value); - } - } finally { - Interactive.unsubscribe(it); - } - return result; - } - /** - * Converts this iterable into an observable builder - * which uses the default scheduler of {@link rx.Observable} to emit values. - * @return the observable builder - */ - public final Observable toObservable() { - return Observable.from(it); - } - /** - * Converts this iterable into an observable builder - * which uses the supplied Scheduler to emit values. - * @param scheduler the scheduler - * @return the observable builder - */ - public final Observable toObservable(Scheduler scheduler) { - return Observable.from(it).subscribeOn(scheduler); - } - - /** - * Pairs each element from this and the oher iterable source and - * combines them into a new value by using the combiner - * function. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the right source type - * @param the result type - * @param right the right source - * @param combiner the combiner function - * @return the new iterable - */ - public final Ix zipWith(final Iterable right, - final Func2 combiner) { - return from(Interactive.zip(it, right, combiner)); - } -} +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; +import java.util.concurrent.Callable; + +/** + * Base class and entry point for fluent Iterables. + *

+ * All operators tolerate {@code null} elements. + *

+ * The Iterables have to be run in a single-threaded manner and none of + * the participating operators expect or support concurrency. + * @param the value type + * @since 1.0 + */ +public abstract class Ix implements Iterable { + + /** + * Emits all characters from the given CharSequence as integer values. + *

+ * The result's iterator() doesn't support remove(). + * @param cs the source character sequence, not null + * @return the new Ix instance + * @throws NullPointerException if cs is null + * @since 1.0 + */ + public static Ix characters(CharSequence cs) { + return new IxCharacters(cs, 0, cs.length()); + } + + /** + * Emits a range of characters from the given CharSequence as integer values. + *

+ * The result's iterator() doesn't support remove(). + * @param cs the source character sequence, not null + * @param start the start character index, inclusive, non-negative + * @param end the end character index, exclusive, non-negative + * @return the new Ix instance + * @throws NullPointerException if cs is null + * @throws IndexOutOfBoundsException if start is out of range [0, cs.length] + * @since 1.0 + */ + public static Ix characters(CharSequence cs, int start, int end) { + int len = cs.length(); + if (start < 0 || end < 0 || start > len || end > len) { + throw new IndexOutOfBoundsException("start=" + start + ", end=" + end + ", length=" + len); + } + return new IxCharacters(cs, start, end); + } + + /** + * Concatenates the elements of Iterable sources, provided as an Iterable itself, sequentially. + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the common base type + * @param sources the Iterable sequence of source Iterables + * @return the new Ix instance + * @throws NullPointerException if sources is null + * @since 1.0 + * @see #merge(Iterable) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Ix concat(Iterable> sources) { + return new IxFlattenIterable, T>( + (Iterable)nullCheck(sources, "sources is null"), + IdentityHelper.>instance()); + } + + /** + * Concatenates the elements of two Iterable sources sequentially + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the value type + * @param source1 the first source, not null + * @param source2 the second source, not null + * @return the new Iterable source + * @throws NullPointerException if any of the sources is null + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public static Ix concat(Iterable source1, Iterable source2) { + return concatArray(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null")); + } + + /** + * Concatenates the elements of three Iterable sources sequentially + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the value type + * @param source1 the first source, not null + * @param source2 the second source, not null + * @param source3 the third source, not null + * @return the new Iterable source + * @throws NullPointerException if any of the sources is null + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public static Ix concat(Iterable source1, Iterable source2, + Iterable source3) { + return concatArray(nullCheck(source1, "source1 is null"), + nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null")); + } + + /** + * Concatenates the elements of three Iterable sources sequentially + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the value type + * @param source1 the first source, not null + * @param source2 the second source, not null + * @param source3 the third source, not null + * @param source4 the fourth source, not null + * @return the new Iterable source + * @throws NullPointerException if any of the sources is null + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public static Ix concat(Iterable source1, Iterable source2, + Iterable source3, Iterable source4) { + return concatArray(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), + nullCheck(source3, "source3 is null"), nullCheck(source4, "source4 is null")); + } + + /** + * Concatenates the elements of Iterable sources, provided as an array, sequentially. + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the common base type + * @param sources the array of source Iterables + * @return the new Ix instance + * @throws NullPointerException if sources is null + * @since 1.0 + * @see #mergeArray(Iterable...) + */ + @SuppressWarnings("unchecked") + public static Ix concatArray(Iterable... sources) { + int n = sources.length; + if (n == 0) { + return empty(); + } + if (n == 1) { + return from((Iterable)sources[0]); + } + return new IxFlattenArrayIterable((Iterable[])sources); + } + + /** + * Defers the generation of the actual Iterable till the iterator() is called on + * the resulting Ix. + *

+ * The result's iterator() forwards the remove() calls to the generated Iterable's Iterator. + * @param the value type + * @param factory the function that returns an Iterable when the resulting Ix.iterator() is called + * @return the new Ix source + * @throws NullPointerException if factory is null + * @since 1.0 + */ + public static Ix defer(IxSupplier> factory) { + return new IxDefer(nullCheck(factory, "factory is null")); + } + + /** + * No elements are emitted. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @return the new Ix instance + * @since 1.0 + */ + public static Ix empty() { + return IxEmpty.instance(); + } + + /** + * Wraps the given Iterable source into an Ix instance (if + * not already an Ix subclass). + *

+ * The result's iterator() forwards the remove() calls to the source's + * iterator(). + * @param the value type + * @param source the Iterable to wrap, not null + * @return the new Ix instance + * @throws NullPointerException if source is null + * @since 1.0 + */ + public static Ix from(Iterable source) { + if (source instanceof Ix) { + return (Ix)source; + } + return new IxWrapper(nullCheck(source, "source")); + } + + /** + * Emits all the elements of the given array. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param values the array of values, not null + * @return the new Ix instance + * @throws NullPointerException if values is null + * @since 1.0 + */ + public static Ix fromArray(T... values) { + int n = values.length; + if (n == 0) { + return empty(); + } + if (n == 1) { + return just(values[0]); + } + return new IxFromArray(0, values.length, values); + } + + /** + * Emits a range of elements from the given array. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param start the staring index, inclusive, non-negative + * @param end the end index, exclusive, non-negative + * @param values the array of values + * @return the new Ix instance + * @throws NullPointerException if values is null + * @throws IndexOutOfBoundsException if either start or end are not in [0, values.length] + * @since 1.0 + */ + public static Ix fromArrayRange(int start, int end, T... values) { + if (start < 0 || end < 0 || start > values.length || end > values.length) { + throw new IndexOutOfBoundsException("start=" + start + ", end=" + end + ", length=" + values.length); + } + return new IxFromArray(start, end, values); + } + + /** + * Generates a sequence of values via a generic indexed for-loop style construct; + * the index starts with the given seed, checked via a condition (to terminate), + * generated from the index via the selector and then a new index is generated via next. + *

+ * The result's iterator() doesn't support remove(). + * @param the index value type + * @param the result value type + * @param seed the initial value of the index + * @param condition the receives the current index (before selector is called) and if it + * returns false, the sequence terminates + * @param next the function that receives the current index and returns the next index + * @param selector the function that receives the current index and returns the value + * to be emitted. + * @return the new Ix instance + * @throws NullPointerException if condition, next or selector is null + * @since 1.0 + */ + public static Ix forloop(T seed, IxPredicate condition, + IxFunction next, + IxFunction selector) { + return new IxForloop(seed, nullCheck(condition, "condition is null"), + nullCheck(selector, "selector is null"), nullCheck(next, "next is null")); + } + + /** + * Calls the given action to generate a value or terminate whenever the next() + * is called on the resulting Ix.iterator(). + *

+ * The result's iterator() doesn't support remove(). + *

+ * The action may call {@code onNext} at most once to signal the next value per action invocation. + * The {@code onCompleted} should be called to indicate no further values will be generated (may be + * called with an onNext in the same action invocation). Calling {@code onError} will immediately + * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). + * @param the value type + * @param nextSupplier the action called with an IxEmitter API to receive value, not null + * @return the new Ix instance + * @throws NullPointerException if nextSupplier is null + * @since 1.0 + */ + public static Ix generate(IxConsumer> nextSupplier) { + return new IxGenerateStateless(nullCheck(nextSupplier, "nextSupplier is null")); + } + + /** + * Calls the given function (with per-iterator state) to generate a value or terminate + * whenever the next() is called on the resulting Ix.iterator(). + *

+ * The result's iterator() doesn't support remove(). + *

+ * The action may call {@code onNext} at most once to signal the next value per action invocation. + * The {@code onCompleted} should be called to indicate no further values will be generated (may be + * called with an onNext in the same action invocation). Calling {@code onError} will immediately + * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). + * @param the value type + * @param the state type supplied to and returned by the nextSupplier function + * @param stateSupplier the function that returns a state for each invocation of iterator() + * @param nextSupplier the action called with an IxEmitter API to receive value, not null + * @return the new Ix instance + * @throws NullPointerException if stateSupplier or nextSupplier is null + * @since 1.0 + */ + public static Ix generate(IxSupplier stateSupplier, IxFunction2, S> nextSupplier) { + return generate(stateSupplier, nextSupplier, IxEmptyAction.instance1()); + } + + /** + * Calls the given function (with per-iterator state) to generate a value or terminate + * whenever the next() is called on the resulting Ix.iterator(). + *

+ * The result's iterator() doesn't support remove(). + *

+ * The action may call {@code onNext} at most once to signal the next value per action invocation. + * The {@code onCompleted} should be called to indicate no further values will be generated (may be + * called with an onNext in the same action invocation). Calling {@code onError} will immediately + * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). + *

+ * Note that since there is no direct way to cancel an Iterator, the stateDisposer is only invoked + * when the nextSupplier calls a terminal method. + * @param the value type + * @param the state type supplied to and returned by the nextSupplier function + * @param stateSupplier the function that returns a state for each invocation of iterator() + * @param nextSupplier the action called with an IxEmitter API to receive value, not null + * @param stateDisposer the action called when the nextSupplier signals an {@code onError} or {@code onCompleted}. + * @return the new Ix instance + * @throws NullPointerException if stateSupplier, nextSupplier or stateDisposer is null + * @since 1.0 + */ + public static Ix generate(IxSupplier stateSupplier, IxFunction2, S> nextSupplier, IxConsumer stateDisposer) { + return new IxGenerate(nullCheck(stateSupplier, "stateSupplier is null"), + nullCheck(nextSupplier, "nextSupplier is null"), nullCheck(stateDisposer, "stateDisposer is null")); + } + + /** + * Emits a single constant value. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param value the constant value to emit + * @return the new Ix instance + * @since 1.0 + */ + public static Ix just(T value) { + return new IxJust(value); + } + + /** + * Concatenates the elements of Iterable sources, provided as an Iterable itself, sequentially. + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the common base type + * @param sources the Iterable sequence of source Iterables + * @return the new Ix instance + * @throws NullPointerException if sources is null + * @since 1.0 + * @see #concat(Iterable) + */ + public static Ix merge(Iterable> sources) { + return concat(sources); + } + + /** + * Concatenates the elements of Iterable sources, provided as an array, sequentially. + *

+ * The result's iterator() forwards the remove() calls to the current iterator. + *

+ * Note that merge and concat operations are the same in the Iterable world. + * @param the common base type + * @param sources the array of source Iterables + * @return the new Ix instance + * @throws NullPointerException if sources is null + * @since 1.0 + * @see #concatArray(Iterable...) + */ + public static Ix mergeArray(Iterable... sources) { + return concatArray(sources); // concat and merge are the same in the Iterable world + } + + /** + * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking + * the smallest item from all those inner Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables of self-comparable items + * @return the new Ix instance + * @since 1.0 + */ + public static > Ix orderedMerge(Iterable> sources) { + return orderedMerge(sources, SelfComparator.INSTANCE); + } + + /** + * Merges items from an Iterable sequence of Iterable sequences, picking + * the smallest item (according to a custom comparator) from all those inner + * Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables + * @param comparator the comparator to compare items and pick the one that returns negative will be picked + * @return the new Ix instance + * @since 1.0 + */ + public static Ix orderedMerge(Iterable> sources, Comparator comparator) { + return new IxOrderedMergeIterable(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); + } + + /** + * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking + * the smallest item from all those inner Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables of self-comparable items + * @return the new Ix instance + * @since 1.0 + */ + public static > Ix orderedMergeArray(Iterable... sources) { + return orderedMergeArray(SelfComparator.INSTANCE, sources); + } + + /** + * Merges items from an array of Iterable sequences, picking + * the smallest item (according to a custom comparator) from all those inner + * Iterables until all sources complete. + * @param the value type + * @param sources the Iterable sequence of Iterables + * @param comparator the comparator to compare items and pick the one that returns negative will be picked + * @return the new Ix instance + * @since 1.0 + */ + public static Ix orderedMergeArray(Comparator comparator, Iterable... sources) { + return new IxOrderedMergeArray(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); + } + + /** + * Emits a range of incrementing integer values, starting from {@code start} and + * up to {@code count} times. + * @param start the starting value + * @param count the number of integers to emit, non-negative + * @return the new Ix instance + * @throws IllegalArgumentException if count is negative + * @since 1.0 + */ + public static Ix range(int start, int count) { + if (count == 0) { + return empty(); + } + if (count == 1) { + return just(start); + } + if (count < 0) { + throw new IllegalArgumentException("count >= 0 required but it was " + count); + } + return new IxRange(start, count); + } + + /** + * Prevents the downstream from calling remove() and throws + * an UnsupportedOperationException instead. + * @return the new Ix instance + * @see #readOnly(boolean) + * @since 1.0 + */ + public final Ix readOnly() { + return new IxReadOnly(this, false); + } + + /** + * Prevents the downstream from calling remove() by optionally + * ignoring it or throwing an UnsupportedOperationException. + * @param silent if true, remove() calls are ignored; if false, + * remove() calls throw an UnsupportedOperationException + * @return the new Ix instance + * @since 1.0 + */ + public final Ix readOnly(boolean silent) { + return new IxReadOnly(this, silent); + } + + /** + * Repeatedly calls the given callable indefinitely and + * emits the returned value. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param callable the callable to call + * @return the new Ix instance + * @since 1.0 + */ + public static Ix repeatCallable(Callable callable) { + return new IxRepeatCallable(nullCheck(callable, "callable is null")); + } + + /** + * Repeats the given value indefinitely. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param value the value to emit whenever next() is called + * @return the new Ix instance + * @since 1.0 + */ + public static Ix repeatValue(T value) { + return new IxRepeat(value); + } + + /** + * Repeats the given value at most count times. + *

+ * A count of zero will yield an empty sequence, a count of one + * will yield a sequence with only one element and so forth. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param value the value to emit + * @param count the number of times to emit the value, non-negative + * @return the new Ix instance + * @throws IllegalArgumentException if count is negative + * @since 1.0 + */ + public static Ix repeatValue(T value, long count) { + return new IxRepeatCount(value, nonNegative(count, "count")); + } + + /** + * Repeats the given value until the given predicate returns true. + *

+ * A count of zero will yield an empty sequence, a count of one + * will yield a sequence with only one element and so forth. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param value the value to emit + * @param stopPredicate the predicate called before any emission; returning + * false keeps repeating the value, returning true terminates the sequence + * @return the new Ix instance + * @throws NullPointerException if stopPredicate is null + * @since 1.0 + */ + public static Ix repeatValue(T value, IxBooleanSupplier stopPredicate) { + return repeatValue(value, Long.MAX_VALUE, stopPredicate); + } + + /** + * Repeats the given value at most count times or until the given predicate returns true. + *

+ * A count of zero will yield an empty sequence, a count of one + * will yield a sequence with only one element and so forth. + *

+ * The result's iterator() doesn't support remove(). + * @param the value type + * @param value the value to emit + * @param count the number of times to emit the value, non-negative + * @param stopPredicate the predicate called before any emission; returning + * false keeps repeating the value, returning true terminates the sequence + * @return the new Ix instance + * @throws IllegalArgumentException if count is negative + * @throws NullPointerException if stopPredicate is null + * @since 1.0 + */ + public static Ix repeatValue(T value, long count, IxBooleanSupplier stopPredicate) { + return new IxRepeatPredicate(value, nonNegative(count, "count"), nullCheck(stopPredicate, "stopPredicate is null")); + } + + /** + * Emits a sequence of substring of a string split by the given separator. + *

+ * The result's iterator() doesn't support remove(). + * @param string the string to split, not null + * @param by the separator to split along, not null + * @return the new Ix instance + * @throws NullPointerException if string or by is null + * @since 1.0 + */ + public static Ix split(String string, String by) { + return new IxSplit(nullCheck(string, "string is null"), nullCheck(by, "by is null")); + } + + /** + * Combines the next element from each source Iterable via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the common element type of the sources + * @param the result value type + * @param sources the array of Iterable sources, not null + * @param zipper the function that takes an array of values and returns a value + * to be emitted, one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if sources or zipper is null + * @since 1.0 + */ + public static Ix zip(Iterable[] sources, IxFunction zipper) { + return new IxZipArray(nullCheck(sources, "sources is null"), nullCheck(zipper, "zipper is null")); + } + + /** + * Combines the next element from each source Iterable, provided as an Iterable itself, + * via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the common element type of the sources + * @param the result value type + * @param sources the Iterable of Iterable sources, not null + * @param zipper the function that takes an array of values and returns a value + * to be emitted, one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if sources or zipper is null + * @since 1.0 + */ + public static Ix zip(Iterable> sources, IxFunction zipper) { + return new IxZipIterable(nullCheck(sources, "sources is null"), nullCheck(zipper, "zipper is null")); + } + + /** + * Combines the next element from each source Iterable via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the first source's element type + * @param the second source's element type + * @param the result value type + * @param source1 the first source Iterable + * @param source2 the second source Iterable + * @param zipper the function that takes one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if any of the sources or zipper is null + * @since 1.0 + */ + public static Ix zip( + Iterable source1, Iterable source2, + IxFunction2 zipper) { + return new IxZip2(nullCheck(source1, "source1 is null"), + nullCheck(source2, "source2 is null"), nullCheck(zipper, "zipper is null")); + } + + /** + * Combines the next element from each source Iterable via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the first source's element type + * @param the second source's element type + * @param the third source's element type + * @param the result value type + * @param source1 the first source Iterable + * @param source2 the second source Iterable + * @param source3 the third source Iterable + * @param zipper the function that takes one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if any of the sources or zipper is null + * @since 1.0 + */ + public static Ix zip( + Iterable source1, Iterable source2, + Iterable source3, + IxFunction3 zipper) { + return new IxZip3(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), + nullCheck(source3, "source3 is null"), nullCheck(zipper, "zipper is null")); + } + + /** + * Combines the next element from each source Iterable via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the first source's element type + * @param the second source's element type + * @param the third source's element type + * @param the fourth source's element type + * @param the result value type + * @param source1 the first source Iterable + * @param source2 the second source Iterable + * @param source3 the third source Iterable + * @param source4 the fourth source Iterable + * @param zipper the function that takes one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if any of the sources or zipper is null + * @since 1.0 + */ + public static Ix zip( + Iterable source1, Iterable source2, + Iterable source3, Iterable source4, + IxFunction4 zipper) { + return new IxZip4(nullCheck(source1, "source1 is null"), + nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null"), + nullCheck(source4, "source4 is null"), nullCheck(zipper, "zipper is null")); + } + + //--------------------------------------------------------------------------------------- + // Instance operators + //--------------------------------------------------------------------------------------- + + /** + * Emits true if all elements of this sequence match a given predicate (including empty). + *

+ * The result's iterator() doesn't support remove(). + * @param predicate the predicate receiving each element + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + */ + public final Ix all(IxPredicate predicate) { + return new IxAll(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Emits true if any element of this sequence matches the given predicate, + * false otherwise (or for empty sequences). + *

+ * The result's iterator() doesn't support remove(). + * @param predicate the predicate receiving each element + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + */ + public final Ix any(IxPredicate predicate) { + return new IxAny(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Calls the given transformers with this and returns its value allowing + * fluent conversions to non-Ix types. + * @param the result type + * @param transformer the function receiving this Ix instance and returns a value + * @return the value returned by the transformer function + * @throws NullPointerException if transformer is null + * @since 1.0 + */ + public final R as(IxFunction, R> transformer) { + return transformer.apply(this); + } + + /** + * Calculates the float-based average of this sequence of numbers. + *

The returned sequence is empty if this sequence is empty. + *

This operator force-casts this sequence which may lead + * to ClassCastException if any of this sequence's elements is not + * a subclass of Number. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix averageFloat() { + return new IxAverageFloat((Iterable)this); + } + + /** + * Calculates the double-based average of this sequence of numbers. + *

The returned sequence is empty if this sequence is empty. + *

This operator force-casts this sequence which may lead + * to ClassCastException if any of this sequence's elements is not + * a subclass of Number. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix averageDouble() { + return new IxAverageDouble((Iterable)this); + } + + /** + * Buffers the subsequent {@code size} elements into a sequence of + * non-overlapping Lists. + *

+ * The result's iterator() doesn't support remove(). + * @param size the number of elements to group together, positive + * @return the new Ix instance + * @throws IllegalArgumentException if size is non-positive + * @since 1.0 + */ + public final Ix> buffer(int size) { + return new IxBuffer(this, positive(size, "size")); + } + + /** + * Buffers the subsequent {@code size} elements into a sequence of + * potentially overlapping Lists. + *

+ * The result's iterator() doesn't support remove(). + * @param size the number of elements to group together, positive + * @param skip specifies how often to start a new list + * @return the new Ix instance + * @throws IllegalArgumentException if size or skip is non-positive + * @since 1.0 + */ + public final Ix> buffer(int size, int skip) { + if (size == skip) { + return buffer(size); + } + if (size < skip) { + return new IxBufferSkip(this, positive(size, "size"), positive(skip, "skip")); + } + return new IxBufferOverlap(this, positive(size, "size"), positive(skip, "skip")); + } + + /** + * Buffer until an item is encountered for which the predicate returns true, + * triggering a new buffer. + *

Neither the previous nor the next buffer will contain the item that caused the + * split + * @param predicate the predicate called with each item and should return false + * to trigger a new buffer + * @return the new Ix instance + * @see #bufferUntil(IxPredicate) + * @see #bufferWhile(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferSplit(IxPredicate predicate) { + return new IxBufferSplit(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Buffer until an item is encountered after which the predicate returns true + * to start a new buffer. + *

The item will be part of the previous buffer. + * @param predicate the predicate called with each item after the item + * has been added to the current buffer and should return true to start a new buffer + * @return the new Ix instance + * @see #bufferSplit(IxPredicate) + * @see #bufferWhile(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferUntil(IxPredicate predicate) { + return new IxBufferUntil(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Buffer while an item is encountered before which the predicate returns false + * to start a new buffer. + *

The item will be part of the next buffer + * @param predicate the predicate called with each item after the item + * has been added to the current buffer and should return true to start a new buffer + * @return the new Ix instance + * @see #bufferSplit(IxPredicate) + * @see #bufferUntil(IxPredicate) + * @since 1.0 + */ + public final Ix> bufferWhile(IxPredicate predicate) { + return new IxBufferWhile(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Cast the elements to the specified class. + *

+ * Note that this is a forced cast on this Ix instance and if + * not compatible, a ClassCastException might be thrown downstream. + * @param the target type + * @param clazz the type token to capture the target type + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public final Ix cast(Class clazz) { + return (Ix)this; + } + + /** + * Collect the elements into a collection via collector action and emit that collection + * as a single item. + *

+ * The result's iterator() doesn't support remove(). + * @param the collection type + * @param initialFactory the function returning a collection for each iterator() call + * @param collector the action called with the collection and the current item + * @return the new Ix instance + * @throws NullPointerException if initialFactory or collector is null + * @since 1.0 + */ + public final Ix collect(IxSupplier initialFactory, IxConsumer2 collector) { + return new IxCollect(this, nullCheck(initialFactory, "initialFactory is null"), nullCheck(collector, "collector")); + } + + /** + * Collects the elements of this sequence into an Object array. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix collectToArray() { + return collect(ToListHelper.initialFactory(), ToListHelper.collector()) + .map(ToListHelper.toArray()); + } + + /** + * Collects the elements of this sequence into a List. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix> collectToList() { + return collect(ToListHelper.initialFactory(), ToListHelper.collector()); + } + + /** + * Collects the elements of this sequence into a Map where the key is + * determined from each element via the keySelector function; duplicates are + * overwritten. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + */ + public final Ix> collectToMap(IxFunction keySelector) { + IxFunction f = IdentityHelper.instance(); + return this.collectToMap(keySelector, f); + } + + /** + * Collects the elements of this sequence into a Map where the key is + * determined from each element via the keySelector function and + * the value is derived from the same element via the valueSelector function; duplicates are + * overwritten. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param the value type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @param valueSelector the function that receives the current element and returns + * a value for it to be used as the Map value + * @return the new Ix instance + * @throws NullPointerException if keySelector or valueSelector is null + * @since 1.0 + */ + public final Ix> collectToMap(IxFunction keySelector, IxFunction valueSelector) { + return new IxToMap(this, nullCheck(keySelector, "keySelector is null"), nullCheck(valueSelector, "valueSelector is null")); + } + + /** + * Collects the elements of this sequence into a multi-Map where the key is + * determined from each element via the keySelector function. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + */ + public final Ix>> collectToMultimap(IxFunction keySelector) { + IxFunction f = IdentityHelper.instance(); + return this.collectToMultimap(keySelector, f); + } + + /** + * Collects the elements of this sequence into a multi-Map where the key is + * determined from each element via the keySelector function and + * the value is derived from the same element via the valueSelector function. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param the value type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @param valueSelector the function that receives the current element and returns + * a value for it to be used as the Map value + * @return the new Ix instance + * @throws NullPointerException if keySelector or valueSelector is null + * @since 1.0 + */ + public final Ix>> collectToMultimap(IxFunction keySelector, IxFunction valueSelector) { + return new IxToMultimap(this, keySelector, valueSelector); + } + + /** + * Collects the elements of this sequence into a Set. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix> collectToSet() { + return new IxToSet(this); + } + + /** + * When the iterator() of the returned Ix is called, it calls the transformer function + * with this Ix instance and emits the elements of the returned Iterable. + *

+ * The result's iterator() forwards the call remove() to the returned Iterable's Iterator. + * + * @param the result value type + * @param transformer the transformer called with this Ix when Ix.iterator() is invoked + * @return the new Ix instance + * @throws NullPointerException if transformer is null + * @since 1.0 + */ + public final Ix compose(IxFunction, ? extends Iterable> transformer) { + return new IxCompose(this, nullCheck(transformer, "transformer is null")); + } + + /** + * Maps each element from this sequence into subsequent Iterable sequences whose elements are + * concatenated in order. + *

+ * Note that flatMap and concatMap operations are the same in the Iterable world. + *

+ * The result's iterator() forwards the call remove() to the current inner Iterator. + * + * @param the result value type + * @param mapper the function + * @return the new Ix instance + * @throws NullPointerException if mapper is null + * @since 1.0 + * @see #flatMap(IxFunction) + */ + public final Ix concatMap(IxFunction> mapper) { + return new IxFlattenIterable(this, nullCheck(mapper, "mapper is null")); + } + + /** + * Emits elements of this sequence followed by the elements of the other sequence. + *

+ * Note that mergeWith and concatWith operations are the same in the Iterable world. + *

+ * The result's iterator() forwards the call remove() to the current Iterator. + * @param other the other sequence to emits elements of + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + * @see #mergeWith(Iterable) + */ + public final Ix concatWith(Iterable other) { + return concat(this, other); + } + + /** + * Emits true if the sequence contains the given Object, compared via null-safe + * equals. + *

+ * The result's iterator() doesn't support remove(). + * @param o the value to find + * @return the new Ix instance + * @since 1.0 + */ + public final Ix contains(Object o) { + return new IxContains(this, o); + } + + /** + * Emits the number of elements in this sequence. + *

+ * The result's iterator() doesn't support remove(). + * @return the number of elements in this sequence + * @since 1.0 + */ + public final Ix count() { + return new IxCount(this); + } + + /** + * Emits the number of elements, as a long, in this sequence. + *

+ * The result's iterator() doesn't support remove(). + * @return the number of elements in this sequence + * @since 1.0 + */ + public final Ix countLong() { + return new IxCountLong(this); + } + + /** + * Emits the given value if this sequence is empty, streams this sequence otherwise. + *

+ * The result's iterator() doesn't support remove(). + * @param value the value to emit if this sequence is empty + * @return the new Ix instance + * @since 1.0 + */ + public final Ix defaultIfEmpty(T value) { + return switchIfEmpty(Ix.just(value)); + } + + /** + * Emits only distinct, never before seen elements (according to null-safe equals()) + * of this sequence. + *

+ * Note that this operator uses a memory of seen elements which may grow unbounded + * with long sequences. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix distinct() { + return distinct(IdentityHelper.instance()); + } + + /** + * Emits only distinct, never before seen keys extracted from elements + * (according to null-safe equals()) of this sequence. + *

+ * Note that this operator uses a memory of seen elements which may grow unbounded + * with long sequences. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function taking the current element and returning a key object + * that will be compared with null-safe equals(). + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + */ + public final Ix distinct(IxFunction keySelector) { + return new IxDistinct(this, nullCheck(keySelector, "keySelector is null")); + } + + /** + * Emits elements from this sequence if each element is different from the previous element + * (according to a null-safe equals()), dropping elements that evaluate to the same as the previous. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix distinctUntilChanged() { + return distinctUntilChanged(IdentityHelper.instance()); + } + + /** + * Emits elements from this sequence if each element is different from the previous element + * (according to a comparer), dropping elements that evaluate to the same as the previous. + *

+ * The result's iterator() doesn't support remove(). + * @param comparer the predicate receiving the previous element and the current element and + * returns true if they are the same (thus ignoring the latter). + * @return the new Ix instance + * @throws NullPointerException if comparer is null + * @since 1.0 + */ + public final Ix distinctUntilChanged(IxPredicate2 comparer) { + return new IxDistinctUntilChanged(this, IdentityHelper.instance(), nullCheck(comparer, "comparer is null")); + } + + /** + * Emits elements from this sequence if each element is different from the previous element + * (according to a null-safe equals() of the extracted key), dropping elements that evaluate + * to the same as the previous. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function that receives the current element and returns a key that will be compared + * via null-safe equals with the previous element's key + * @return the new Ix instance + * @throws NullPointerException if comparer is null + * @since 1.0 + */ + public final Ix distinctUntilChanged(IxFunction keySelector) { + return new IxDistinctUntilChanged(this, keySelector, EqualityHelper.INSTANCE); + } + + /** + * Calls the given action just before when the consumer calls next() of this Ix.iterator(). + *

+ * The result's iterator() forwards calls to remove() to this Iterator. + * @param action the action to call for each item + * @return the new Ix instance + * @throws NullPointerException if action is null + * @since 1.0 + */ + public final Ix doOnNext(IxConsumer action) { + return new IxDoOn(this, nullCheck(action, "action is null"), IxEmptyAction.instance0()); + } + + /** + * Calls the given action after consumption of this sequence has completed, i.e., when + * hasNext() of this Ix.iterator() returns false. + *

+ * The result's iterator() forwards calls to remove() to this' Iterator. + * @param action the action to call after the source sequence completes + * @return the new Ix instance + * @throws NullPointerException if action is null + * @since 1.0 + */ + public final Ix doOnCompleted(Runnable action) { + return new IxDoOn(this, IxEmptyAction.instance1(), nullCheck(action, "action is null")); + } + + /** + * Emits the elements of this sequence followed by the elements of the given array of values. + *

+ * The result's iterator() doesn't support remove(). + * @param values the elements to emit after this sequence + * @return the new Ix instance + * @throws NullPointerException if values is null + * @since 1.0 + */ + public final Ix endWith(T... values) { + return concat(this, fromArray(values)); + } + + /** + * Emit every Nth item only from upstream. + *

Example: Ix.range(1, 5).every(2) will yield {2, 4}. + * @param nth how many items to skip + 1 + * @return the new Ix instance + * @since 1.0 + */ + public final Ix every(int nth) { + return new IxEvery(this, positive(nth, "nth")); + } + + /** + * Emits distinct elements from this and the other Iterable which are not + * in the other sequence (i.e., (A union B) minus (A intersection B)). + *

+ * The result's iterator() doesn't support remove(). + * @param other the other Iterable sequence, not null + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + * @see #union(Iterable) + * @see #intersect(Iterable) + */ + public final Ix except(Iterable other) { + return new IxExcept(this, nullCheck(other, "other is null")); + } + + /** + * Emits elements of this sequence which match the given predicate only. + *

+ * The result's iterator() forwards the call to remove() to this' Iterator. + * @param predicate the predicate receiving the current element and if it + * returns true, the value is emitted, ignored otherwise. + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + */ + public final Ix filter(IxPredicate predicate) { + return new IxFilter(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Maps each element from this sequence into subsequent Iterable sequences whose elements are + * concatenated in order. + *

+ * Note that flatMap and concatMap operations are the same in the Iterable world. + *

+ * The result's iterator() forwards the call remove() to the current inner Iterator. + * + * @param the result value type + * @param mapper the function + * @return the new Ix instance + * @throws NullPointerException if mapper is null + * @since 1.0 + * @see #concatMap(IxFunction) + */ + public final Ix flatMap(IxFunction> mapper) { + return new IxFlattenIterable(this, mapper); + } + + /** + * Groups elements of this sequence into distinct groups keyed by the keys returned by the keySelector. + *

+ * The operator doesn't lose data and calling hasNext/next on either the returned Ix or on the inner + * GroupedIx can move the source sequence forward. + *

+ * The result's iterator() and the inner groups' Iterators don't support remove(). + * @param the key type + * @param keySelector the function receiving the current element and returns the key to be used for + * grouping the values into the same inner GroupedIx. + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + * @see #groupBy(IxFunction, IxFunction) + */ + public final Ix> groupBy(IxFunction keySelector) { + return groupBy(keySelector, IdentityHelper.instance()); + } + + /** + * Groups mapped elements (by the valueSelector) of this sequence into distinct groups + * keyed by the keys returned by the keySelector. + *

+ * The operator doesn't lose data and calling hasNext/next on either the returned Ix or on the inner + * GroupedIx can move the source sequence forward. + *

+ * The result's iterator() and the inner groups' Iterators don't support remove(). + * @param the key type + * @param the value type + * @param keySelector the function receiving the current element and returns the key to be used for + * grouping the values into the same inner GroupedIx. + * @param valueSelector the function receiving the current element and returns the value to be emitted + * by the appropriate group + * @return the new Ix instance + * @throws NullPointerException if keySelector or valueSelector is null + * @since 1.0 + * @see #groupBy(IxFunction, IxFunction) + */ + public final Ix> groupBy(IxFunction keySelector, + IxFunction valueSelector) { + return new IxGroupBy(this, nullCheck(keySelector, "keySelector is null"), nullCheck(valueSelector, "valueSelector is null")); + } + + /** + * Emits true if this sequence has elements, emits false otherwise. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix hasElements() { + return new IxHasElements(this); + } + + /** + * Hides the identity of this Ix instance and prevents certain identity-based optimizations. + *

+ * The result's iterator() forwards the remove() calls to this' Iterator. + * @return the new Ix instance + * @since 1.0 + */ + public final Ix hide() { + return new IxWrapper(this); + } + + /** + * Emits distinct values of this and the other Iterables that are present in + * both sequences. + *

+ * The result's iterator() doesn't support remove(). + * @param other the other Iterable sequence + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + * @see #except(Iterable) + * @see #union(Iterable) + */ + public final Ix intersect(Iterable other) { + return new IxIntersect(this, nullCheck(other, "other is null")); + } + + /** + * Runs through this sequence, ignoring all values until this sequence completes. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix ignoreElements() { + return new IxIgnoreElements(this); + } + + /** + * Converts elements of this sequence to String and concatenates them into + * a single, comma separated String. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix join() { + return join(", "); + } + + /** + * Converts elements of this sequence to String and concatenates them into + * a single String separated by the given character sequence. + *

+ * The result's iterator() doesn't support remove(). + * @param separator the character sequence separating elements + * @return the new Ix instance + * @since 1.0 + */ + public final Ix join(CharSequence separator) { + return new IxJoin(this, separator); + } + + /** + * Calls the given lifter function with the iterator of this sequence and emits + * elements of the returned Iterator. + *

+ * The result's iterator() forwards the remove() calls to the returned Iterator. + * @param the result value type + * @param lifter the function that receives the Iterator of this and returns an Iterator + * that will be consumed further on + * @return the new Ix instance + * @throws NullPointerException if lifter is null + * @since 1.0 + */ + public final Ix lift(IxFunction, ? extends Iterator> lifter) { + return new IxLift(this, nullCheck(lifter, "lifter is null")); + } + + /** + * Maps each element of this sequence to some other value. + *

+ * The result's iterator() forwards the remove() calls to this' Iterator. + * @param the result value type + * @param mapper the function that receives an element from this sequence + * and returns another value for it to be emitted. + * @return the new Ix instance + * @throws NullPointerException if mapper is null + * @since 1.0 + */ + public final Ix map(IxFunction mapper) { + return new IxMap(this, mapper); + } + + /** + * Emits the first maximum element according to the given comparator. + *

+ * The result's iterator() doesn't support remove(). + * @param comparator the comparator called with the latest maximum element and + * the current element; if it returns a positive value, the current element + * becomes the maximum element. + * @return the new Ix instance + * @throws NullPointerException if comparator is null + * @since 1.0 + * @see #min(Comparator) + */ + public final Ix max(Comparator comparator) { + return new IxMinMax(this, comparator, -1); + } + + /** + * Emits the first maximum element according to their natural order. + *

+ * The sequence may throw a ClassCastException if any of the elements is + * not self-comparable (i.e., doesn't implement the Comparable interface). + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + * @see #min() + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public final Ix max() { + return max((Comparator)SelfComparator.INSTANCE); + } + + /** + * Returns the first maximum integer value. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * an Integer object. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix maxInt() { + return new IxMaxInt((Ix)this); + } + + /** + * Returns the first maximum long value. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * a Long object. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix maxLong() { + return new IxMaxLong((Ix)this); + } + + /** + * Emits elements of this sequence followed by the elements of the other sequence. + *

+ * Note that mergeWith and concatWith operations are the same in the Iterable world. + *

+ * The result's iterator() forwards the call remove() to the current Iterator. + * @param other the other sequence to emits elements of + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + * @see #concatWith(Iterable) + */ + public final Ix mergeWith(Iterable other) { + return concatWith(other); + } + + /** + * Emits the first minimum element according to the given comparator. + *

+ * The result's iterator() doesn't support remove(). + * @param comparator the comparator called with the latest minimum element and + * the current element; if it returns a negative value, the current element + * becomes the minimum element. + * @return the new Ix instance + * @throws NullPointerException if comparator is null + * @since 1.0 + * @see #max(Comparator) + */ + public final Ix min(Comparator comparator) { + return new IxMinMax(this, comparator, 1); + } + + /** + * Emits the first minimum element according to their natural order. + *

+ * The sequence may throw a ClassCastException if any of the element is + * not self-comparable (i.e., doesn't implement the Comparable interface). + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + * @see #min() + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public final Ix min() { + return min((Comparator)SelfComparator.INSTANCE); + } + + /** + * Returns the first minimum integer value. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * an Integer object. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix minInt() { + return new IxMinInt((Ix)this); + } + + /** + * Returns the first minimum long value. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * a Long object. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix minLong() { + return new IxMinLong((Ix)this); + } + + /** + * Orders elements according to their natural order. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * a self-comparable object (i.e., doesn't implement the Comparable interface). + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + * @see #orderByReverse() + * @see #orderBy(Comparator) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Ix orderBy() { + return orderBy((Comparator)SelfComparator.INSTANCE); + } + + /** + * Orders elements according to the comparator. + *

+ * The result's iterator() doesn't support remove(). + * @param comparator the comparator comparing two elements; if it returns a negative value, + * the first element will be before the second; if it returns a positive value, + * the first element will be after the second. + * @return the new Ix instance + * @throws NullPointerException if comparator is null + * @since 1.0 + * @see #orderBy() + * @see #orderByReverse(Comparator) + */ + public final Ix orderBy(Comparator comparator) { + return new IxOrderBy(this, IdentityHelper.instance(), nullCheck(comparator, "comparator is null"), 1); + } + + /** + * Orders elements according to the natural order of the extracted keys from these elements. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function receiving each element and returns a self-comparable key for them. + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + * @see #orderByReverse(IxFunction) + */ + public final > Ix orderBy(IxFunction keySelector) { + return new IxOrderBy(this, nullCheck(keySelector, "keySelector is null"), SelfComparator.INSTANCE, 1); + } + + /** + * Orders elements according to their reverse natural order. + *

+ * The sequence may throw a ClassCastException if any of the elements is not + * a self-comparable object (i.e., doesn't implement the Comparable interface). + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + * @see #orderBy() + * @see #orderByReverse(Comparator) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public final Ix orderByReverse() { + return orderByReverse((Comparator)SelfComparator.INSTANCE); + } + + /** + * Orders elements according to the reversed comparator. + *

+ * The result's iterator() doesn't support remove(). + * @param comparator the comparator comparing two elements; if it returns a negative value, + * the first element will be after the second; if it returns a positive value, + * the first element will be before the second. + * @return the new Ix instance + * @throws NullPointerException if comparator is null + * @since 1.0 + * @see #orderByReverse() + * @see #orderBy(Comparator) + */ + public final Ix orderByReverse(Comparator comparator) { + return new IxOrderBy(this, IdentityHelper.instance(), nullCheck(comparator, "comparator is null"), -1); + } + + /** + * Orders elements according to the reverse natural order of the extracted keys from these elements. + *

+ * The result's iterator() doesn't support remove(). + * @param the key type + * @param keySelector the function receiving each element and returns a self-comparable key for them. + * @return the new Ix instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + * @see #orderByReverse(IxFunction) + */ + public final > Ix orderByReverse(IxFunction keySelector) { + return new IxOrderBy(this, nullCheck(keySelector, "keySelector is null"), SelfComparator.INSTANCE, -1); + } + + /** + * Shares an underlying Iterator that is consumed only once and each created iterator() that calls + * next() will receive the elements; other iterator() instances may receive different or no elements + * at all. + *

+ * The result's iterator() doesn't support remove(). + * @return the new iterator sequence + * @since 1.0 + */ + public final Ix publish() { + return new IxPublish(this); + } + + /** + * Shares an Iterator, exposed as an Ix sequence, for the duration of the transform function called + * for each iterator() invocation and emits elements of the resulting iterable sequence of the function. + *

+ * The result's iterator() doesn't support remove(). + * @param the result value type + * @param transform the function that receives an Ix instance sharing a single underlying Iterator to this + * sequence and returns another Iterable to be the result sequence + * @return the new Iterable sequence + * @throws NullPointerException if transform is null + * @since 1.0 + */ + public final Ix publish(IxFunction, ? extends Iterable> transform) { + return new IxPublishSelector(this, nullCheck(transform, "transform is null")); + } + + /** + * Reduces the elements of this sequence into a single value via a reducer function. + *

+ * The result's iterator() doesn't support remove(). + * @param reducer the function that receives the previous reduced element (or the first) and the current element + * and returns a new reduced element + * @return the new Ix instance + * @throws NullPointerException if reducer is null + * @since 1.0 + * @see #reduce(IxSupplier, IxFunction2) + */ + public final Ix reduce(IxFunction2 reducer) { + return new IxAggregate(this, nullCheck(reducer, "reducer is null")); + } + + /** + * Given a per-iterator() initial value, reduces the elements of this sequence into a single + * value via a reducer function. + *

+ * The result's iterator() doesn't support remove(). + * @param the reduced value type + * @param initialFactory a function called for each iterator() invocation and returns the first + * reduced value + * @param reducer the function called with the previous (or initial) reduced value and the current element + * and returns a new reduced value + * @return the new Ix instance + * @throws NullPointerException if initialFactory or reducer is null + * @since 1.0 + * @see #reduce(IxFunction2) + */ + public final Ix reduce(IxSupplier initialFactory, IxFunction2 reducer) { + return new IxReduce(this, initialFactory, reducer); + } + + /** + * Removes those elements via Iterator.remove() from this sequence that match the + * given predicate. + *

+ * The result's iterator() forwards the calls to remove() to this' Iterator. + * @param predicate the function called with the current element and returns true + * if that particular element should be removed. + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + * @see #retain(IxPredicate) + */ + public final Ix remove(IxPredicate predicate) { + return new IxRemove(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Repeats this sequence indefinitely. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix repeat() { + return concat(repeatValue(this)); + } + + /** + * Repeats this sequence at most the given number of times. + *

A count of zero will yield an empty sequence, a count of one + * will yield a sequence with only one element and so forth. + *

+ * The result's iterator() doesn't support remove(). + * @param times the number of times to emit the value, non-negative + * @return the new Ix instance + * @throws IllegalArgumentException if count is negative + * @since 1.0 + */ + public final Ix repeat(long times) { + return concat(repeatValue(this, times)); + } + + /** + * Repeats this sequence if the given predicate returns true after the sequence + * completes in a round. + *

+ * The result's iterator() doesn't support remove(). + * @param stopPredicate the predicate called before any emission; returning + * false keeps repeating the value, returning true terminates the sequence + * @return the new Ix instance + * @throws NullPointerException if stopPredicate is null + * @since 1.0 + */ + public final Ix repeat(IxBooleanSupplier stopPredicate) { + return concat(repeatValue(this, stopPredicate)); + } + + /** + * Repeats this sequence if the given predicate returns true after the sequence + * completes in a round or at most the given number of times. + *

+ * A count of zero will yield an empty sequence, a count of one + * will yield a sequence with only one element and so forth. + *

+ * The result's iterator() doesn't support remove(). + * @param times the number of times to emit the value, non-negative + * @param stopPredicate the predicate called before any emission; returning + * false keeps repeating the value, returning true terminates the sequence + * @return the new Ix instance + * @throws IllegalArgumentException if count is negative + * @throws NullPointerException if stopPredicate is null + * @since 1.0 + */ + public final Ix repeat(long times, IxBooleanSupplier stopPredicate) { + return concat(repeatValue(this, times, stopPredicate)); + } + + /** + * Caches and replays all elements of this sequence to consumers of this' iterator(). + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix replay() { + return new IxReplay(this); + } + + /** + * Caches and replays the last {@code size} elements of this sequence to consumers of this' iterator(). + *

+ * Consumption by any of the iterator() may move the source sequence forward and subsequent iterator() + * consumers may get a different set of values + *

+ * The result's iterator() doesn't support remove(). + * @param size the maximum number of elements to keep replaying to new iterator() consumers, positive + * @return the new Ix instance + * @throws IllegalArgumentException if size is non-positive + * @since 1.0 + */ + public final Ix replay(int size) { + return new IxReplaySize(this, positive(size, "size")); + } + + /** + * Caches and replays the elements of this sequence for the duration of the given transform function + * without consuming this sequence multiple times. + *

+ * The result's iterator() doesn't support remove(). + * @param the result value type + * @param transform the function receiving a view into the cache and returns an Iterable sequence whose + * elements will be emitted by this Ix. + * @return the new Ix instance + * @throws NullPointerException if transform is null + * @since 1.0 + */ + public final Ix replay(IxFunction, ? extends Iterable> transform) { + return new IxReplaySelector(this, nullCheck(transform, "transform is null")); + } + + /** + * Caches and replays the the last {@code size} elements of this sequence for the duration of the given transform function + * without consuming this sequence multiple times. + *

+ * Consumption by any of the inner Ix' iterator() may move the shared sequence forward and subsequent iterator() + * consumers may get a different set of values + *

+ * The result's iterator() doesn't support remove(). + * @param the result value type + * @param size the maximum number of elements to keep replaying to new inner Ix iterator() consumers, positive + * @param transform the function receiving a view into the cache and returns an Iterable sequence whose + * elements will be emitted by this Ix. + * @return the new Ix instance + * @throws NullPointerException if transform is null + * @throws IllegalArgumentException if size is non-positive + * @since 1.0 + */ + public final Ix replay(int size, IxFunction, ? extends Iterable> transform) { + return new IxReplaySizeSelector(this, positive(size, "size"), nullCheck(transform, "transform is null")); + } + + /** + * Removes those elements via Iterator.remove() from this sequence that don't match the + * given predicate. + *

+ * The result's iterator() forwards the calls to remove() to this' Iterator. + * @param predicate the function called with the current element and returns false + * if that particular element should be removed. + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + * @see #remove(IxPredicate) + */ + public final Ix retain(IxPredicate predicate) { + return new IxRetain(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Plays this sequence in reverse. + *

+ * The reversal requires consuming the entire sequence and doesn't work with + * infinite sequences. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + public final Ix reverse() { + return new IxReverse(this); + } + + /** + * Performs a running accumulation, that is, returns intermediate elements returned by the + * scanner function. + *

+ * The result's iterator() doesn't support remove(). + * @param scanner the function that receives the previous (or first) accumulated element and the current + * element and returns a value to be emitted and to become the accumulated element + * @return the new Ix instance + * @throws NullPointerException if scanner is null + * @since 1.0 + */ + public final Ix scan(IxFunction2 scanner) { + return new IxScan(this, nullCheck(scanner, "scanner is null")); + } + + /** + * Performs a running accumulation, that is, returns intermediate elements returned by the + * scanner function, starting with a per-iterator initial value. + *

+ * The result's iterator() doesn't support remove(). + * @param the accumulated value type + * @param initialFactory function called for each iterator() and returns the initial accumulator value + * @param scanner the function that receives the previous (or first) accumulated element and the current + * element and returns a value to be emitted and to become the accumulated element + * @return the new Ix instance + * @throws NullPointerException if initialFactory or scanner is null + * @since 1.0 + */ + public final Ix scan(IxSupplier initialFactory, IxFunction2 scanner) { + return new IxScanSeed(this, nullCheck(initialFactory, "initialFactory is null"), nullCheck(scanner, "scanner is null")); + } + + /** + * Determines if two sequences have the same elements in the same order and are the same length based + * on null-safe object equality. + *

+ * The result's iterator() doesn't support remove(). + * @param other the other sequence to compare with + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + */ + public final Ix sequenceEqual(Iterable other) { + return sequenceEqual(nullCheck(other, "other is null"), EqualityHelper.INSTANCE); + } + + /** + * Determines if two sequences have the same elements in the same order and are the same length based + * on the given comparer's boolean value. + *

+ * The result's iterator() doesn't support remove(). + * @param other the other sequence to compare with + * @param comparer the predicate receiving elements from this and the other sequence and returns true if those + * elements are equal + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + */ + public final Ix sequenceEqual(Iterable other, IxPredicate2 comparer) { + return new IxSequenceEqual(this, nullCheck(other, "other is null"), nullCheck(comparer, "comparer is null")); + } + + /** + * Skips the first n elements from this sequence. + *

+ * The result's iterator() forwards the calls to remove() to this' Iterator. + * @param n the elements to skip, non-positive values won't skip any elements + * @return the new Ix instance + * @since 1.0 + * @see #take(int) + */ + public final Ix skip(int n) { + if (n <= 0) { + return this; + } + return new IxSkip(this, n); + } + + /** + * Skips the last n elements from this sequence. + *

+ * The result's iterator() doesn't support remove(). + * @param n the elements to skip, non-positive values won't skip any elements + * @return the new Ix instance + * @since 1.0 + * @see #takeLast(int) + */ + public final Ix skipLast(int n) { + if (n <= 0) { + return this; + } + return new IxSkipLast(this, n); + } + + /** + * Skips the first elements while the given predicate returns true; once it returns false + * all subsequent elements are emitted. + *

+ * The result's iterator() forwards the calls to remove() to this' Iterator. + * @param predicate the predicate called with the current element and returns true + * to skip that element + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + * @see #takeWhile(IxPredicate) + */ + public final Ix skipWhile(IxPredicate predicate) { + return new IxSkipWhile(this, nullCheck(predicate, "predicate is null")); + } + + /** + * Emits elements of the given array followed by the elements of this sequence. + *

+ * The result's iterator() doesn't support remove(). + * @param values the array of values to emit first + * @return the new Ix instance + * @throws NullPointerException if values is null + * @since 1.0 + */ + public final Ix startWith(T... values) { + return concat(fromArray(values), this); + } + + /** + * Sums values of this sequence as integer. + *

+ * The operation may throw a ClassCastException if any of the elements + * is not an Integer. + *

+ * An empty sequence yields an empty sum. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix sumInt() { + return new IxSumInt((Ix)this); + } + + /** + * Sums values of this sequence as long. + *

+ * The operation may throw a ClassCastException if any of the elements + * is not an Long. + *

+ * An empty sequence yields an empty sum. + *

+ * The result's iterator() doesn't support remove(). + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix sumLong() { + return new IxSumLong((Ix)this); + } + + /** + * Emits the elements of the other sequence if this sequence is empty. + *

+ * The result's Iterator forwards calls of remove() to this' or the other's Iterator. + * @param other the other Iterable instance, not null + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + */ + public final Ix switchIfEmpty(Iterable other) { + return new IxSwitchIfEmpty(this, nullCheck(other, "other is null")); + } + + /** + * Emits the first n elements (or less) of this sequence. + *

+ * The result's Iterator forwards calls of remove() to this' Iterator. + * @param n the number of items to emit at most, non-negative + * @return the new Ix instance + * @throws IllegalArgumentException if n is negative + * @since 1.0 + * @see #skip(int) + */ + public final Ix take(int n) { + return new IxTake(this, nonNegative(n, "n")); + } + + /** + * Emits the last n elements (or fewer) of this sequence. + *

+ * The result's iterator() doesn't support remove(). + * @param n the number of last elements to emit + * @return the new Ix instance + * @throws IllegalArgumentException if n is negative + * @since 1.0 + * @see #skipLast(int) + */ + public final Ix takeLast(int n) { + return new IxTakeLast(this, nonNegative(n, "n")); + } + + /** + * Take elements from this sequence until the given predicate returns true + * for the current element (checked after emission of that element). + *

+ * The result's Iterator forwards calls of remove() to this' Iterator. + * @param stopPredicate the function receiving the current element and returns + * true if no further elements should be emitted after this element. + * @return the new Ix instance + * @throws NullPointerException if stopPredicate is null + * @since 1.0 + */ + public final Ix takeUntil(IxPredicate stopPredicate) { + return new IxTakeUntil(this, nullCheck(stopPredicate, "stopPredicate is null")); + } + + /** + * Take elements from this sequence while the given predicate returns true + * for the current element (checked before emission of that element). + *

+ * The result's Iterator forwards calls of remove() to this' Iterator. + * @param predicate the function receiving the current element and returns + * false if no further elements should be emitted (not even the current). + * @return the new Ix instance + * @throws NullPointerException if predicate is null + * @since 1.0 + */ + public final Ix takeWhile(IxPredicate predicate) { + return new IxTakeWhile(this, nullCheck(predicate, "predicate is null")); + } + + + /** + * Maps this sequence of numbers into a sequence of longs. + *

+ * The sequence may throw a ClassCastException if any of the elements + * is not a subclass of Number. + *

+ * The result's Iterator forwards calls of remove() to this' Iterator. + * @return the new Ix instance + * @since 1.0 + */ + @SuppressWarnings("unchecked") + public final Ix toLong() { + return ((Ix)this).map(NumberToLongHelper.INSTANCE); + } + + /** + * Allows working with the Iterator of this sequence and emit elements in + * a more flexible way + *

+ * The result's iterator() doesn't support remove(). + * @param the result value type + * @param transformer the functional interface whose moveNext is called with the + * current Iterator and should signal a value to be emitted for it. + * @return the new Ix instance + * @throws NullPointerException if transformer is null + */ + public final Ix transform(IxTransform transformer) { + return new IxTransformer(this, nullCheck(transformer, "transformer is null")); + } + + /** + * Emits a distinct set of values from both this and the other sequence. + *

+ * The result's iterator() doesn't support remove(). + * @param other the other Iterable sequence, not null + * @return the new Ix instance + * @throws NullPointerException if other is null + * @since 1.0 + * @see #except(Iterable) + * @see #intersect(Iterable) + */ + public final Ix union(Iterable other) { + return new IxUnion(this, nullCheck(other, "other is null")); + } + + /** + * Emits inner Ix Iterables of non-overlapping sequences mapped from this sequence + * with the given maximum size each. + * + *

+ * The result's and the inner Ix' iterator() don't support remove(). + * @param size the maximum size of the inner windows, positive + * @return the new Ix instance + * @throws IllegalArgumentException if size is non-positive + * @since 1.0 + * @see #window(int, int) + */ + public final Ix> window(int size) { + return new IxWindow(this, positive(size, "size")); + } + + /** + * Emits inner Ix Iterables of potentially overlapping sequences mapped from this + * sequence with the given maximum size each and started each {@code skip} source elements. + * @param size the maximum size of the inner windows, positive + * @param skip after how many elements to start a new window (repeatedly), positive + * @return the new Ix instance + * @throws IllegalArgumentException if size or skip is non-positive + * @since 1.0 + * @see #window(int) + */ + public final Ix> window(int size, int skip) { + if (size == skip) { + return window(size); + } + if (size < skip) { + return new IxWindowSkip(this, positive(size, "size"), positive(skip, "skip")); + } + return new IxWindowOverlap(this, positive(size, "size"), positive(skip, "skip")); + } + + /** + * Combines the next element from this and the other source Iterable via a zipper function. + *

+ * If one of the source Iterables is sorter the sequence terminates eagerly. + *

+ * The result's iterator() doesn't support remove(). + * + * @param the other source's element type + * @param the result value type + * @param other the the other source Iterable + * @param zipper the function that takes one from each source, not null + * @return the new Ix instance + * @throws NullPointerException if other or zipper is null + * @since 1.0 + */ + public final Ix zipWith(Iterable other, IxFunction2 zipper) { + return zip(this, other, zipper); + } + + //--------------------------------------------------------------------------------------- + // Leaving the Iterable world + //--------------------------------------------------------------------------------------- + + /** + * Returns the first element of this sequence. + * @return the first element + * @throws NoSuchElementException if this sequence is empty + * @since 1.0 + * @see #first(Object) + * @see #last(Object) + */ + @SuppressWarnings("unchecked") + public final T first() { + if (this instanceof Callable) { + return checkedCall((Callable) this); + } + return iterator().next(); + } + + /** + * Returns the first element of this sequence or the defaultValue + * if this sequence is empty. + * @param defaultValue the value to return if this sequence is empty + * @return the first element or the default value + * @since 1.0 + * @see #first() + * @see #last() + */ + @SuppressWarnings("unchecked") + public final T first(T defaultValue) { + if (this instanceof Callable) { + return checkedCall((Callable) this); + } + Iterator it = iterator(); + if (it.hasNext()) { + return it.next(); + } + return defaultValue; + } + + /** + * Consumes the entire sequence and calls the given action with each value. + * @param action the action to call + * @throws NullPointerException if action is null + * @since 1.0 + * @see #foreachWhile(IxPredicate) + */ + public final void foreach(IxConsumer action) { + for (T t : this) { + action.accept(t); + } + } + + /** + * Consumes the entire sequence and calls the given predicate with each value; + * which can stop the iteration by returning false. + * @param predicate the predicate to call with the current element and should + * return true to continue the loop or false to quit the loop. + * @throws NullPointerException if action is null + * @since 1.0 + * @see #foreach(IxConsumer) + */ + public final void foreachWhile(IxPredicate predicate) { + for (T t : this) { + if (!predicate.test(t)) { + break; + } + } + } + + /** + * Consumes the entire sequence and adds each element into the given collection + * that is also returned. + * @param the collection of type accepting a (super)type of this element type + * @param collection the collection to collect into + * @return the collection itself + * @throws NullPointerException if collection is null + * @since 1.0 + */ + public final > U into(U collection) { + for (T v : this) { + collection.add(v); + } + return collection; + } + + /** + * Returns the last element of this sequence. + * @return the last element of this sequence + * @throws NoSuchElementException if the sequence is empty + * @since 1.0 + * @see #last(Object) + */ + @SuppressWarnings("unchecked") + public final T last() { + if (this instanceof Callable) { + return checkedCall((Callable) this); + } + Iterator it = iterator(); + if (!it.hasNext()) { + throw new NoSuchElementException(); + } + + for (;;) { + T t = it.next(); + if (!it.hasNext()) { + return t; + } + } + } + + /** + * Returns the last element of this sequence or the defaultValue if + * this sequence is empty. + * @param defaultValue the value to return if this sequence is empty + * @return the last element or the default value + * @since 1.0 + * @see #last() + * @see #first() + */ + @SuppressWarnings("unchecked") + public final T last(T defaultValue) { + if (this instanceof Callable) { + return checkedCall((Callable) this); + } + Iterator it = iterator(); + if (!it.hasNext()) { + return defaultValue; + } + + for (;;) { + T t = it.next(); + if (!it.hasNext()) { + return t; + } + } + } + + /** + * Prints the elements of this sequence to the console, separated + * by a comma+space and with a line break after roughly 80 characters. + * @since 1.0 + */ + public final void print() { + print(", ", 80); + } + + /** + * Prints the elements of this sequence to the console, separated + * by the given separator and with a line break after roughly the + * given charsPerLine amount. + * @param separator the characters to separate the elements + * @param charsPerLine indicates how long a line should be + */ + public final void print(CharSequence separator, int charsPerLine) { + boolean first = true; + int len = 0; + + for (T v : this) { + + String s = String.valueOf(v); + + if (first) { + System.out.print(s); + len += s.length(); + first = false; + } else { + System.out.print(separator); + len += separator.length(); + if (len > charsPerLine) { + System.out.println(); + System.out.print(s); + len = s.length(); + } else { + System.out.print(s); + len += s.length(); + } + } + + } + } + + /** + * Prints each element of this sequence into a new line on the console. + * @since 1.0 + */ + public final void println() { + for (T v : this) { + System.out.println(v); + } + } + + /** + * Prints each element of this sequence into a new line on the console, prefixed + * by the given character sequence. + * @param prefix the prefix before each line + */ + public final void println(CharSequence prefix) { + for (T v : this) { + System.out.print(prefix); + System.out.println(v); + } + } + /** + * Removes all elements by repeatedly calling this sequence's Iterator.remove(). + */ + public final void removeAll() { + Iterator it = iterator(); + while (it.hasNext()) { + it.next(); + it.remove(); + } + } + + /** + * Consumes this Iterable and removes all elements for + * which the predicate returns true; in other words, + * remove those elements of a mutable source that match + * the predicate. + * @param predicate the predicate called with the current + * element and should return true for elements to remove, false + * for elements to keep. + * @throws UnsupportedOperationException if the this Iterable + * doesn't allow removing elements. + * @see #retainAll(IxPredicate) + * @see #removeAll() + * @since 1.0 + */ + public final void removeAll(IxPredicate predicate) { + Iterator it = iterator(); + while (it.hasNext()) { + T v = it.next(); + if (predicate.test(v)) { + it.remove(); + } + } + } + /** + * Consumes this Iterable and removes all elements for + * which the predicate returns false; in other words, + * retain those elements of a mutable source that match + * the predicate. + * @param predicate the predicate called with the current + * element and should return true for elements to keep, false + * for elements to remove. + * @throws UnsupportedOperationException if the this Iterable + * doesn't allow removing elements. + * @see #removeAll(IxPredicate) + * @since 1.0 + */ + public final void retainAll(IxPredicate predicate) { + Iterator it = iterator(); + while (it.hasNext()) { + T v = it.next(); + if (!predicate.test(v)) { + it.remove(); + } + } + } + + /** + * Iterates over this instance, dropping all values it produces. + * @see #subscribe() + */ + public final void run() { + Iterator it = iterator(); + while (it.hasNext()) { + it.next(); + } + } + + /** + * Returns the single element of this sequence or throws a NoSuchElementException + * if this sequence is empty or IndexOutOfBoundsException if this sequence has more + * than on element + * @return the single element of the sequence + * @throws IndexOutOfBoundsException if the sequence has more than one element + * @throws NoSuchElementException if the sequence is empty + * @since 1.0 + * @see #single(Object) + */ + public final T single() { + Iterator it = iterator(); + if (it.hasNext()) { + T v = it.next(); + if (it.hasNext()) { + throw new IndexOutOfBoundsException("The source has more than one element."); + } + return v; + } + throw new NoSuchElementException("The source is empty."); + } + + + /** + * Returns the single element of this sequence, defaultValue + * if this sequence is empty or IndexOutOfBoundsException if this sequence has more + * than one element + * @param defaultValue the value to return if this sequence is empty + * @return the single element of the sequence + * @throws IndexOutOfBoundsException if the sequence has more than one element + * @since 1.0 + * @see #single(Object) + */ + public final T single(T defaultValue) { + Iterator it = iterator(); + if (it.hasNext()) { + T v = it.next(); + if (it.hasNext()) { + throw new IndexOutOfBoundsException("The source has more than one element."); + } + return v; + } + return defaultValue; + } + + /** + * Iterates over this instance, dropping all values it produces. + * @see #run() + */ + public final void subscribe() { + run(); + } + + /** + * Iterates over this sequence and calls the given onNext action with + * each element. + * @param onNext the consumer to call with each element + * @throws NullPointerException if consumer is null + * @since 1.0 + */ + public final void subscribe(IxConsumer onNext) { + for (T v : this) { + onNext.accept(v); + } + } + + /** + * Iterates over this sequence and calls the given onNext action with + * each element and calls the onError with any exception thrown by the iteration + * or the onNext action. + * @param onNext the consumer to call with each element + * @param onError the consumer to call with the exception thrown + * @throws NullPointerException if onError is null + * @since 1.0 + */ + public final void subscribe(IxConsumer onNext, IxConsumer onError) { + try { + for (T v : this) { + onNext.accept(v); + } + } catch (Throwable ex) { + onError.accept(ex); + } + } + + /** + * Iterates over this sequence and calls the given onNext action with + * each element and calls the onError with any exception thrown by the iteration + * or the onNext action; otherwise calls the onCompleted action when the sequence completes + * without exception. + * @param onNext the consumer to call with each element + * @param onError the consumer to call with the exception thrown + * @param onCompleted the action called after the sequence has been consumed + * @throws NullPointerException if onError or onCompleted is null + * @since 1.0 + */ + public final void subscribe(IxConsumer onNext, IxConsumer onError, Runnable onCompleted) { + try { + for (T v : this) { + onNext.accept(v); + } + } catch (Throwable ex) { + onError.accept(ex); + return; + } + onCompleted.run(); + } + + /** + * Collects the elements of this sequence into an Object array. + *

+ * @return the new Object array instance + * @since 1.0 + */ + public final Object[] toArray() { + return toList().toArray(); + } + + /** + * Collects the elements of this sequence into a generic array provided. + *

+ * @param the output array type + * @param array the target array to fill in or use as a template if not long enough + * @return the new generic array instance + * @since 1.0 + */ + public final U[] toArray(U[] array) { + return toList().toArray(array); + } + + /** + * Collects the elements of this sequence into a List. + *

+ * @return the List instance + * @since 1.0 + */ + public final List toList() { + List list = new ArrayList(); + return into(list); + } + + + /** + * Collects the elements of this sequence into a Map where the key is + * determined from each element via the keySelector function; duplicates are + * overwritten. + *

+ * @param the key type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @return the new Map instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + */ + public final Map toMap(IxFunction keySelector) { + return this.collectToMap(keySelector).first(); + } + + /** + * Collects the elements of this sequence into a Map where the key is + * determined from each element via the keySelector function and + * the value is derived from the same element via the valueSelector function; duplicates are + * overwritten. + *

+ * @param the key type + * @param the value type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @param valueSelector the function that receives the current element and returns + * a value for it to be used as the Map value + * @return the new Map instance + * @throws NullPointerException if keySelector or valueSelector is null + * @since 1.0 + */ + public final Map toMap(IxFunction keySelector, IxFunction valueSelector) { + return this.collectToMap(keySelector, valueSelector).first(); + } + + /** + * Collects the elements of this sequence into a multi-Map where the key is + * determined from each element via the keySelector function. + *

+ * @param the key type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @return the new Map instance + * @throws NullPointerException if keySelector is null + * @since 1.0 + */ + public final Map> toMultimap(IxFunction keySelector) { + return this.collectToMultimap(keySelector).first(); + } + + /** + * Collects the elements of this sequence into a multi-Map where the key is + * determined from each element via the keySelector function and + * the value is derived from the same element via the valueSelector function. + *

+ * @param the key type + * @param the value type + * @param keySelector the function that receives the current element and returns + * a key for it to be used as the Map key. + * @param valueSelector the function that receives the current element and returns + * a value for it to be used as the Map value + * @return the new Map instance + * @throws NullPointerException if keySelector or valueSelector is null + * @since 1.0 + */ + public final Map> toMultimap(IxFunction keySelector, IxFunction valueSelector) { + return this.collectToMultimap(keySelector, valueSelector).first(); + } + + /** + * Collects the elements of this sequence into a Set. + *

+ * @return the new Ix instance + * @since 1.0 + */ + public final Set toSet() { + Set list = new HashSet(); + return into(list); + } + + // -------------------------------------------------------------------------------------------- + // Helper methods + // -------------------------------------------------------------------------------------------- + + /** + * Checks if the value is null and if so, throws + * a NullPointerException with the given message. + * @param the value type + * @param value the value to check for null + * @param message the message to report in the exception + * @return the value + */ + protected static U nullCheck(U value, String message) { + if (value == null) { + throw new NullPointerException(message); + } + return value; + } + + /** + * Calls the given callable and rethrows its exception + * (as RuntimeException if necessary). + * @param the value type + * @param callable the callable to call + * @return the value returned by the callable + */ + protected static U checkedCall(Callable callable) { + try { + return callable.call(); + } catch (Throwable ex) { + if (ex instanceof RuntimeException) { + throw (RuntimeException)ex; + } + if (ex instanceof Error) { + throw (Error)ex; + } + throw new RuntimeException(ex); + } + } + + /** + * Checks if the given value is non-negative and returns it; throws + * an IllegalArgumentException otherwise. + * @param n the number to check + * @param name the name of the parameter + * @return n + */ + protected static long nonNegative(long n, String name) { + if (n < 0L) { + throw new IllegalArgumentException(name + " >= 0 required but it was " + n); + } + return n; + } + + /** + * Checks if the given value is non-negative and returns it; throws + * an IllegalArgumentException otherwise. + * @param n the number to check + * @param name the name of the parameter + * @return n + */ + protected static int nonNegative(int n, String name) { + if (n < 0L) { + throw new IllegalArgumentException(name + " >= 0 required but it was " + n); + } + return n; + } + + /** + * Checks if the given value is positive and returns it; throws + * an IllegalArgumentException otherwise. + * @param n the number to check + * @param name the name of the parameter + * @return n + */ + protected static int positive(int n, String name) { + if (n <= 0L) { + throw new IllegalArgumentException(name + " > 0 required but it was " + n); + } + return n; + } + +} diff --git a/src/main/java/ix/IxAggregate.java b/src/main/java/ix/IxAggregate.java new file mode 100644 index 0000000..2a4b255 --- /dev/null +++ b/src/main/java/ix/IxAggregate.java @@ -0,0 +1,63 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxAggregate extends IxSource { + + final IxFunction2 aggregator; + + IxAggregate(Iterable source, IxFunction2 aggregator) { + super(source); + this.aggregator = aggregator; + } + + @Override + public Iterator iterator() { + return new AggregateIterator(source.iterator(), aggregator); + } + + static final class AggregateIterator extends IxSourceIterator { + + final IxFunction2 aggregator; + + AggregateIterator(Iterator it, IxFunction2 aggregator) { + super(it); + this.aggregator = aggregator; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + IxFunction2 f = aggregator; + + if (it.hasNext()) { + T acc = it.next(); + while (it.hasNext()) { + acc = f.apply(acc, it.next()); + } + value = acc; + hasValue = true; + done = true; + return true; + } + return false; + } + } + +} diff --git a/src/main/java/ix/IxAll.java b/src/main/java/ix/IxAll.java new file mode 100644 index 0000000..ceb6fd4 --- /dev/null +++ b/src/main/java/ix/IxAll.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxAll extends IxSource { + + final IxPredicate predicate; + + IxAll(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new AllIterator(source.iterator(), predicate); + } + + static final class AllIterator extends IxSourceIterator { + + final IxPredicate predicate; + + AllIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + IxPredicate p = predicate; + + while (it.hasNext()) { + if (!p.test(it.next())) { + hasValue = true; + value = false; + done = true; + return true; + } + } + + hasValue = true; + value = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxAny.java b/src/main/java/ix/IxAny.java new file mode 100644 index 0000000..9589936 --- /dev/null +++ b/src/main/java/ix/IxAny.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxAny extends IxSource { + + final IxPredicate predicate; + + IxAny(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new AnyIterator(source.iterator(), predicate); + } + + static final class AnyIterator extends IxSourceIterator { + + final IxPredicate predicate; + + AnyIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + IxPredicate p = predicate; + + while (it.hasNext()) { + if (p.test(it.next())) { + hasValue = true; + value = true; + done = true; + return true; + } + } + + hasValue = true; + value = false; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxAverageDouble.java b/src/main/java/ix/IxAverageDouble.java new file mode 100644 index 0000000..b51b692 --- /dev/null +++ b/src/main/java/ix/IxAverageDouble.java @@ -0,0 +1,61 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxAverageDouble extends IxSource { + + IxAverageDouble(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new AverageFloatIterator(source.iterator()); + } + + static final class AverageFloatIterator extends IxSourceIterator { + + AverageFloatIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + double accumulator = 0f; + long count = 0; + + if (!it.hasNext()) { + done = true; + return false; + } + + do { + accumulator += it.next().doubleValue(); + count++; + } while (it.hasNext()); + + value = accumulator / count; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxAverageFloat.java b/src/main/java/ix/IxAverageFloat.java new file mode 100644 index 0000000..8cf3664 --- /dev/null +++ b/src/main/java/ix/IxAverageFloat.java @@ -0,0 +1,61 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxAverageFloat extends IxSource { + + IxAverageFloat(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new AverageFloatIterator(source.iterator()); + } + + static final class AverageFloatIterator extends IxSourceIterator { + + AverageFloatIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + float accumulator = 0f; + int count = 0; + + if (!it.hasNext()) { + done = true; + return false; + } + + do { + accumulator += it.next().floatValue(); + count++; + } while (it.hasNext()); + + value = accumulator / count; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxBaseIterator.java b/src/main/java/ix/IxBaseIterator.java new file mode 100644 index 0000000..d46d00a --- /dev/null +++ b/src/main/java/ix/IxBaseIterator.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * A base iterator that manages + * the state between hasNext() and the next() calls; plus defines + * the remove() to throw UnsupportedOperationException. + * @param the result value type + */ +public abstract class IxBaseIterator implements Iterator { + + /** Indicates a value is available for consumption. */ + protected boolean hasValue; + + /** Indicates there are no more data available. */ + protected boolean done; + + /** The current value if hasValue is true. */ + protected R value; + + /** + * Move the stream forward by a single element. + * @return what the hasNext should return + */ + protected abstract boolean moveNext(); + + @Override + public final boolean hasNext() { + boolean b = hasValue; + if (!b) { + if (!done) { + return moveNext(); + } + } + return b; + } + + @Override + public final R next() { + if (!hasValue && !hasNext()) { + throw new NoSuchElementException(); + } + R v = value; + hasValue = false; + value = null; + return v; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/ix/CloseableIterable.java b/src/main/java/ix/IxBooleanSupplier.java similarity index 71% rename from src/main/java/ix/CloseableIterable.java rename to src/main/java/ix/IxBooleanSupplier.java index bfb4ad0..c1ecdc2 100644 --- a/src/main/java/ix/CloseableIterable.java +++ b/src/main/java/ix/IxBooleanSupplier.java @@ -1,26 +1,28 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - - -/** - * An iterable type which returns iterators that support a close() method. - * @param the iterator element type - */ -public interface CloseableIterable extends Iterable { - @Override - CloseableIterator iterator(); -} +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with no inputs and a boolean output. + */ +public interface IxBooleanSupplier { + /** + * Calls the function which returns a boolean. + * @return the output boolean + */ + boolean getAsBoolean(); +} diff --git a/src/main/java/ix/IxBuffer.java b/src/main/java/ix/IxBuffer.java new file mode 100644 index 0000000..1a03c38 --- /dev/null +++ b/src/main/java/ix/IxBuffer.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxBuffer extends IxSource> { + + final int size; + + IxBuffer(Iterable source, int size) { + super(source); + this.size = size; + } + + @Override + public Iterator> iterator() { + return new BufferIterator(source.iterator(), size); + } + + static final class BufferIterator extends IxSourceIterator> { + final int size; + + BufferIterator(Iterator it, int size) { + super(it); + this.size = size; + } + + @Override + protected boolean moveNext() { + int s = size; + + Iterator it = this.it; + + List list = new ArrayList(); + + while (s != 0 && it.hasNext()) { + list.add(it.next()); + s--; + } + + if (list.isEmpty()) { + done = true; + return false; + } + value = list; + hasValue = true; + if (s != 0) { + done = true; + } + return true; + } + + + } +} diff --git a/src/main/java/ix/IxBufferOverlap.java b/src/main/java/ix/IxBufferOverlap.java new file mode 100644 index 0000000..c801ddf --- /dev/null +++ b/src/main/java/ix/IxBufferOverlap.java @@ -0,0 +1,94 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxBufferOverlap extends IxSource> { + + final int size; + + final int skip; + + IxBufferOverlap(Iterable source, int size, int skip) { + super(source); + this.size = size; + this.skip = skip; + } + + @Override + public Iterator> iterator() { + return new BufferIterator(source.iterator(), size, skip); + } + + static final class BufferIterator extends IxSourceQueuedIterator, List> + implements IxConsumer2, T> { + final int size; + + final int skip; + + int index; + + BufferIterator(Iterator it, int size, int skip) { + super(it); + this.size = size; + this.skip = skip; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Iterator it = this.it; + + int s = size; + int k = skip; + + int i = index; + + while (it.hasNext()) { + if (i == 0) { + offer(new ArrayList()); + } + T v = it.next(); + foreach(this, v); + if (++i == k) { + i = 0; + } + + if (((List)peek()).size() == s) { + break; + } + } + index = i; + + List list = fromObject(poll()); + if (list == null) { + done = true; + return false; + } + + value = list; + hasValue = true; + return true; + } + + @Override + public void accept(List t1, T t2) { + t1.add(t2); + } + } +} diff --git a/src/main/java/ix/IxBufferSkip.java b/src/main/java/ix/IxBufferSkip.java new file mode 100644 index 0000000..70ca253 --- /dev/null +++ b/src/main/java/ix/IxBufferSkip.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxBufferSkip extends IxSource> { + + final int size; + + final int skip; + + IxBufferSkip(Iterable source, int size, int skip) { + super(source); + this.size = size; + this.skip = skip; + } + + @Override + public Iterator> iterator() { + return new BufferSkipIterator(source.iterator(), size, skip); + } + + static final class BufferSkipIterator extends IxSourceIterator> { + final int size; + + final int skip; + + boolean once; + + BufferSkipIterator(Iterator it, int size, int skip) { + super(it); + this.size = size; + this.skip = skip; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + int s = size; + + if (once) { + int k = skip - s; + while (k != 0 && it.hasNext()) { + it.next(); + k--; + } + + } else { + once = true; + } + + List list = new ArrayList(); + + while (s != 0 && it.hasNext()) { + list.add(it.next()); + s--; + } + + + if (list.isEmpty()) { + done = true; + return false; + } + value = list; + hasValue = true; + if (s != 0) { + done = true; + } + return true; + } + + + } +} diff --git a/src/main/java/ix/IxBufferSplit.java b/src/main/java/ix/IxBufferSplit.java new file mode 100644 index 0000000..e354496 --- /dev/null +++ b/src/main/java/ix/IxBufferSplit.java @@ -0,0 +1,103 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * Split into buffers when the predicate returns true and neither + * buffer contains the item. + * + * @param the value type + */ +final class IxBufferSplit extends IxSource> { + + final IxPredicate predicate; + + IxBufferSplit(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = new ArrayList(); + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + if (predicate.test(v)) { + buffer = b; + return true; + } + + b.add(v); + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxBufferUntil.java b/src/main/java/ix/IxBufferUntil.java new file mode 100644 index 0000000..6a1e72c --- /dev/null +++ b/src/main/java/ix/IxBufferUntil.java @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * Split into buffers when the predicate returns true and neither + * buffer contains the item. + * + * @param the value type + */ +final class IxBufferUntil extends IxSource> { + + final IxPredicate predicate; + + IxBufferUntil(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = new ArrayList(); + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + b.add(v); + + if (predicate.test(v)) { + buffer = b; + return true; + } + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + done = true; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxBufferWhile.java b/src/main/java/ix/IxBufferWhile.java new file mode 100644 index 0000000..af28b81 --- /dev/null +++ b/src/main/java/ix/IxBufferWhile.java @@ -0,0 +1,111 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * Buffer while the predicate returns true. + * + * @param the value type + */ +final class IxBufferWhile extends IxSource> { + + final IxPredicate predicate; + + IxBufferWhile(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator> iterator() { + return new BufferSplitIterator(source.iterator(), predicate); + } + + static final class BufferSplitIterator implements Iterator> { + + final Iterator source; + + final IxPredicate predicate; + + boolean done; + + List buffer; + + List next; + + BufferSplitIterator(Iterator source, IxPredicate predicate) { + this.source = source; + this.predicate = predicate; + } + + @Override + public boolean hasNext() { + List b = buffer; + if (b == null) { + if (done) { + return false; + } + + b = next; + if (b == null) { + b = new ArrayList(); + } + + Iterator src = source; + while (src.hasNext()) { + T v = src.next(); + + if (!predicate.test(v)) { + buffer = b; + b = new ArrayList(); + b.add(v); + next = b; + return true; + } + + b.add(v); + } + + if (b.isEmpty()) { + done = true; + return false; + } + + buffer = b; + done = true; + } + return true; + } + + @Override + public List next() { + if (hasNext()) { + List b = buffer; + buffer = null; + return b; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxCharacters.java b/src/main/java/ix/IxCharacters.java new file mode 100644 index 0000000..c54a404 --- /dev/null +++ b/src/main/java/ix/IxCharacters.java @@ -0,0 +1,75 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxCharacters extends Ix { + + final CharSequence source; + + final int start; + + final int end; + + IxCharacters(CharSequence source, int start, int end) { + this.source = source; + this.start = start; + this.end = end; + } + + @Override + public Iterator iterator() { + return new CharactersIterator(source, start, end); + } + + static final class CharactersIterator implements Iterator { + + final CharSequence source; + + final int end; + + int index; + + CharactersIterator(CharSequence source, int start, int end) { + this.source = source; + this.index = start; + this.end = end; + } + + @Override + public boolean hasNext() { + return index != end; + } + + @Override + public Integer next() { + int i = index; + if (i != end) { + index = i + 1; + return (int)source.charAt(i); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/src/main/java/ix/IxCollect.java b/src/main/java/ix/IxCollect.java new file mode 100644 index 0000000..4932bc2 --- /dev/null +++ b/src/main/java/ix/IxCollect.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxCollect extends IxSource { + + final IxSupplier initialFactory; + + final IxConsumer2 collector; + + IxCollect(Iterable source, IxSupplier initialFactory, IxConsumer2 collector) { + super(source); + this.initialFactory = initialFactory; + this.collector = collector; + } + + @Override + public Iterator iterator() { + return new CollectorIterator(source.iterator(), collector, initialFactory.get()); + } + + static final class CollectorIterator extends IxSourceIterator { + + final IxConsumer2 collector; + + CollectorIterator(Iterator it, IxConsumer2 collector, C value) { + super(it); + this.collector = collector; + this.value = value; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + IxConsumer2 coll = collector; + + C c = value; + + while (it.hasNext()) { + coll.accept(c, it.next()); + } + + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxCompose.java b/src/main/java/ix/IxCompose.java new file mode 100644 index 0000000..c578bf8 --- /dev/null +++ b/src/main/java/ix/IxCompose.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxCompose extends IxSource { + + final IxFunction, ? extends Iterable> transformer; + + IxCompose(Iterable source, IxFunction, ? extends Iterable> transformer) { + super(source); + this.transformer = transformer; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + return (Iterator)transformer.apply(from(source)).iterator(); + } + +} diff --git a/src/main/java/ix/internal/util/package-info.java b/src/main/java/ix/IxConsumer.java similarity index 71% rename from src/main/java/ix/internal/util/package-info.java rename to src/main/java/ix/IxConsumer.java index cb6f35e..b56463b 100644 --- a/src/main/java/ix/internal/util/package-info.java +++ b/src/main/java/ix/IxConsumer.java @@ -1,19 +1,29 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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. - */ -/** - * Contains utility classes to support the internal implementations. - */ -package ix.internal.util; \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with one input value. + * @param the input value type + */ +public interface IxConsumer { + /** + * Applies a function to the input value. + * @param t the input value + */ + void accept(T t); +} diff --git a/src/main/java/ix/IxConsumer2.java b/src/main/java/ix/IxConsumer2.java new file mode 100644 index 0000000..5ec592c --- /dev/null +++ b/src/main/java/ix/IxConsumer2.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with two input values. + * @param the input value type + * @param the input value type + */ +public interface IxConsumer2 { + /** + * Applies a function to the input value. + * @param t the first input value + * @param u the second input value + */ + void accept(T t, U u); +} diff --git a/src/main/java/ix/IxContains.java b/src/main/java/ix/IxContains.java new file mode 100644 index 0000000..5e44c24 --- /dev/null +++ b/src/main/java/ix/IxContains.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxContains extends IxSource { + + final Object o; + + IxContains(Iterable source, Object o) { + super(source); + this.o = o; + } + + @Override + public Iterator iterator() { + return new ContainsIterator(source.iterator(), o); + } + + static final class ContainsIterator extends IxSourceIterator { + + final Object o; + + ContainsIterator(Iterator it, Object o) { + super(it); + this.o = o; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + Object o = this.o; + + while (it.hasNext()) { + T v = it.next(); + if (o == v || (o != null && o.equals(v))) { + value = true; + hasValue = true; + done = true; + return true; + } + } + + value = false; + hasValue = true; + done = true; + return true; + } + } + +} diff --git a/src/main/java/ix/IxCount.java b/src/main/java/ix/IxCount.java new file mode 100644 index 0000000..882f662 --- /dev/null +++ b/src/main/java/ix/IxCount.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxCount extends IxSource { + + IxCount(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new CountIterator(source.iterator()); + } + + static final class CountIterator extends IxSourceIterator { + + CountIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + int c = 0; + + Iterator it = this.it; + + while (it.hasNext()) { + it.next(); + c++; + } + + value = c; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxCountLong.java b/src/main/java/ix/IxCountLong.java new file mode 100644 index 0000000..f06a40f --- /dev/null +++ b/src/main/java/ix/IxCountLong.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxCountLong extends IxSource { + + IxCountLong(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new CountLongIterator(source.iterator()); + } + + static final class CountLongIterator extends IxSourceIterator { + + CountLongIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + long c = 0; + + Iterator it = this.it; + + while (it.hasNext()) { + it.next(); + c++; + } + + value = c; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/internal/operators/DeferIterable.java b/src/main/java/ix/IxDefer.java similarity index 63% rename from src/main/java/ix/internal/operators/DeferIterable.java rename to src/main/java/ix/IxDefer.java index e2271a1..6d5b409 100644 --- a/src/main/java/ix/internal/operators/DeferIterable.java +++ b/src/main/java/ix/IxDefer.java @@ -1,33 +1,34 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -import rx.functions.Func0; - -public final class DeferIterable implements Iterable { - private final Func0> func; - - public DeferIterable(Func0> func) { - this.func = func; - } - - @Override - public Iterator iterator() { - return func.call().iterator(); - } -} \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxDefer extends Ix { + + final IxSupplier> factory; + + IxDefer(IxSupplier> factory) { + this.factory = factory; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + return (Iterator)factory.get().iterator(); + } +} diff --git a/src/main/java/ix/IxDistinct.java b/src/main/java/ix/IxDistinct.java new file mode 100644 index 0000000..94ac42d --- /dev/null +++ b/src/main/java/ix/IxDistinct.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxDistinct extends IxSource { + + final IxFunction keySelector; + + IxDistinct(Iterable source, IxFunction keySelector) { + super(source); + this.keySelector = keySelector; + } + + @Override + public Iterator iterator() { + return new DistinctIterator(source.iterator(), keySelector); + } + + static final class DistinctIterator extends IxSourceIterator { + final IxFunction keySelector; + + final Set set; + + DistinctIterator(Iterator it, IxFunction keySelector) { + super(it); + this.keySelector = keySelector; + this.set = new HashSet(); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + while (it.hasNext()) { + T v = it.next(); + + K k = keySelector.apply(v); + + if (set.add(k)) { + value = v; + hasValue = true; + return true; + } + } + + done = true; + return false; + } + } +} diff --git a/src/main/java/ix/IxDistinctUntilChanged.java b/src/main/java/ix/IxDistinctUntilChanged.java new file mode 100644 index 0000000..9f7b44a --- /dev/null +++ b/src/main/java/ix/IxDistinctUntilChanged.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxDistinctUntilChanged extends IxSource { + + final IxFunction keySelector; + + final IxPredicate2 comparer; + + IxDistinctUntilChanged(Iterable source, IxFunction keySelector, + IxPredicate2 comparer) { + super(source); + this.keySelector = keySelector; + this.comparer = comparer; + } + + @Override + public Iterator iterator() { + return new DistinctUntilChangedIterator(source.iterator(), keySelector, comparer); + } + + static final class DistinctUntilChangedIterator extends IxSourceIterator { + + final IxFunction keySelector; + + final IxPredicate2 comparer; + + K last; + + boolean once; + + DistinctUntilChangedIterator(Iterator it, IxFunction keySelector, + IxPredicate2 comparer) { + super(it); + this.keySelector = keySelector; + this.comparer = comparer; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + K prev = last; + K curr; + + while (it.hasNext()) { + T v = it.next(); + curr = keySelector.apply(v); + + if (!once) { + once = true; + + last = curr; + + value = v; + hasValue = true; + return true; + } + + if (!comparer.test(prev, curr)) { + last = curr; + + value = v; + hasValue = true; + return true; + } + + prev = curr; + } + + + done = true; + return false; + } + + + } +} diff --git a/src/main/java/ix/IxDoOn.java b/src/main/java/ix/IxDoOn.java new file mode 100644 index 0000000..57feef6 --- /dev/null +++ b/src/main/java/ix/IxDoOn.java @@ -0,0 +1,63 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxDoOn extends IxSource { + + final IxConsumer onNext; + + final Runnable onCompleted; + + IxDoOn(Iterable source, IxConsumer onNext, Runnable onCompleted) { + super(source); + this.onNext = onNext; + this.onCompleted = onCompleted; + } + + @Override + public Iterator iterator() { + return new DoOnIterator(source.iterator(), onNext, onCompleted); + } + + static final class DoOnIterator extends IxSourceIterator { + final IxConsumer onNext; + + final Runnable onCompleted; + + DoOnIterator(Iterator it, IxConsumer onNext, Runnable onCompleted) { + super(it); + this.onNext = onNext; + this.onCompleted = onCompleted; + } + + @Override + protected boolean moveNext() { + if (it.hasNext()) { + T v = it.next(); + value = v; + hasValue = true; + onNext.accept(v); + return true; + } + onCompleted.run(); + done = true; + return false; + } + } +} diff --git a/src/main/java/ix/IxEmitter.java b/src/main/java/ix/IxEmitter.java new file mode 100644 index 0000000..f1a0e61 --- /dev/null +++ b/src/main/java/ix/IxEmitter.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * Allows signalling values or completion in an imperative manner. + * + * @param the value type emitted + */ +public interface IxEmitter { + + /** + * The next value to signal. + * @param value the value to signal + */ + void onNext(T value); + + /** + * Indicate no more values will be generated. + */ + void onComplete(); +} diff --git a/src/test/java/ix/TestInteractiveTake.java b/src/main/java/ix/IxEmpty.java similarity index 50% rename from src/test/java/ix/TestInteractiveTake.java rename to src/main/java/ix/IxEmpty.java index e778003..7e76d4d 100644 --- a/src/test/java/ix/TestInteractiveTake.java +++ b/src/main/java/ix/IxEmpty.java @@ -1,39 +1,49 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import static ix.internal.operators.Interactive.concat; -import static ix.internal.operators.Interactive.size; -import static ix.internal.operators.Interactive.take; -import static ix.internal.operators.Interactive.toIterable; - -import org.junit.Test; - -/** - * Test the Interactive.take operator. - */ -public class TestInteractiveTake { - /** - * Test take(). - */ - @Test - public void takeOk() { - Iterable prefix = toIterable(1, 2); - Iterable i = concat(prefix, toIterable(3, 4)); - TestUtil.assertEqual(take(i, size(prefix)), prefix); - } - -} +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxEmpty extends Ix implements Iterator { + + static final IxEmpty INSTANCE = new IxEmpty(); + + @SuppressWarnings("unchecked") + static Ix instance() { + return (Ix)INSTANCE; + } + + @Override + public Iterator iterator() { + return this; + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/ix/IxEmptyAction.java b/src/main/java/ix/IxEmptyAction.java new file mode 100644 index 0000000..44bf72c --- /dev/null +++ b/src/main/java/ix/IxEmptyAction.java @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +enum IxEmptyAction implements IxConsumer, Runnable { + INSTANCE; + + @SuppressWarnings("unchecked") + public static IxConsumer instance1() { + return (IxConsumer)INSTANCE; + } + + public static Runnable instance0() { + return INSTANCE; + } + + @Override + public void accept(Object t) { + // deliberately no op + } + + @Override + public void run() { + // deliberately no op + } + +} diff --git a/src/main/java/ix/IxEvery.java b/src/main/java/ix/IxEvery.java new file mode 100644 index 0000000..7c510a2 --- /dev/null +++ b/src/main/java/ix/IxEvery.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * Emits every Nth item from upstream. + * + * @param the value type + */ +final class IxEvery extends IxSource { + + final int nth; + + IxEvery(Iterable source, int nth) { + super(source); + this.nth = nth; + } + + @Override + public Iterator iterator() { + return new EveryIterator(source.iterator(), nth); + } + + static final class EveryIterator implements Iterator { + + final Iterator source; + + final int nth; + + boolean done; + + boolean hasValue; + + EveryIterator(Iterator it, int nth) { + this.source = it; + this.nth = nth; + } + + @Override + public boolean hasNext() { + if (done) { + return false; + } + if (!hasValue) { + int i = nth - 1; + + Iterator src = source; + + while (i != 0 && src.hasNext()) { + src.next(); + i--; + } + + if (src.hasNext()) { + hasValue = true; + return true; + } + + done = true; + return false; + } + return true; + } + + @Override + public T next() { + if (hasNext()) { + hasValue = false; + return source.next(); + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + source.remove(); + } + } +} diff --git a/src/main/java/ix/IxExcept.java b/src/main/java/ix/IxExcept.java new file mode 100644 index 0000000..af4bdb5 --- /dev/null +++ b/src/main/java/ix/IxExcept.java @@ -0,0 +1,98 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; +import java.util.Map.Entry; + +final class IxExcept extends IxSource { + + final Iterable other; + + IxExcept(Iterable source, Iterable other) { + super(source); + this.other = other; + } + + @Override + public Iterator iterator() { + return new ExceptIterator(source.iterator(), other.iterator()); + } + + static final class ExceptIterator extends IxSourceIterator { + final Iterator other; + + final LinkedHashMap set; + + Iterator> setIterator; + + boolean once; + + boolean second; + + ExceptIterator(Iterator it, Iterator other) { + super(it); + this.other = other; + this.set = new LinkedHashMap(); + } + + @Override + protected boolean moveNext() { + LinkedHashMap secondSet = set; + if (!once) { + once = true; + while (other.hasNext()) { + secondSet.put(other.next(), true); + } + } + + for (;;) { + if (second) { + Iterator> sIt = setIterator; + while (sIt.hasNext()) { + Entry e = sIt.next(); + + if (e.getValue()) { + value = e.getKey(); + hasValue = true; + return true; + } + } + done = true; + return false; + } else { + Iterator fIt = it; + while (fIt.hasNext()) { + T v = fIt.next(); + + Boolean b = secondSet.get(v); + if (b == null) { + value = v; + hasValue = true; + return true; + } + if (b) { + secondSet.put(v, false); + } + } + second = true; + setIterator = secondSet.entrySet().iterator(); + } + } + } + } +} diff --git a/src/main/java/ix/IxFilter.java b/src/main/java/ix/IxFilter.java new file mode 100644 index 0000000..c26a036 --- /dev/null +++ b/src/main/java/ix/IxFilter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxFilter extends IxSource { + + final IxPredicate predicate; + + IxFilter(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new FilterIterator(source.iterator(), predicate); + } + + static final class FilterIterator extends IxSourceIterator { + + final IxPredicate predicate; + + FilterIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + for (;;) { + if (it.hasNext()) { + T v = it.next(); + if (predicate.test(v)) { + value = v; + hasValue = true; + return true; + } + } else { + done = true; + return false; + } + } + } + + @Override + public void remove() { + it.remove(); + } + } +} diff --git a/src/main/java/ix/IxFlattenArrayIterable.java b/src/main/java/ix/IxFlattenArrayIterable.java new file mode 100644 index 0000000..e8656ce --- /dev/null +++ b/src/main/java/ix/IxFlattenArrayIterable.java @@ -0,0 +1,88 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; +import java.util.concurrent.Callable; + +final class IxFlattenArrayIterable extends Ix { + + final Iterable[] sources; + + IxFlattenArrayIterable(Iterable[] sources) { + this.sources = sources; + } + + @Override + public Iterator iterator() { + return new FlattenIterator(sources); + } + + static final class FlattenIterator extends IxBaseIterator { + + final Iterable[] sources; + + Iterator current; + + int index; + + FlattenIterator(Iterable[] sources) { + this.sources = sources; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Iterator c = current; + + while (c == null) { + int i = index; + if (i != sources.length) { + Iterable inner = sources[i]; + index = i + 1; + if (inner instanceof Callable) { + value = checkedCall(((Callable)inner)); + hasValue = true; + return true; + } + + c = inner.iterator(); + + if (c.hasNext()) { + current = c; + break; + } else { + c = null; + } + } else { + done = true; + return false; + } + } + + value = c.next(); + hasValue = true; + + if (!c.hasNext()) { + current = null; + } + return true; + } + + } + +} diff --git a/src/main/java/ix/IxFlattenIterable.java b/src/main/java/ix/IxFlattenIterable.java new file mode 100644 index 0000000..d1969c1 --- /dev/null +++ b/src/main/java/ix/IxFlattenIterable.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; +import java.util.concurrent.Callable; + +final class IxFlattenIterable extends IxSource { + + final IxFunction> mapper; + + IxFlattenIterable(Iterable source, IxFunction> mapper) { + super(source); + this.mapper = mapper; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + if (source instanceof Callable) { + return (Iterator)(mapper.apply(checkedCall((Callable)source)).iterator()); + } + return new FlattenIterator(source.iterator(), mapper); + } + + static final class FlattenIterator extends IxSourceIterator { + + final IxFunction> mapper; + + Iterator current; + + FlattenIterator(Iterator it, IxFunction> mapper) { + super(it); + this.mapper = mapper; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Iterator c = current; + + while (c == null) { + if (it.hasNext()) { + Iterable inner = mapper.apply(it.next()); + if (inner instanceof Callable) { + value = checkedCall((Callable)inner); + hasValue = true; + return true; + } + + c = inner.iterator(); + + if (c.hasNext()) { + current = c; + break; + } else { + c = null; + } + } else { + done = true; + return false; + } + } + + value = c.next(); + hasValue = true; + + if (!c.hasNext()) { + current = null; + } + return true; + } + + } + +} diff --git a/src/main/java/ix/IxForloop.java b/src/main/java/ix/IxForloop.java new file mode 100644 index 0000000..7035e9a --- /dev/null +++ b/src/main/java/ix/IxForloop.java @@ -0,0 +1,86 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxForloop extends Ix { + + final T seed; + + final IxPredicate condition; + + final IxFunction selector; + + final IxFunction next; + + IxForloop(T seed, IxPredicate condition, IxFunction selector, + IxFunction next) { + this.seed = seed; + this.condition = condition; + this.selector = selector; + this.next = next; + } + + @Override + public Iterator iterator() { + return new ForloopIterator(seed, condition, selector, next); + } + + static final class ForloopIterator extends IxBaseIterator { + + T index; + + final IxPredicate condition; + + final IxFunction selector; + + final IxFunction next; + + boolean exceptFirst; + + ForloopIterator(T index, IxPredicate condition, IxFunction selector, + IxFunction next) { + this.index = index; + this.condition = condition; + this.selector = selector; + this.next = next; + } + + @Override + protected boolean moveNext() { + T i = index; + + if (exceptFirst) { + i = next.apply(i); + index = i; + } else { + exceptFirst = true; + } + + if (!condition.test(i)) { + done = true; + return false; + } + + value = selector.apply(i); + hasValue = true; + + return true; + } + } +} diff --git a/src/main/java/ix/IxFromArray.java b/src/main/java/ix/IxFromArray.java new file mode 100644 index 0000000..7bb3e1f --- /dev/null +++ b/src/main/java/ix/IxFromArray.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxFromArray extends Ix { + + final int start; + final int end; + final T[] array; + + IxFromArray(int start, int end, T[] array) { + this.start = start; + this.end = end; + this.array = array; + } + + @Override + public Iterator iterator() { + return new FromArray(start, end, array); + } + + static final class FromArray implements Iterator { + final T[] array; + + final int end; + + int index; + + FromArray(int start, int end, T[] array) { + this.index = start; + this.end = end; + this.array = array; + } + + @Override + public boolean hasNext() { + return index != end; + } + + @Override + public T next() { + int i = index; + if (i != end) { + index = i + 1; + return array[i]; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxFunction.java b/src/main/java/ix/IxFunction.java new file mode 100644 index 0000000..3086135 --- /dev/null +++ b/src/main/java/ix/IxFunction.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with one input value and one output value. + * @param the input value type + * @param the output value type + */ +public interface IxFunction { + /** + * Applies a function to the input value and returns an output value. + * @param t the input value + * @return the output value + */ + R apply(T t); +} diff --git a/src/main/java/ix/Enumerable.java b/src/main/java/ix/IxFunction2.java similarity index 56% rename from src/main/java/ix/Enumerable.java rename to src/main/java/ix/IxFunction2.java index e3db935..64cceac 100644 --- a/src/main/java/ix/Enumerable.java +++ b/src/main/java/ix/IxFunction2.java @@ -1,31 +1,33 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -/** - * The base interface for an Enumerable-Enumerator - * pair of iteration method where the - * enumerator has next() to - * advance the iteration and current() - * to return the current element. An example - * from normal Java for such - * kind of iteration is the java.sql.ResultSet. - * @param the element type - */ -public interface Enumerable { - /** @return the enumerator. */ - Enumerator enumerator(); -} +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with two input values and one output value. + * @param the first input value type + * @param the second input value type + * @param the output value type + */ +public interface IxFunction2 { + /** + * Applies a function to the input values and returns an output value. + * @param t the first input value + * @param u the second input value + * @return the output value + */ + R apply(T t, U u); +} diff --git a/src/main/java/ix/IxFunction3.java b/src/main/java/ix/IxFunction3.java new file mode 100644 index 0000000..827f97c --- /dev/null +++ b/src/main/java/ix/IxFunction3.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with three input values and one output value. + * @param the first input value type + * @param the second input value type + * @param the third input value type + * @param the output value type + */ +public interface IxFunction3 { + /** + * Applies a function to the input values and returns an output value. + * @param t the first input value + * @param u the second input value + * @param v the third input value + * @return the output value + */ + R apply(T t, U u, V v); +} diff --git a/src/main/java/ix/IxFunction4.java b/src/main/java/ix/IxFunction4.java new file mode 100644 index 0000000..562601c --- /dev/null +++ b/src/main/java/ix/IxFunction4.java @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with four input values and one output value. + * @param the first input value type + * @param the second input value type + * @param the third input value type + * @param the fourth input value type + * @param the output value type + */ +public interface IxFunction4 { + /** + * Applies a function to the input values and returns an output value. + * @param t the first input value + * @param u the second input value + * @param v the third input value + * @param w the fourth input value + * @return the output value + */ + R apply(T t, U u, V v, W w); +} diff --git a/src/main/java/ix/IxGenerate.java b/src/main/java/ix/IxGenerate.java new file mode 100644 index 0000000..b7740d8 --- /dev/null +++ b/src/main/java/ix/IxGenerate.java @@ -0,0 +1,83 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxGenerate extends Ix { + + final IxSupplier stateFactory; + + final IxFunction2, S> generator; + + final IxConsumer stateDisposer; + + IxGenerate(IxSupplier stateFactory, IxFunction2, S> generator, IxConsumer stateDisposer) { + this.stateFactory = stateFactory; + this.generator = generator; + this.stateDisposer = stateDisposer; + } + + @Override + public Iterator iterator() { + return new GenerateIterator(stateFactory.get(), generator, stateDisposer); + } + + static final class GenerateIterator extends IxBaseIterator + implements IxEmitter { + + final IxFunction2, S> generator; + + final IxConsumer stateDisposer; + + S state; + + GenerateIterator(S state, IxFunction2, S> generator, IxConsumer stateDisposer) { + this.state = state; + this.generator = generator; + this.stateDisposer = stateDisposer; + } + + @Override + protected boolean moveNext() { + + state = generator.apply(state, this); + + boolean hv = hasValue; + boolean d = done; + if (!hv && !d) { + stateDisposer.accept(state); + throw new IllegalStateException("The generator didn't call any of the onXXX methods!"); + } + if (d) { + stateDisposer.accept(state); + } + return hv; + } + + @Override + public void onNext(T t) { + value = t; + hasValue = true; + } + + @Override + public void onComplete() { + done = true; + } + } +} diff --git a/src/main/java/ix/IxGenerateStateless.java b/src/main/java/ix/IxGenerateStateless.java new file mode 100644 index 0000000..ac28483 --- /dev/null +++ b/src/main/java/ix/IxGenerateStateless.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxGenerateStateless extends Ix { + + final IxConsumer> generator; + + IxGenerateStateless(IxConsumer> generator) { + this.generator = generator; + } + + @Override + public Iterator iterator() { + return new GenerateIterator(generator); + } + + static final class GenerateIterator extends IxBaseIterator + implements IxEmitter { + + final IxConsumer> generator; + + GenerateIterator(IxConsumer> generator) { + this.generator = generator; + } + + @Override + protected boolean moveNext() { + + generator.accept(this); + + boolean hv = hasValue; + if (!hv && !done) { + throw new IllegalStateException("The generator didn't call any of the onXXX methods!"); + } + return hv; + } + + @Override + public void onNext(T t) { + value = t; + hasValue = true; + } + + @Override + public void onComplete() { + done = true; + } + } +} diff --git a/src/main/java/ix/IxGroupBy.java b/src/main/java/ix/IxGroupBy.java new file mode 100644 index 0000000..e23d9f3 --- /dev/null +++ b/src/main/java/ix/IxGroupBy.java @@ -0,0 +1,192 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxGroupBy extends IxSource> { + + static final Object NULL = new Object(); + + final IxFunction keySelector; + + final IxFunction valueSelector; + + IxGroupBy(Iterable source, IxFunction keySelector, + IxFunction valueSelector) { + super(source); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + } + + @Override + public Iterator> iterator() { + return new GroupByIterator(source.iterator(), keySelector, valueSelector); + } + + static final class GroupByIterator extends IxSourceIterator> { + final IxFunction keySelector; + + final IxFunction valueSelector; + + final Map> groups; + + final Queue> queue; + + GroupByIterator(Iterator it, IxFunction keySelector, + IxFunction valueSelector) { + super(it); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + this.groups = new HashMap>(); + this.queue = new ArrayDeque>(); + } + + @Override + protected boolean moveNext() { + GroupedIterable g = queue.poll(); + if (g != null) { + value = g; + hasValue = true; + return true; + } + if (mainMoveNext()) { + g = queue.poll(); + value = g; + hasValue = true; + return true; + } + done = true; + return false; + } + + boolean mainMoveNext() { + for (;;) { + if (!it.hasNext()) { + groups.clear(); + return false; + } + + T v = it.next(); + + K key = keySelector.apply(v); + V val = valueSelector.apply(v); + + GroupedIterable g = groups.get(key); + if (g == null) { + g = new GroupedIterable(key, this); + groups.put(key, g); + g.iterator.queue.offer(val != null ? val : NULL); + + queue.offer(g); + return true; + } else { + g.iterator.queue.offer(val != null ? val : NULL); + } + } + } + + boolean groupMoveNext(GroupByGroupIterator groupIterator) { + if (done) { + return false; + } + for (;;) { + if (!it.hasNext()) { + groups.clear(); + return false; + } + + T v = it.next(); + + K key = keySelector.apply(v); + V val = valueSelector.apply(v); + + GroupedIterable g = groups.get(key); + if (g == null) { + g = new GroupedIterable(key, this); + groups.put(key, g); + g.iterator.queue.offer(val != null ? val : NULL); + queue.offer(g); + } else { + g.iterator.queue.offer(val != null ? val : NULL); + if (EqualityHelper.INSTANCE.test(key, groupIterator.key)) { + return true; + } + } + } + } + } + + static final class GroupedIterable extends GroupedIx { + + final GroupByGroupIterator iterator; + + boolean once; + + GroupedIterable(K key, GroupByIterator parent) { + super(key); + this.iterator = new GroupByGroupIterator(parent, key); + } + + @Override + public Iterator iterator() { + if (!once) { + once = true; + return iterator; + } + throw new IllegalStateException("This GroupedIx iterable can be consumed only once."); + } + + @Override + public String toString() { + return "GroupedIterable[key=" + iterator.key + ", queue=" + iterator.queue.size() + "]"; + } + } + + static final class GroupByGroupIterator extends IxBaseIterator { + final GroupByIterator parent; + + final K key; + + final ArrayDeque queue; + + GroupByGroupIterator(GroupByIterator parent, K key) { + this.parent = parent; + this.key = key; + this.queue = new ArrayDeque(); + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Object o = queue.poll(); + if (o != null) { + value = o == NULL ? null : (V)o; + hasValue = true; + return true; + } + if (parent.groupMoveNext(this)) { + o = queue.poll(); + value = o == NULL ? null : (V)o; + hasValue = true; + return true; + } + done = true; + return false; + } + } +} diff --git a/src/main/java/ix/IxHasElements.java b/src/main/java/ix/IxHasElements.java new file mode 100644 index 0000000..1d2d9b9 --- /dev/null +++ b/src/main/java/ix/IxHasElements.java @@ -0,0 +1,46 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxHasElements extends IxSource { + + IxHasElements(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new HasElementsIterator(source.iterator()); + } + + static final class HasElementsIterator extends IxSourceIterator { + + HasElementsIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + value = it.hasNext(); + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/internal/operators/Skip.java b/src/main/java/ix/IxIgnoreElements.java similarity index 53% rename from src/main/java/ix/internal/operators/Skip.java rename to src/main/java/ix/IxIgnoreElements.java index ef768a4..f7240f5 100644 --- a/src/main/java/ix/internal/operators/Skip.java +++ b/src/main/java/ix/IxIgnoreElements.java @@ -14,35 +14,38 @@ * limitations under the License. */ -package ix.internal.operators; +package ix; -import java.util.*; +import java.util.Iterator; -public final class Skip implements Iterable { - final Iterable source; - - final int num; +final class IxIgnoreElements extends IxSource { - public Skip(Iterable source, int num) { - this.source = source; - this.num = num; + IxIgnoreElements(Iterable source) { + super(source); } - + @Override public Iterator iterator() { - @SuppressWarnings("unchecked") - Iterator it = (Iterator)source.iterator(); - - int i = num; - - while (i > 0) { - if (!it.hasNext()) { - return Collections.emptyList().iterator(); + return new IgnoreElementsIterator(source.iterator()); + } + + static final class IgnoreElementsIterator extends IxSourceIterator { + + IgnoreElementsIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + while (it.hasNext()) { + it.next(); } - it.next(); - i--; + + done = true; + return false; } - - return it; + } } diff --git a/src/main/java/ix/IxIntersect.java b/src/main/java/ix/IxIntersect.java new file mode 100644 index 0000000..40a1332 --- /dev/null +++ b/src/main/java/ix/IxIntersect.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxIntersect extends IxSource { + + final Iterable other; + + IxIntersect(Iterable source, Iterable other) { + super(source); + this.other = other; + } + + @Override + public Iterator iterator() { + return new IntersectIterator(source.iterator(), other.iterator()); + } + + static final class IntersectIterator extends IxSourceIterator { + final Iterator other; + + final Set set; + + boolean once; + + IntersectIterator(Iterator it, Iterator other) { + super(it); + this.other = other; + this.set = new HashSet(); + } + + @Override + protected boolean moveNext() { + Set secondSet = set; + if (!once) { + once = true; + Iterator o = other; + while (o.hasNext()) { + secondSet.add(o.next()); + } + } + + Iterator fIt = it; + while (fIt.hasNext()) { + T v = fIt.next(); + + if (secondSet.contains(v)) { + value = v; + hasValue = true; + return true; + } + } + + done = true; + return false; + } + } +} diff --git a/src/main/java/ix/IxJoin.java b/src/main/java/ix/IxJoin.java new file mode 100644 index 0000000..85566bd --- /dev/null +++ b/src/main/java/ix/IxJoin.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxJoin extends IxSource { + + final CharSequence separator; + + IxJoin(Iterable source, CharSequence separator) { + super(source); + this.separator = separator; + } + + @Override + public Iterator iterator() { + return new JoinIterator(source.iterator(), separator); + } + + static final class JoinIterator extends IxSourceIterator { + final CharSequence separator; + + JoinIterator(Iterator it, CharSequence separator) { + super(it); + this.separator = separator; + } + + @Override + protected boolean moveNext() { + CharSequence sep = separator; + + Iterator it = this.it; + + StringBuilder b = new StringBuilder(); + + if (it.hasNext()) { + b.append(it.next()); + + while (it.hasNext()) { + b.append(sep); + b.append(it.next()); + } + } + + value = b.toString(); + hasValue = true; + done = true; + return true; + } + } + +} diff --git a/src/main/java/ix/IxJust.java b/src/main/java/ix/IxJust.java new file mode 100644 index 0000000..b28fa2f --- /dev/null +++ b/src/main/java/ix/IxJust.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxJust extends Ix implements IxScalarCallable { + + final T value; + + IxJust(T value) { + this.value = value; + } + + @Override + public T call() { + return value; + } + + @Override + public Iterator iterator() { + return new JustIterator(value); + } + + static final class JustIterator implements Iterator { + + final T value; + + boolean empty; + + JustIterator(T value) { + this.value = value; + } + + @Override + public boolean hasNext() { + return !empty; + } + + @Override + public T next() { + if (!empty) { + empty = true; + return value; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/internal/operators/ShareIterable.java b/src/main/java/ix/IxLift.java similarity index 60% rename from src/main/java/ix/internal/operators/ShareIterable.java rename to src/main/java/ix/IxLift.java index e1c2b24..0c4ec67 100644 --- a/src/main/java/ix/internal/operators/ShareIterable.java +++ b/src/main/java/ix/IxLift.java @@ -1,36 +1,35 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -public final class ShareIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - Iterator it; - - public ShareIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator iterator() { - if (it == null) { - it = source.iterator(); - } - return it; - } -} \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxLift extends IxSource { + + final IxFunction, ? extends Iterator> lifter; + + IxLift(Iterable source, IxFunction, ? extends Iterator> lifter) { + super(source); + this.lifter = lifter; + } + + @Override + public Iterator iterator() { + return lifter.apply(source.iterator()); + } + +} diff --git a/src/main/java/ix/IxMap.java b/src/main/java/ix/IxMap.java new file mode 100644 index 0000000..684de67 --- /dev/null +++ b/src/main/java/ix/IxMap.java @@ -0,0 +1,61 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxMap extends IxSource { + + final IxFunction mapper; + + IxMap(Iterable source, IxFunction mapper) { + super(source); + this.mapper = mapper; + } + + @Override + public Iterator iterator() { + return new MapIterator(source.iterator(), mapper); + } + + static final class MapIterator implements Iterator { + + final Iterator it; + + final IxFunction mapper; + + MapIterator(Iterator it, IxFunction mapper) { + this.it = it; + this.mapper = mapper; + } + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public R next() { + return mapper.apply(it.next()); + } + + @Override + public void remove() { + it.remove(); + } + } +} diff --git a/src/main/java/ix/IxMaxInt.java b/src/main/java/ix/IxMaxInt.java new file mode 100644 index 0000000..394a340 --- /dev/null +++ b/src/main/java/ix/IxMaxInt.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxMaxInt extends IxSource { + + IxMaxInt(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new MaxIntIterator(source.iterator()); + } + + static final class MaxIntIterator extends IxSourceIterator { + + MaxIntIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + int sum = it.next(); + + while (it.hasNext()) { + sum = Math.max(sum, it.next()); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxMaxLong.java b/src/main/java/ix/IxMaxLong.java new file mode 100644 index 0000000..652255d --- /dev/null +++ b/src/main/java/ix/IxMaxLong.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxMaxLong extends IxSource { + + IxMaxLong(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new MaxLongIterator(source.iterator()); + } + + static final class MaxLongIterator extends IxSourceIterator { + + MaxLongIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + long sum = it.next(); + + while (it.hasNext()) { + sum = Math.max(sum, it.next()); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxMinInt.java b/src/main/java/ix/IxMinInt.java new file mode 100644 index 0000000..0f5f627 --- /dev/null +++ b/src/main/java/ix/IxMinInt.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxMinInt extends IxSource { + + IxMinInt(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new MinIntIterator(source.iterator()); + } + + static final class MinIntIterator extends IxSourceIterator { + + MinIntIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + int sum = it.next(); + + while (it.hasNext()) { + sum = Math.min(sum, it.next()); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxMinLong.java b/src/main/java/ix/IxMinLong.java new file mode 100644 index 0000000..7a04e9f --- /dev/null +++ b/src/main/java/ix/IxMinLong.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxMinLong extends IxSource { + + IxMinLong(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new MinLongIterator(source.iterator()); + } + + static final class MinLongIterator extends IxSourceIterator { + + MinLongIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + long sum = it.next(); + + while (it.hasNext()) { + sum = Math.min(sum, it.next()); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxMinMax.java b/src/main/java/ix/IxMinMax.java new file mode 100644 index 0000000..d2e2e24 --- /dev/null +++ b/src/main/java/ix/IxMinMax.java @@ -0,0 +1,81 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxMinMax extends IxSource { + + final Comparator comparator; + + final int flag; + + IxMinMax(Iterable source, Comparator comparator, int flag) { + super(source); + this.comparator = comparator; + this.flag = flag; + } + + @Override + public Iterator iterator() { + return new MinMaxIterator(source.iterator(), comparator, flag); + } + + static final class MinMaxIterator extends IxSourceIterator { + + final Comparator comparator; + + final int flag; + + MinMaxIterator(Iterator it, Comparator comparator, int flag) { + super(it); + this.comparator = comparator; + this.flag = flag; + } + + @Override + protected boolean moveNext() { + T v; + + Iterator it = this.it; + + if (!it.hasNext()) { + done = true; + return false; + } + + v = it.next(); + + Comparator f = comparator; + int g = flag; + + while (it.hasNext()) { + T w = it.next(); + if (f.compare(v, w) * g > 0) { + v = w; + } + } + + value = v; + hasValue = true; + done = true; + return true; + } + + } + +} diff --git a/src/main/java/ix/IxOrderBy.java b/src/main/java/ix/IxOrderBy.java new file mode 100644 index 0000000..b77e66a --- /dev/null +++ b/src/main/java/ix/IxOrderBy.java @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxOrderBy extends IxSource { + + final IxFunction keySelector; + + final Comparator comparator; + + final int flag; + + IxOrderBy(Iterable source, IxFunction keySelector, Comparator comparator, int flag) { + super(source); + this.keySelector = keySelector; + this.comparator = comparator; + this.flag = flag; + } + + @Override + public Iterator iterator() { + return new OrderByIterator(source.iterator(), keySelector, comparator, flag); + } + + static final class OrderByIterator extends IxSourceIterator implements Comparator { + + final IxFunction keySelector; + + final Comparator comparator; + + final int flag; + + List values; + + int index; + + OrderByIterator(Iterator it, IxFunction keySelector, Comparator comparator, int flag) { + super(it); + this.keySelector = keySelector; + this.comparator = comparator; + this.flag = flag; + } + + @Override + protected boolean moveNext() { + + List list = values; + + if (list == null) { + list = new ArrayList(); + + Iterator it = this.it; + + while (it.hasNext()) { + list.add(it.next()); + } + + if (list.isEmpty()) { + done = true; + return false; + } + + Collections.sort(list, this); + + values = list; + } + + int i = index; + if (i != list.size()) { + index = i + 1; + value = list.get(i); + list.set(i, null); + hasValue = true; + return true; + } + done = true; + return false; + } + + @Override + public int compare(T o1, T o2) { + K k1 = keySelector.apply(o1); + K k2 = keySelector.apply(o2); + return comparator.compare(k1, k2) * flag; + } + } + +} diff --git a/src/main/java/ix/IxOrderedMergeArray.java b/src/main/java/ix/IxOrderedMergeArray.java new file mode 100644 index 0000000..ce895fa --- /dev/null +++ b/src/main/java/ix/IxOrderedMergeArray.java @@ -0,0 +1,142 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +/** + * Merges an array of Iterable items by picking the smallest from them + * with the help of a Comparator. + * + * @param the value type + */ +final class IxOrderedMergeArray extends Ix { + + final Iterable[] sources; + + final Comparator comparator; + + IxOrderedMergeArray(Iterable[] sources, Comparator comparator) { + this.sources = sources; + this.comparator = comparator; + } + + @Override + public Iterator iterator() { + Iterable[] all = sources; + int n = all.length; + @SuppressWarnings("unchecked") + Iterator[] srcs = new Iterator[n]; + for (int i = 0; i < n; i++) { + srcs[i] = all[i].iterator(); + } + return new OrderedMergeIterator(srcs, n, comparator); + } + + static final class OrderedMergeIterator implements Iterator { + + final Iterator[] sources; + + final Comparator comparator; + + final int n; + + final Object[] latest; + + static final Object EMPTY = new Object(); + + static final Object DONE = new Object(); + + boolean done; + + int index; + + OrderedMergeIterator(Iterator[] sources, int n, Comparator comparator) { + this.sources = sources; + this.n = n; + this.latest = new Object[n]; + Arrays.fill(latest, EMPTY); + this.comparator = comparator; + this.index = -1; + } + + @SuppressWarnings("unchecked") + @Override + public boolean hasNext() { + int i = index; + if (i < 0) { + if (done) { + return false; + } + int count = n; + Object[] vs = latest; + int d = 0; + int f = -1; + T min = null; + for (int j = 0; j < count; j++) { + Object o = vs[j]; + if (o == DONE) { + d++; + continue; + } else + if (o == EMPTY) { + Iterator src = sources[j]; + if (src.hasNext()) { + o = src.next(); + vs[j] = o; + } else { + d++; + vs[j] = DONE; + continue; + } + } + + if (f < 0 || comparator.compare(min, (T)o) > 0) { + f = j; + min = (T)o; + } + } + + if (d == count) { + done = true; + return false; + } + + index = f; + } + return true; + } + + @Override + public T next() { + if (hasNext()) { + int i = index; + index = -1; + @SuppressWarnings("unchecked") + T v = (T)latest[i]; + latest[i] = EMPTY; + return v; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxOrderedMergeIterable.java b/src/main/java/ix/IxOrderedMergeIterable.java new file mode 100644 index 0000000..d5af595 --- /dev/null +++ b/src/main/java/ix/IxOrderedMergeIterable.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import ix.IxOrderedMergeArray.OrderedMergeIterator; + +/** + * Merges an array of Iterable items by picking the smallest from them + * with the help of a Comparator. + * + * @param the value type + */ +final class IxOrderedMergeIterable extends Ix { + + final Iterable> sources; + + final Comparator comparator; + + IxOrderedMergeIterable(Iterable> sources, Comparator comparator) { + this.sources = sources; + this.comparator = comparator; + } + + @Override + public Iterator iterator() { + @SuppressWarnings("unchecked") + Iterator[] srcs = new Iterator[8]; + int n = 0; + + for (Iterable iter : sources) { + if (n == srcs.length) { + srcs = Arrays.copyOf(srcs, n + (n >> 2)); + } + srcs[n++] = iter.iterator(); + } + + return new OrderedMergeIterator(srcs, n, comparator); + } +} diff --git a/src/main/java/ix/IxPredicate.java b/src/main/java/ix/IxPredicate.java new file mode 100644 index 0000000..3b81236 --- /dev/null +++ b/src/main/java/ix/IxPredicate.java @@ -0,0 +1,30 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with one input value and a boolean return value. + * @param the input value type + */ +public interface IxPredicate { + /** + * Applies a function to the input value and returns a boolean value. + * @param t the input value + * @return the output boolean + */ + boolean test(T t); +} diff --git a/src/main/java/ix/IxPredicate2.java b/src/main/java/ix/IxPredicate2.java new file mode 100644 index 0000000..1f39934 --- /dev/null +++ b/src/main/java/ix/IxPredicate2.java @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with two input values and a boolean return value. + * @param the first input value type + * @param the second input value + */ +public interface IxPredicate2 { + /** + * Applies a function to the input value and returns a boolean value. + * @param t the first input value + * @param u the second input value + * @return the output boolean + */ + boolean test(T t, U u); +} diff --git a/src/main/java/ix/IxPublish.java b/src/main/java/ix/IxPublish.java new file mode 100644 index 0000000..4570ce0 --- /dev/null +++ b/src/main/java/ix/IxPublish.java @@ -0,0 +1,39 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxPublish extends IxSource { + + Iterator current; + + IxPublish(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + Iterator c = current; + if (c == null) { + c = source.iterator(); + current = c; + } + return c; + } + +} diff --git a/src/main/java/ix/IxPublishSelector.java b/src/main/java/ix/IxPublishSelector.java new file mode 100644 index 0000000..f03130e --- /dev/null +++ b/src/main/java/ix/IxPublishSelector.java @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxPublishSelector extends IxSource { + + final IxFunction, ? extends Iterable> selector; + + IxPublishSelector(Iterable source, IxFunction, ? extends Iterable> selector) { + super(source); + this.selector = selector; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + + return (Iterator)selector.apply(new PublishSelectorIterable(source.iterator())).iterator(); + } + + static final class PublishSelectorIterable extends Ix { + + final Iterator source; + + PublishSelectorIterable(Iterator source) { + this.source = source; + } + + @Override + public Iterator iterator() { + return source; + } + } +} diff --git a/src/main/java/ix/IxRange.java b/src/main/java/ix/IxRange.java new file mode 100644 index 0000000..06ff9a9 --- /dev/null +++ b/src/main/java/ix/IxRange.java @@ -0,0 +1,69 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxRange extends Ix { + + final int start; + + final int end; + + IxRange(int start, int count) { + this.start = start; + this.end = start + count; + } + + @Override + public Iterator iterator() { + return new RangeIterator(start, end); + } + + static final class RangeIterator implements Iterator { + + final int end; + + int index; + + RangeIterator(int start, int end) { + this.index = start; + this.end = end; + } + + @Override + public boolean hasNext() { + return index != end; + } + + @Override + public Integer next() { + int i = index; + if (i != end) { + index = i + 1; + return i; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/src/main/java/ix/IxReadOnly.java b/src/main/java/ix/IxReadOnly.java new file mode 100644 index 0000000..6850d90 --- /dev/null +++ b/src/main/java/ix/IxReadOnly.java @@ -0,0 +1,90 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +/** + * Suppress or throw when the remove() is called. + * + * @param the value type + */ +final class IxReadOnly extends IxSource { + + final boolean silent; + + IxReadOnly(Iterable source, boolean silent) { + super(source); + this.silent = silent; + } + + @Override + public Iterator iterator() { + if (silent) { + return new ReadOnlySilentIterator(source.iterator()); + } + return new ReadOnlyThrowingIterator(source.iterator()); + } + + static final class ReadOnlySilentIterator implements Iterator { + + final Iterator source; + + ReadOnlySilentIterator(Iterator source) { + this.source = source; + } + + @Override + public boolean hasNext() { + return source.hasNext(); + } + + @Override + public T next() { + return source.next(); + } + + @Override + public void remove() { + // deliberately ignored + } + } + + static final class ReadOnlyThrowingIterator implements Iterator { + + final Iterator source; + + ReadOnlyThrowingIterator(Iterator source) { + this.source = source; + } + + @Override + public boolean hasNext() { + return source.hasNext(); + } + + @Override + public T next() { + return source.next(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxReduce.java b/src/main/java/ix/IxReduce.java new file mode 100644 index 0000000..aa58af7 --- /dev/null +++ b/src/main/java/ix/IxReduce.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxReduce extends IxSource { + + final IxSupplier initialFactory; + + final IxFunction2 reducer; + + IxReduce(Iterable source, IxSupplier initialFactory, IxFunction2 reducer) { + super(source); + this.initialFactory = initialFactory; + this.reducer = reducer; + } + + @Override + public Iterator iterator() { + return new CollectorIterator(source.iterator(), reducer, initialFactory.get()); + } + + static final class CollectorIterator extends IxSourceIterator { + + final IxFunction2 reducer; + + CollectorIterator(Iterator it, IxFunction2 reducer, C value) { + super(it); + this.reducer = reducer; + this.value = value; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + IxFunction2 f = reducer; + + C c = value; + + while (it.hasNext()) { + c = f.apply(c, it.next()); + } + + value = c; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxRemove.java b/src/main/java/ix/IxRemove.java new file mode 100644 index 0000000..fe99cd8 --- /dev/null +++ b/src/main/java/ix/IxRemove.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxRemove extends IxSource { + + final IxPredicate predicate; + + IxRemove(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new RemoveIterator(source.iterator(), predicate); + } + + static final class RemoveIterator extends IxSourceIterator { + final IxPredicate predicate; + + RemoveIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + + for (;;) { + if (!it.hasNext()) { + done = true; + return false; + } + + T v = it.next(); + + if (predicate.test(v)) { + it.remove(); + } else { + value = v; + hasValue = true; + return true; + } + } + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxRepeat.java b/src/main/java/ix/IxRepeat.java new file mode 100644 index 0000000..a30b998 --- /dev/null +++ b/src/main/java/ix/IxRepeat.java @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxRepeat extends Ix implements Iterator { + + final T value; + + IxRepeat(T value) { + this.value = value; + } + + @Override + public Iterator iterator() { + return this; + } + + @Override + public boolean hasNext() { + return true; + } + + @Override + public T next() { + return value; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/ix/IxRepeatCallable.java b/src/main/java/ix/IxRepeatCallable.java new file mode 100644 index 0000000..1587466 --- /dev/null +++ b/src/main/java/ix/IxRepeatCallable.java @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; +import java.util.concurrent.Callable; + +/** + * Repeatedly call a Callable indefinitely. + * + * @param the value type + */ +final class IxRepeatCallable extends Ix implements Iterator { + + final Callable callable; + + IxRepeatCallable(Callable callable) { + this.callable = callable; + } + + @Override + public Iterator iterator() { + return this; + } + + @Override + public boolean hasNext() { + return true; + } + + @Override + public T next() { + return checkedCall(callable); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/ix/IxRepeatCount.java b/src/main/java/ix/IxRepeatCount.java new file mode 100644 index 0000000..c974425 --- /dev/null +++ b/src/main/java/ix/IxRepeatCount.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxRepeatCount extends Ix { + + final T value; + + final long count; + + IxRepeatCount(T value, long count) { + this.value = value; + this.count = count; + } + + @Override + public Iterator iterator() { + return new RepeatCountIterator(value, count); + } + + static final class RepeatCountIterator implements Iterator { + + final T value; + + long count; + + RepeatCountIterator(T value, long count) { + this.value = value; + this.count = count; + } + + @Override + public boolean hasNext() { + return count != 0L; + } + + @Override + public T next() { + long c = count; + if (c != 0L) { + count = c - 1; + return value; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/main/java/ix/IxRepeatPredicate.java b/src/main/java/ix/IxRepeatPredicate.java new file mode 100644 index 0000000..8c21013 --- /dev/null +++ b/src/main/java/ix/IxRepeatPredicate.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxRepeatPredicate extends Ix { + + final T value; + + final long count; + + final IxBooleanSupplier stopPredicate; + + IxRepeatPredicate(T value, long count, IxBooleanSupplier stopPredicate) { + this.value = value; + this.stopPredicate = stopPredicate; + this.count = count; + } + + @Override + public Iterator iterator() { + return new RepeatPredicateIterator(value, count, stopPredicate); + } + + static final class RepeatPredicateIterator extends IxBaseIterator { + + final T valueToRepeat; + + long count; + + final IxBooleanSupplier stopPredicate; + + RepeatPredicateIterator(T value, long count, IxBooleanSupplier stopPredicate) { + this.valueToRepeat = value; + this.stopPredicate = stopPredicate; + this.count = count; + } + + @Override + protected boolean moveNext() { + long c = count--; + if (c != 0L && !stopPredicate.getAsBoolean()) { + value = valueToRepeat; + hasValue = true; + return true; + } + done = true; + return false; + } + + } +} diff --git a/src/main/java/ix/IxReplay.java b/src/main/java/ix/IxReplay.java new file mode 100644 index 0000000..9f588ba --- /dev/null +++ b/src/main/java/ix/IxReplay.java @@ -0,0 +1,84 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxReplay extends IxSource { + + List list; + + Iterator it; + + IxReplay(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + if (it == null) { + it = source.iterator(); + } + return new ReplayIterator(this); + } + + boolean moveNext() { + if (!it.hasNext()) { + return false; + } + + List list = this.list; + if (list == null) { + list = new ArrayList(); + this.list = list; + } + + list.add(it.next()); + return true; + } + + static final class ReplayIterator extends IxBaseIterator { + + final IxReplay parent; + + int index; + + ReplayIterator(IxReplay parent) { + this.parent = parent; + } + + @Override + protected boolean moveNext() { + int i = index; + List list = parent.list; + + if (list == null || i == list.size()) { + if (!parent.moveNext()) { + done = true; + return false; + } + if (list == null) { + list = parent.list; + } + } + index = i + 1; + value = list.get(i); + hasValue = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxReplaySelector.java b/src/main/java/ix/IxReplaySelector.java new file mode 100644 index 0000000..943a835 --- /dev/null +++ b/src/main/java/ix/IxReplaySelector.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxReplaySelector extends IxSource { + + final IxFunction, ? extends Iterable> selector; + + IxReplaySelector(Iterable source, IxFunction, ? extends Iterable> selector) { + super(source); + this.selector = selector; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + + return (Iterator)selector.apply(new IxReplay(source)).iterator(); + } +} diff --git a/src/main/java/ix/IxReplaySize.java b/src/main/java/ix/IxReplaySize.java new file mode 100644 index 0000000..edfc5e5 --- /dev/null +++ b/src/main/java/ix/IxReplaySize.java @@ -0,0 +1,104 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxReplaySize extends IxSource { + + final int maxSize; + + Iterator it; + + Node head; + + Node tail; + + int size; + + IxReplaySize(Iterable source, int maxSize) { + super(source); + this.maxSize = maxSize; + this.head = this.tail = new Node(null); + } + + @Override + public Iterator iterator() { + if (it == null) { + it = source.iterator(); + } + return new ReplaySizeIterator(this, head); + } + + boolean moveNext() { + if (!it.hasNext()) { + return false; + } + + Node n = new Node(it.next()); + tail.next = n; + tail = n; + + int s = size; + if (s != maxSize) { + size = s + 1; + } else { + head = head.next; + } + return true; + } + + static final class Node { + final T value; + + Node next; + + Node(T value) { + this.value = value; + } + } + + static final class ReplaySizeIterator extends IxBaseIterator { + final IxReplaySize parent; + + Node node; + + ReplaySizeIterator(IxReplaySize parent, Node node) { + this.parent = parent; + this.node = node; + } + + @Override + protected boolean moveNext() { + Node n = node; + + if (n.next == null) { + if (!parent.moveNext()) { + done = true; + return false; + } + } + n = n.next; + + value = n.value; + hasValue = true; + node = n; + + return true; + } + } +} diff --git a/src/main/java/ix/internal/operators/ShareSelectorIterable.java b/src/main/java/ix/IxReplaySizeSelector.java similarity index 51% rename from src/main/java/ix/internal/operators/ShareSelectorIterable.java rename to src/main/java/ix/IxReplaySizeSelector.java index 7beeab8..fa52393 100644 --- a/src/main/java/ix/internal/operators/ShareSelectorIterable.java +++ b/src/main/java/ix/IxReplaySizeSelector.java @@ -1,37 +1,40 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -import rx.functions.Func1; - -public final class ShareSelectorIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func1, ? extends Iterable> selector; - - public ShareSelectorIterable(Iterable source, - Func1, ? extends Iterable> selector) { - this.source = source; - this.selector = selector; - } - - @Override - public Iterator iterator() { - return selector.call(Interactive.share(source)).iterator(); - } -} \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxReplaySizeSelector extends IxSource { + + final int maxSize; + + final IxFunction, ? extends Iterable> selector; + + IxReplaySizeSelector(Iterable source, int maxSize, + IxFunction, ? extends Iterable> selector) { + super(source); + this.maxSize = maxSize; + this.selector = selector; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + + return (Iterator)selector.apply(new IxReplaySize(source, maxSize)).iterator(); + } +} diff --git a/src/main/java/ix/IxRetain.java b/src/main/java/ix/IxRetain.java new file mode 100644 index 0000000..d467853 --- /dev/null +++ b/src/main/java/ix/IxRetain.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxRetain extends IxSource { + + final IxPredicate predicate; + + IxRetain(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new RetainIterator(source.iterator(), predicate); + } + + static final class RetainIterator extends IxSourceIterator { + final IxPredicate predicate; + + RetainIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + + for (;;) { + if (!it.hasNext()) { + done = true; + return false; + } + + T v = it.next(); + + if (predicate.test(v)) { + value = v; + hasValue = true; + return true; + } else { + it.remove(); + } + } + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxReverse.java b/src/main/java/ix/IxReverse.java new file mode 100644 index 0000000..6faf720 --- /dev/null +++ b/src/main/java/ix/IxReverse.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxReverse extends IxSource { + + IxReverse(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new ReverseIterator(source.iterator()); + } + + static final class ReverseIterator extends IxSourceIterator { + + List list; + + int index; + + ReverseIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + List list = this.list; + + if (list == null) { + list = new ArrayList(); + this.list = list; + while (it.hasNext()) { + list.add(it.next()); + } + index = list.size(); + } + + int i = index; + if (i == 0) { + done = true; + return false; + } + value = list.get(i - 1); + hasValue = true; + index = i - 1; + return true; + } + } +} diff --git a/src/main/java/ix/IxScalarCallable.java b/src/main/java/ix/IxScalarCallable.java new file mode 100644 index 0000000..dfbcefa --- /dev/null +++ b/src/main/java/ix/IxScalarCallable.java @@ -0,0 +1,30 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.concurrent.Callable; + +/** + * Marker interface to indicate a source that has exactly one constant + * value, available for assembly-time optimizations. + * @param the value type + */ +public interface IxScalarCallable extends Callable { + + @Override + T call(); +} diff --git a/src/main/java/ix/IxScan.java b/src/main/java/ix/IxScan.java new file mode 100644 index 0000000..e618c34 --- /dev/null +++ b/src/main/java/ix/IxScan.java @@ -0,0 +1,79 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxScan extends IxSource { + + final IxFunction2 scanner; + + IxScan(Iterable source, IxFunction2 scanner) { + super(source); + this.scanner = scanner; + } + + @Override + public Iterator iterator() { + return new ScanIterator(source.iterator(), scanner); + } + + static final class ScanIterator extends IxSourceIterator { + + final IxFunction2 scanner; + + T last; + + boolean once; + + ScanIterator(Iterator it, IxFunction2 scanner) { + super(it); + this.scanner = scanner; + } + + @Override + protected boolean moveNext() { + if (!once) { + if (it.hasNext()) { + once = true; + T v = it.next(); + + last = v; + value = v; + hasValue = true; + return true; + } + done = true; + return false; + } + + if (it.hasNext()) { + T v = it.next(); + + v = scanner.apply(last, v); + last = v; + value = v; + hasValue = true; + return true; + } + + last = null; + done = true; + return false; + } + } +} diff --git a/src/main/java/ix/IxScanSeed.java b/src/main/java/ix/IxScanSeed.java new file mode 100644 index 0000000..d02bbf3 --- /dev/null +++ b/src/main/java/ix/IxScanSeed.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxScanSeed extends IxSource { + + final IxSupplier seed; + + final IxFunction2 scanner; + + IxScanSeed(Iterable source, IxSupplier seed, IxFunction2 scanner) { + super(source); + this.seed = seed; + this.scanner = scanner; + } + + @Override + public Iterator iterator() { + return new ScanSeedIterator(source.iterator(), seed.get(), scanner); + } + + static final class ScanSeedIterator extends IxSourceIterator { + final IxFunction2 scanner; + + R accumulator; + + boolean once; + + ScanSeedIterator(Iterator it, R accumulator, IxFunction2 scanner) { + super(it); + this.accumulator = accumulator; + this.scanner = scanner; + } + + @Override + protected boolean moveNext() { + if (!once) { + once = true; + value = accumulator; + hasValue = true; + return true; + } + + if (it.hasNext()) { + + R v = scanner.apply(accumulator, it.next()); + + accumulator = v; + value = v; + hasValue = true; + return true; + } + + accumulator = null; + done = true; + return false; + } + } + +} diff --git a/src/main/java/ix/IxSequenceEqual.java b/src/main/java/ix/IxSequenceEqual.java new file mode 100644 index 0000000..b26f1e5 --- /dev/null +++ b/src/main/java/ix/IxSequenceEqual.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSequenceEqual extends IxSource { + + final Iterable other; + + final IxPredicate2 comparer; + + IxSequenceEqual(Iterable source, Iterable other, + IxPredicate2 comparer) { + super(source); + this.other = other; + this.comparer = comparer; + } + + @Override + public Iterator iterator() { + return new SequenceEqualIterator(source.iterator(), other.iterator(), comparer); + } + + static final class SequenceEqualIterator extends IxSourceIterator { + + final Iterator other; + + final IxPredicate2 comparer; + + SequenceEqualIterator(Iterator it, Iterator other, + IxPredicate2 comparer) { + super(it); + this.other = other; + this.comparer = comparer; + } + + @Override + protected boolean moveNext() { + + Iterator it2 = it; + + while (it2.hasNext()) { + + T v = it2.next(); + + if (other.hasNext()) { + + T u = other.next(); + + if (!comparer.test(v, u)) { + + value = false; + hasValue = true; + done = true; + return true; + } + } else { + value = false; + hasValue = true; + done = true; + return true; + } + } + if (other.hasNext()) { + value = false; + hasValue = true; + done = true; + return true; + } + + value = true; + hasValue = true; + done = true; + return true; + } + + + } + +} diff --git a/src/main/java/ix/IxSkip.java b/src/main/java/ix/IxSkip.java new file mode 100644 index 0000000..ef56e1f --- /dev/null +++ b/src/main/java/ix/IxSkip.java @@ -0,0 +1,71 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSkip extends IxSource { + + final int n; + + IxSkip(Iterable source, int n) { + super(source); + this.n = n; + } + + @Override + public Iterator iterator() { + return new SkipIterator(source.iterator(), n); + } + + static final class SkipIterator extends IxSourceIterator { + + int n; + + SkipIterator(Iterator it, int n) { + super(it); + this.n = n; + } + @Override + protected boolean moveNext() { + Iterator it = this.it; + int n = this.n; + + if (n != 0) { + while (n != 0) { + if (it.hasNext()) { + it.next(); + } else { + done = true; + return false; + } + n--; + } + this.n = 0; + } + if (it.hasNext()) { + value = it.next(); + hasValue = true; + return true; + } + done = true; + return false; + } + + + } +} diff --git a/src/main/java/ix/IxSkipLast.java b/src/main/java/ix/IxSkipLast.java new file mode 100644 index 0000000..09e4aa2 --- /dev/null +++ b/src/main/java/ix/IxSkipLast.java @@ -0,0 +1,78 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSkipLast extends IxSource { + + final int n; + + IxSkipLast(Iterable source, int n) { + super(source); + this.n = n; + } + + @Override + public Iterator iterator() { + return new SkipLastIterator(source.iterator(), n); + } + + static final class SkipLastIterator extends IxSourceQueuedIterator { + + final int n; + + int size; + + SkipLastIterator(Iterator it, int n) { + super(it); + this.n = n; + } + + @Override + protected boolean moveNext() { + int s = size; + int n = this.n; + + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + + if (s != n) { + while (s != n) { + offer(toObject(it.next())); + if (!it.hasNext()) { + done = true; + return false; + } + s++; + } + size = s; + } + + value = fromObject(poll()); + offer(toObject(it.next())); + + hasValue = true; + + return true; + } + + } +} diff --git a/src/main/java/ix/IxSkipWhile.java b/src/main/java/ix/IxSkipWhile.java new file mode 100644 index 0000000..158ea62 --- /dev/null +++ b/src/main/java/ix/IxSkipWhile.java @@ -0,0 +1,78 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSkipWhile extends IxSource { + + final IxPredicate predicate; + + IxSkipWhile(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new SkipWhileIterator(source.iterator(), predicate); + } + + static final class SkipWhileIterator extends IxSourceIterator { + + final IxPredicate predicate; + + boolean passThrough; + + SkipWhileIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + if (passThrough) { + if (it.hasNext()) { + hasValue = true; + value = it.next(); + return true; + } + done = true; + return false; + } + + while (it.hasNext()) { + T v = it.next(); + if (!predicate.test(v)) { + passThrough = true; + hasValue = true; + value = v; + return true; + } + } + + done = true; + return false; + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxSource.java b/src/main/java/ix/IxSource.java new file mode 100644 index 0000000..f3a0364 --- /dev/null +++ b/src/main/java/ix/IxSource.java @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * Abstract base class for Ix operators that take a source Iterable. + * @param the source value type + * @param the result value type + */ +abstract class IxSource extends Ix { + + protected final Iterable source; + + IxSource(Iterable source) { + this.source = source; + } + +} diff --git a/src/main/java/ix/CloseableIterator.java b/src/main/java/ix/IxSourceIterator.java similarity index 55% rename from src/main/java/ix/CloseableIterator.java rename to src/main/java/ix/IxSourceIterator.java index bb36961..da541fb 100644 --- a/src/main/java/ix/CloseableIterator.java +++ b/src/main/java/ix/IxSourceIterator.java @@ -1,41 +1,36 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import java.util.Iterator; -import rx.Subscription; - -/** - * An iterator which supports a close() method. Usage: - *

- * CloseableIterator<T> it = citerable.iterator();
- * try {
- *     while (it.hasNext()) {
- *         doSomething(it.next());
- *         if (condition) {
- *             break;
- *         }
- *     }
- * } finally {
- *     it.close();
- * }
- * it.close();
- * 
- * @param the element type - */ -public interface CloseableIterator extends Iterator, Subscription { - -} +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +/** + * A base iterator that references an upstream iterator and manages + * the state between hasNext() and the next() calls; plus defines + * the remove() to throw UnsupportedOperationException. + * @param the source value type + * @param the result value type + */ +public abstract class IxSourceIterator extends IxBaseIterator { + + /** The upstream's iterator. */ + protected final Iterator it; + + public IxSourceIterator(Iterator it) { + this.it = it; + } +} diff --git a/src/main/java/ix/IxSourceQueuedIterator.java b/src/main/java/ix/IxSourceQueuedIterator.java new file mode 100644 index 0000000..c1584a5 --- /dev/null +++ b/src/main/java/ix/IxSourceQueuedIterator.java @@ -0,0 +1,146 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +/** + * A base iterator that extends a custom ArrayDeque, references an upstream iterator + * and manages the state between hasNext() and the next() calls; plus defines + * the remove() to throw UnsupportedOperationException. + * @param the source value type + * @param the queued element types + * @param the result value type + */ +public abstract class IxSourceQueuedIterator +extends IxSourceIterator { + + protected static final Object NULL = new Object(); + + private Object[] array; + + private int producerIndex; + + private int consumerIndex; + + public IxSourceQueuedIterator(Iterator it) { + super(it); + } + + /** + * Cast the value into an object and turn + * a null value into a sentinel value. + * @param value the value to cast + * @return the cast value, not null + * @see IxSourceQueuedIterator#fromObject(Object) + */ + protected final Object toObject(U value) { + return value != null ? value : NULL; + } + + /** + * Cast the object back to a typed value. + * @param value the value to cast back + * @return the typed value, maybe null + */ + @SuppressWarnings("unchecked") + protected final U fromObject(Object value) { + return value == NULL ? null : (U)value; + } + + protected final boolean offer(Object value) { + if (value == null) { + throw new NullPointerException("The queue doesn't support null values."); + } + Object[] a = array; + if (a == null) { + a = new Object[8]; + array = a; + } + int mask = a.length - 1; + int pi = producerIndex; + + int offset = pi & mask; + if (a[offset] != null) { + int newLen = mask * 2 + 2; + Object[] b = new Object[newLen]; + System.arraycopy(a, offset, b, 0, mask + 1 - offset); + System.arraycopy(a, 0, b, offset, offset); + b[mask + 1] = value; + + array = b; + consumerIndex = 0; + producerIndex = mask + 2; + } else { + a[offset] = value; + producerIndex = pi + 1; + } + return true; + } + + protected final Object poll() { + Object[] a = array; + if (a != null) { + int m = a.length - 1; + int ci = consumerIndex; + int offset = ci & m; + + Object v = a[offset]; + if (v != null) { + a[offset] = null; + consumerIndex = ci + 1; + } + return v; + } + return null; + } + + protected final Object peek() { + Object[] a = array; + if (a != null) { + int m = a.length - 1; + int ci = consumerIndex; + int offset = ci & m; + + return a[offset]; + } + return null; + } + + protected final boolean isEmpty() { + return consumerIndex == producerIndex; + } + + protected final void clear() { + array = null; + consumerIndex = 0; + producerIndex = 0; + } + + protected final void foreach(IxConsumer2 action, S state) { + Object[] a = array; + if (a != null) { + int m = a.length - 1; + int pi = producerIndex; + for (int ci = consumerIndex; ci != pi; ci++) { + int offset = ci & m; + Object o = a[offset]; + action.accept(fromObject(o), state); + } + } + } +} diff --git a/src/main/java/ix/IxSplit.java b/src/main/java/ix/IxSplit.java new file mode 100644 index 0000000..117e8d6 --- /dev/null +++ b/src/main/java/ix/IxSplit.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSplit extends Ix { + + final String string; + + final String by; + + IxSplit(String string, String by) { + this.string = string; + this.by = by; + } + + @Override + public Iterator iterator() { + return new SplitIterator(string, by); + } + + static final class SplitIterator extends IxBaseIterator { + final String string; + + final String by; + + int index; + + SplitIterator(String string, String by) { + this.string = string; + this.by = by; + } + + @Override + protected boolean moveNext() { + int i = index; + int j = string.indexOf(by, i); + + if (j < 0) { + value = string.substring(i); + hasValue = true; + done = true; + return true; + } + + hasValue = true; + index = j + by.length(); + value = string.substring(i, j); + return true; + } + } +} diff --git a/src/main/java/ix/IxSumInt.java b/src/main/java/ix/IxSumInt.java new file mode 100644 index 0000000..bb312d6 --- /dev/null +++ b/src/main/java/ix/IxSumInt.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSumInt extends IxSource { + + IxSumInt(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new SumIntIterator(source.iterator()); + } + + static final class SumIntIterator extends IxSourceIterator { + + SumIntIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + int sum = it.next(); + + while (it.hasNext()) { + sum += it.next(); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxSumLong.java b/src/main/java/ix/IxSumLong.java new file mode 100644 index 0000000..6e9f7ab --- /dev/null +++ b/src/main/java/ix/IxSumLong.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSumLong extends IxSource { + + IxSumLong(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return new SumLongIterator(source.iterator()); + } + + static final class SumLongIterator extends IxSourceIterator { + + SumLongIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + if (!it.hasNext()) { + done = true; + return false; + } + long sum = it.next(); + + while (it.hasNext()) { + sum += it.next(); + } + + value = sum; + hasValue = true; + done = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxSupplier.java b/src/main/java/ix/IxSupplier.java new file mode 100644 index 0000000..23df3fb --- /dev/null +++ b/src/main/java/ix/IxSupplier.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +/** + * A function callback with no inputs and one output value. + * @param the output value type + */ +public interface IxSupplier { + /** + * Calls the function which returns a value. + * @return the output value + */ + R get(); +} diff --git a/src/main/java/ix/IxSwitchIfEmpty.java b/src/main/java/ix/IxSwitchIfEmpty.java new file mode 100644 index 0000000..aa4d6dd --- /dev/null +++ b/src/main/java/ix/IxSwitchIfEmpty.java @@ -0,0 +1,99 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxSwitchIfEmpty extends IxSource { + + final Iterable other; + + IxSwitchIfEmpty(Iterable source, Iterable other) { + super(source); + this.other = other; + } + + @Override + public Iterator iterator() { + return new SwitchIfEmptyIterator(source.iterator(), other); + } + + static final class SwitchIfEmptyIterator extends IxSourceIterator { + + final Iterable other; + + Iterator otherIterator; + + boolean nonEmpty; + + SwitchIfEmptyIterator(Iterator it, Iterable other) { + super(it); + this.other = other; + } + + @Override + protected boolean moveNext() { + Iterator ot = otherIterator; + if (ot != null) { + if (ot.hasNext()) { + value = ot.next(); + hasValue = true; + return true; + } + done = true; + return false; + } + + if (nonEmpty) { + if (it.hasNext()) { + value = it.next(); + hasValue = true; + return true; + } + done = true; + return false; + } + + if (it.hasNext()) { + nonEmpty = true; + value = it.next(); + hasValue = true; + return true; + } + + ot = other.iterator(); + otherIterator = ot; + if (ot.hasNext()) { + value = ot.next(); + hasValue = true; + return true; + } + done = true; + return false; + } + + @Override + public void remove() { + Iterator ot = otherIterator; + if (ot != null) { + ot.remove(); + } else { + it.remove(); + } + } + } +} diff --git a/src/main/java/ix/IxTake.java b/src/main/java/ix/IxTake.java new file mode 100644 index 0000000..698171c --- /dev/null +++ b/src/main/java/ix/IxTake.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxTake extends IxSource { + + final int n; + + IxTake(Iterable source, int n) { + super(source); + this.n = n; + } + + @Override + public Iterator iterator() { + return new TakeIterator(source.iterator(), n); + } + + static final class TakeIterator extends IxSourceIterator { + + int n; + + TakeIterator(Iterator it, int n) { + super(it); + this.n = n; + } + + @Override + protected boolean moveNext() { + int n = this.n; + if (n == 0 || !it.hasNext()) { + done = true; + return false; + } + + value = it.next(); + hasValue = true; + this.n = n - 1; + + return true; + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxTakeLast.java b/src/main/java/ix/IxTakeLast.java new file mode 100644 index 0000000..278a354 --- /dev/null +++ b/src/main/java/ix/IxTakeLast.java @@ -0,0 +1,72 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxTakeLast extends IxSource { + + final int n; + + IxTakeLast(Iterable source, int n) { + super(source); + this.n = n; + } + + @Override + public Iterator iterator() { + return new TakeLastIterator(source.iterator(), n); + } + + static final class TakeLastIterator extends IxSourceQueuedIterator { + + int n; + + TakeLastIterator(Iterator it, int n) { + super(it); + this.n = n; + } + + @Override + protected boolean moveNext() { + + int n = this.n; + if (n != 0) { + Iterator it = this.it; + while (it.hasNext()) { + if (n == 0) { + poll(); + } else { + n--; + } + offer(toObject(it.next())); + } + this.n = n; + } + + Object o = poll(); + if (o != null) { + value = fromObject(o); + hasValue = true; + return true; + } + done = true; + return false; + } + } + +} diff --git a/src/main/java/ix/IxTakeUntil.java b/src/main/java/ix/IxTakeUntil.java new file mode 100644 index 0000000..ff89ad4 --- /dev/null +++ b/src/main/java/ix/IxTakeUntil.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxTakeUntil extends IxSource { + + final IxPredicate predicate; + + IxTakeUntil(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new TakeUntilIterator(source.iterator(), predicate); + } + + static final class TakeUntilIterator extends IxSourceIterator { + + final IxPredicate predicate; + + TakeUntilIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + if (it.hasNext()) { + T v = it.next(); + value = v; + hasValue = true; + if (predicate.test(v)) { + done = true; + } + return true; + } + done = true; + return false; + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxTakeWhile.java b/src/main/java/ix/IxTakeWhile.java new file mode 100644 index 0000000..5da9258 --- /dev/null +++ b/src/main/java/ix/IxTakeWhile.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxTakeWhile extends IxSource { + + final IxPredicate predicate; + + IxTakeWhile(Iterable source, IxPredicate predicate) { + super(source); + this.predicate = predicate; + } + + @Override + public Iterator iterator() { + return new TakeWhileIterator(source.iterator(), predicate); + } + + static final class TakeWhileIterator extends IxSourceIterator { + + final IxPredicate predicate; + + TakeWhileIterator(Iterator it, IxPredicate predicate) { + super(it); + this.predicate = predicate; + } + + @Override + protected boolean moveNext() { + if (it.hasNext()) { + T v = it.next(); + if (!predicate.test(v)) { + done = true; + return false; + } + value = v; + hasValue = true; + return true; + } + done = true; + return false; + } + + @Override + public void remove() { + it.remove(); + } + } + +} diff --git a/src/main/java/ix/IxToMap.java b/src/main/java/ix/IxToMap.java new file mode 100644 index 0000000..f9c3527 --- /dev/null +++ b/src/main/java/ix/IxToMap.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxToMap extends IxSource> { + + final IxFunction keySelector; + + final IxFunction valueSelector; + + IxToMap(Iterable source, IxFunction keySelector, IxFunction valueSelector) { + super(source); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + } + + @Override + public Iterator> iterator() { + return new ToMapIterator(source.iterator(), keySelector, valueSelector); + } + + static final class ToMapIterator extends IxSourceIterator> { + + final IxFunction keySelector; + + final IxFunction valueSelector; + + ToMapIterator(Iterator it, IxFunction keySelector, IxFunction valueSelector) { + super(it); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + IxFunction keySelector = this.keySelector; + + IxFunction valueSelector = this.valueSelector; + + Map result = new HashMap(); + + while (it.hasNext()) { + T t = it.next(); + + K k = keySelector.apply(t); + + V v = valueSelector.apply(t); + + result.put(k, v); + } + + value = result; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxToMultimap.java b/src/main/java/ix/IxToMultimap.java new file mode 100644 index 0000000..a01c5db --- /dev/null +++ b/src/main/java/ix/IxToMultimap.java @@ -0,0 +1,82 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxToMultimap extends IxSource>> { + + final IxFunction keySelector; + + final IxFunction valueSelector; + + IxToMultimap(Iterable source, IxFunction keySelector, IxFunction valueSelector) { + super(source); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + } + + @Override + public Iterator>> iterator() { + return new ToMapIterator(source.iterator(), keySelector, valueSelector); + } + + static final class ToMapIterator extends IxSourceIterator>> { + + final IxFunction keySelector; + + final IxFunction valueSelector; + + ToMapIterator(Iterator it, IxFunction keySelector, IxFunction valueSelector) { + super(it); + this.keySelector = keySelector; + this.valueSelector = valueSelector; + } + + @Override + protected boolean moveNext() { + Iterator it = this.it; + + IxFunction keySelector = this.keySelector; + + IxFunction valueSelector = this.valueSelector; + + Map> result = new HashMap>(); + + while (it.hasNext()) { + T t = it.next(); + + K k = keySelector.apply(t); + + Collection coll = result.get(k); + if (coll == null) { + coll = new ArrayList(); + result.put(k, coll); + } + + V v = valueSelector.apply(t); + + coll.add(v); + } + + value = result; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxToSet.java b/src/main/java/ix/IxToSet.java new file mode 100644 index 0000000..b3e6983 --- /dev/null +++ b/src/main/java/ix/IxToSet.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxToSet extends IxSource> { + + IxToSet(Iterable source) { + super(source); + } + + @Override + public Iterator> iterator() { + return new ToSetIterator(source.iterator()); + } + + static final class ToSetIterator extends IxSourceIterator> { + + ToSetIterator(Iterator it) { + super(it); + } + + @Override + protected boolean moveNext() { + + Set set = new HashSet(); + + Iterator it = this.it; + + while (it.hasNext()) { + set.add(it.next()); + } + + value = set; + hasValue = true; + done = true; + return true; + } + } +} diff --git a/src/main/java/ix/IxTransform.java b/src/main/java/ix/IxTransform.java new file mode 100644 index 0000000..a6b8e1b --- /dev/null +++ b/src/main/java/ix/IxTransform.java @@ -0,0 +1,52 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +/** + * Functional interface that allows transforming an + * upstream Iterator for each downstream next() call. + *

+ * If you need per consumer-state, wrap the parent operator + * with compose(): + *


+ * Ix.range(1, 10).compose(o -> {
+ *     int[] counter = { 0 };
+ *     return o.transform((it, c) -> {
+ *         if (it.hasNext()) {
+ *             it.next();
+ *             c.call(++counter[0]);
+ *             return NEXT;
+ *         }
+ *         return STOP;
+ *     });
+ * });
+ * 
+ * @param the source value type + * @param the result value type + */ +public interface IxTransform { + + int STOP = 0; + + int NEXT = 1; + + int LAST = 2; + + int moveNext(Iterator it, IxConsumer consumer); +} diff --git a/src/main/java/ix/IxTransformer.java b/src/main/java/ix/IxTransformer.java new file mode 100644 index 0000000..aeebe1f --- /dev/null +++ b/src/main/java/ix/IxTransformer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxTransformer extends IxSource { + + final IxTransform transform; + + IxTransformer(Iterable source, IxTransform transform) { + super(source); + this.transform = transform; + } + + @Override + public Iterator iterator() { + return new TransformerIterator(source.iterator(), transform); + } + + static final class TransformerIterator extends IxSourceIterator + implements IxConsumer { + + final IxTransform transform; + + TransformerIterator(Iterator it, IxTransform transform) { + super(it); + this.transform = transform; + } + + @Override + protected boolean moveNext() { + int m = transform.moveNext(it, this); + if (m == IxTransform.LAST) { + done = true; + return true; + } + if (m == IxTransform.STOP) { + value = null; + done = true; + return false; + } + if (!hasValue) { + throw new IllegalStateException("No value set!"); + } + return true; + } + + @Override + public void accept(R t) { + if (hasValue) { + throw new IllegalStateException("Value already set in this turn!"); + } + value = t; + hasValue = true; + } + } +} diff --git a/src/main/java/ix/IxUnion.java b/src/main/java/ix/IxUnion.java new file mode 100644 index 0000000..2961f9d --- /dev/null +++ b/src/main/java/ix/IxUnion.java @@ -0,0 +1,82 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxUnion extends IxSource { + + final Iterable other; + + IxUnion(Iterable source, Iterable other) { + super(source); + this.other = other; + } + + @Override + public Iterator iterator() { + return new UnionIterator(source.iterator(), other.iterator()); + } + + static final class UnionIterator extends IxSourceIterator { + + final Iterator other; + + final Set set; + + boolean second; + + UnionIterator(Iterator it, Iterator other) { + super(it); + this.other = other; + this.set = new HashSet(); + } + + @Override + protected boolean moveNext() { + Set set = this.set; + for (;;) { + if (second) { + Iterator other = this.other; + while (other.hasNext()) { + T v = other.next(); + if (set.add(v)) { + value = v; + hasValue = true; + return true; + } + } + + done = true; + return false; + } + + Iterator it = this.it; + while (it.hasNext()) { + T v = it.next(); + if (set.add(v)) { + value = v; + hasValue = true; + return true; + } + } + + second = true; + } + } + } +} diff --git a/src/main/java/ix/IxWindow.java b/src/main/java/ix/IxWindow.java new file mode 100644 index 0000000..c0632dc --- /dev/null +++ b/src/main/java/ix/IxWindow.java @@ -0,0 +1,163 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxWindow extends IxSource> { + + final int size; + + static final Object NULL = new Object(); + + IxWindow(Iterable source, int size) { + super(source); + this.size = size; + } + + @Override + public Iterator> iterator() { + return new WindowIterator(source.iterator(), size); + } + + static final class WindowIterator extends IxSourceIterator> { + + final int size; + + int index; + + WindowIterable current; + + WindowIterator(Iterator it, int size) { + super(it); + this.size = size; + } + + @Override + protected boolean moveNext() { + int i = index; + for (;;) { + if (!it.hasNext()) { + done = true; + return false; + } + + T v = it.next(); + + WindowIterable c; + if (i++ == 0) { + if (i == size) { + index = 0; + } else { + index = i; + } + c = new WindowIterable(this, size); + current = c; + c.iterator.queue.offer(v != null ? v : NULL); + value = c; + hasValue = true; + return true; + } + + current.iterator.queue.offer(v != null ? v : NULL); + + if (i == size) { + i = 0; + } + } + } + + boolean moveInner() { + if (!it.hasNext()) { + return false; + } + + T v = it.next(); + + current.iterator.queue.offer(v != null ? v : NULL); + + int i = index + 1; + if (i == size) { + current = null; + index = 0; + } else { + index = i; + } + return true; + } + } + + static final class WindowIterable extends Ix { + + final WindowInnerIterator iterator; + + boolean once; + + WindowIterable(WindowIterator parent, int size) { + this.iterator = new WindowInnerIterator(parent, size); + } + + @Override + public Iterator iterator() { + if (!once) { + once = true; + return iterator; + } + throw new IllegalStateException("This Window Ix iterable can be consumed only once."); + } + } + + static final class WindowInnerIterator extends IxBaseIterator { + + final WindowIterator parent; + + final ArrayDeque queue; + + int remaining; + + WindowInnerIterator(WindowIterator parent, int remaining) { + this.parent = parent; + this.queue = new ArrayDeque(); + this.remaining = remaining; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + int r = remaining; + if (r == 0) { + done = true; + return false; + } + Object o = queue.poll(); + + if (o == null) { + if (!parent.moveInner()) { + done = true; + return false; + } + o = queue.poll(); + } + + value = o == NULL ? null : (T)o; + hasValue = true; + remaining = r - 1; + return true; + } + } + +} diff --git a/src/main/java/ix/IxWindowOverlap.java b/src/main/java/ix/IxWindowOverlap.java new file mode 100644 index 0000000..21ae806 --- /dev/null +++ b/src/main/java/ix/IxWindowOverlap.java @@ -0,0 +1,211 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxWindowOverlap extends IxSource> { + + final int size; + + final int skip; + + static final Object NULL = new Object(); + + IxWindowOverlap(Iterable source, int size, int skip) { + super(source); + this.size = size; + this.skip = skip; + } + + @Override + public Iterator> iterator() { + return new WindowIterator(source.iterator(), size, skip); + } + + static final class WindowIterator extends IxSourceIterator> { + + final int size; + + final int skip; + + final Queue> queue; + + final Queue> windows; + + int index; + + int headSize; + + WindowIterator(Iterator it, int size, int skip) { + super(it); + this.size = size; + this.skip = skip; + this.queue = new ArrayDeque>(); + this.windows = new ArrayDeque>(); + } + + @Override + protected boolean moveNext() { + WindowIterable w = queue.poll(); + if (w == null) { + if (!moveMain()) { + done = true; + return false; + } + w = queue.poll(); + } + + value = w; + hasValue = true; + return true; + } + + boolean moveMain() { + int i = index; + for (;;) { + if (!it.hasNext()) { + return false; + } + + T v = it.next(); + + for (WindowIterable c : windows) { + c.iterator.offer(v); + } + + int j = headSize + 1; + if (j == size) { + windows.poll(); + headSize = j - skip; + } else { + headSize = j; + } + + if (i++ == 0) { + if (i == skip) { + index = 0; + } else { + index = i; + } + WindowIterable c = new WindowIterable(this, size); + c.iterator.offer(v); + queue.offer(c); + windows.offer(c); + + return true; + } + + if (i == skip) { + i = 0; + } + } + } + + boolean moveInner() { + int i = index; + if (!it.hasNext()) { + return false; + } + + T v = it.next(); + + for (WindowIterable c : windows) { + c.iterator.offer(v); + } + + int j = headSize + 1; + if (j == size) { + windows.poll(); + headSize = j - skip; + } else { + headSize = j; + } + + if (i++ == 0) { + WindowIterable c = new WindowIterable(this, size); + c.iterator.offer(v); + queue.offer(c); + windows.offer(c); + } + + if (i == skip) { + index = 0; + } + return true; + } + } + + static final class WindowIterable extends Ix { + + final WindowInnerIterator iterator; + + boolean once; + + WindowIterable(WindowIterator parent, int size) { + this.iterator = new WindowInnerIterator(parent); + } + + @Override + public Iterator iterator() { + if (!once) { + once = true; + return iterator; + } + throw new IllegalStateException("This Window Ix iterable can be consumed only once."); + } + } + + static final class WindowInnerIterator extends IxBaseIterator { + + final WindowIterator parent; + + final ArrayDeque queue; + + WindowInnerIterator(WindowIterator parent) { + this.parent = parent; + this.queue = new ArrayDeque(); + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Object o = queue.poll(); + + if (o == null) { + if (!parent.moveInner()) { + done = true; + return false; + } + o = queue.poll(); + if (o == null) { + done = true; + return false; + } + } + + value = o == NULL ? null : (T)o; + hasValue = true; + return true; + } + + void offer(T v) { + queue.offer(v != null ? v : NULL); + } + } + +} diff --git a/src/main/java/ix/IxWindowSkip.java b/src/main/java/ix/IxWindowSkip.java new file mode 100644 index 0000000..6e7f8d7 --- /dev/null +++ b/src/main/java/ix/IxWindowSkip.java @@ -0,0 +1,169 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +final class IxWindowSkip extends IxSource> { + + final int size; + + final int skip; + + static final Object NULL = new Object(); + + IxWindowSkip(Iterable source, int size, int skip) { + super(source); + this.size = size; + this.skip = skip; + } + + @Override + public Iterator> iterator() { + return new WindowIterator(source.iterator(), size, skip); + } + + static final class WindowIterator extends IxSourceIterator> { + + final int size; + + int index; + + final int skip; + + WindowIterable current; + + WindowIterator(Iterator it, int size, int skip) { + super(it); + this.size = size; + this.skip = skip; + } + + @Override + protected boolean moveNext() { + int i = index; + for (;;) { + if (!it.hasNext()) { + done = true; + return false; + } + + T v = it.next(); + + if (i++ == 0) { + index = i; + WindowIterable c = new WindowIterable(this, size); + current = c; + c.iterator.offer(v); + value = c; + hasValue = true; + return true; + } + + WindowInnerIterator ci = current.iterator; + + if (ci.offered < size) { + ci.offer(v); + } + + if (i == skip) { + i = 0; + } + } + } + + boolean moveInner() { + if (!it.hasNext()) { + return false; + } + + T v = it.next(); + + current.iterator.offer(v); + + index++; + return true; + } + } + + static final class WindowIterable extends Ix { + + final WindowInnerIterator iterator; + + boolean once; + + WindowIterable(WindowIterator parent, int size) { + this.iterator = new WindowInnerIterator(parent, size); + } + + @Override + public Iterator iterator() { + if (!once) { + once = true; + return iterator; + } + throw new IllegalStateException("This Window Ix iterable can be consumed only once."); + } + } + + static final class WindowInnerIterator extends IxBaseIterator { + + final WindowIterator parent; + + final ArrayDeque queue; + + int remaining; + + int offered; + + WindowInnerIterator(WindowIterator parent, int size) { + this.parent = parent; + this.queue = new ArrayDeque(); + this.remaining = size; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + int r = remaining; + if (r == 0) { + done = true; + return false; + } + Object o = queue.poll(); + + if (o == null) { + if (!parent.moveInner()) { + done = true; + return false; + } + o = queue.poll(); + } + + value = o == NULL ? null : (T)o; + hasValue = true; + remaining = r - 1; + return true; + } + + void offer(T t) { + offered++; + queue.offer(t != null ? t : NULL); + } + } + +} diff --git a/src/main/java/ix/IxWrapper.java b/src/main/java/ix/IxWrapper.java new file mode 100644 index 0000000..53ab5b2 --- /dev/null +++ b/src/main/java/ix/IxWrapper.java @@ -0,0 +1,32 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxWrapper extends IxSource { + + IxWrapper(Iterable source) { + super(source); + } + + @Override + public Iterator iterator() { + return source.iterator(); + } + +} diff --git a/src/main/java/ix/IxZip2.java b/src/main/java/ix/IxZip2.java new file mode 100644 index 0000000..a7e1e6b --- /dev/null +++ b/src/main/java/ix/IxZip2.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxZip2 extends Ix { + + final Iterable source1; + + final Iterable source2; + + final IxFunction2 zipper; + + IxZip2(Iterable source1, Iterable source2, IxFunction2 zipper) { + this.source1 = source1; + this.source2 = source2; + this.zipper = zipper; + } + + @Override + public Iterator iterator() { + return new Zip2Iterator(source1.iterator(), source2.iterator(), zipper); + } + + static final class Zip2Iterator extends IxBaseIterator { + + final Iterator source1; + + final Iterator source2; + + final IxFunction2 zipper; + + Zip2Iterator(Iterator source1, Iterator source2, IxFunction2 zipper) { + this.source1 = source1; + this.source2 = source2; + this.zipper = zipper; + } + + @Override + protected boolean moveNext() { + if (!source1.hasNext()) { + done = true; + return false; + } + + T1 t1 = source1.next(); + + if (!source2.hasNext()) { + done = true; + return false; + } + + T2 t2 = source2.next(); + + value = zipper.apply(t1, t2); + hasValue = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxZip3.java b/src/main/java/ix/IxZip3.java new file mode 100644 index 0000000..b45c4ce --- /dev/null +++ b/src/main/java/ix/IxZip3.java @@ -0,0 +1,91 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxZip3 extends Ix { + final Iterable source1; + + final Iterable source2; + + final Iterable source3; + + final IxFunction3 zipper; + + IxZip3(Iterable source1, Iterable source2, Iterable source3, + IxFunction3 zipper) { + this.source1 = source1; + this.source2 = source2; + this.source3 = source3; + this.zipper = zipper; + } + + @Override + public Iterator iterator() { + return new Zip3Iterator(source1.iterator(), source2.iterator(), + source3.iterator(), zipper); + } + + static final class Zip3Iterator extends IxBaseIterator { + + final Iterator source1; + + final Iterator source2; + + final Iterator source3; + + final IxFunction3 zipper; + + Zip3Iterator(Iterator source1, Iterator source2, Iterator source3, + IxFunction3 zipper) { + this.source1 = source1; + this.source2 = source2; + this.source3 = source3; + this.zipper = zipper; + } + + @Override + protected boolean moveNext() { + if (!source1.hasNext()) { + done = true; + return false; + } + + T1 t1 = source1.next(); + + if (!source2.hasNext()) { + done = true; + return false; + } + + T2 t2 = source2.next(); + + if (!source3.hasNext()) { + done = true; + return false; + } + + T3 t3 = source3.next(); + + value = zipper.apply(t1, t2, t3); + hasValue = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxZip4.java b/src/main/java/ix/IxZip4.java new file mode 100644 index 0000000..66929b9 --- /dev/null +++ b/src/main/java/ix/IxZip4.java @@ -0,0 +1,106 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxZip4 extends Ix { + final Iterable source1; + + final Iterable source2; + + final Iterable source3; + + final Iterable source4; + + final IxFunction4 zipper; + + IxZip4(Iterable source1, Iterable source2, + Iterable source3, Iterable source4, + IxFunction4 zipper) { + this.source1 = source1; + this.source2 = source2; + this.source3 = source3; + this.source4 = source4; + this.zipper = zipper; + } + + @Override + public Iterator iterator() { + return new Zip4Iterator(source1.iterator(), source2.iterator(), + source3.iterator(), source4.iterator(), zipper); + } + + static final class Zip4Iterator extends IxBaseIterator { + + final Iterator source1; + + final Iterator source2; + + final Iterator source3; + + final Iterator source4; + + final IxFunction4 zipper; + + Zip4Iterator(Iterator source1, Iterator source2, Iterator source3, + Iterator source4, + IxFunction4 zipper) { + this.source1 = source1; + this.source2 = source2; + this.source3 = source3; + this.source4 = source4; + this.zipper = zipper; + } + + @Override + protected boolean moveNext() { + if (!source1.hasNext()) { + done = true; + return false; + } + + T1 t1 = source1.next(); + + if (!source2.hasNext()) { + done = true; + return false; + } + + T2 t2 = source2.next(); + + if (!source3.hasNext()) { + done = true; + return false; + } + + T3 t3 = source3.next(); + + if (!source4.hasNext()) { + done = true; + return false; + } + + T4 t4 = source4.next(); + + value = zipper.apply(t1, t2, t3, t4); + hasValue = true; + return true; + } + + } +} diff --git a/src/main/java/ix/IxZipArray.java b/src/main/java/ix/IxZipArray.java new file mode 100644 index 0000000..22f396a --- /dev/null +++ b/src/main/java/ix/IxZipArray.java @@ -0,0 +1,82 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +final class IxZipArray extends Ix { + + final Iterable[] sources; + + final IxFunction zipper; + + IxZipArray(Iterable[] sources, IxFunction zipper) { + this.sources = sources; + this.zipper = zipper; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + + Iterable[] src = sources; + + Iterator[] iterators = new Iterator[src.length]; + for (int i = 0; i < iterators.length; i++) { + iterators[i] = (Iterator)src[i].iterator(); + } + + return new ZipArrayIterator(iterators, zipper); + } + + static final class ZipArrayIterator extends IxBaseIterator { + + final Iterator[] sources; + + final IxFunction zipper; + + ZipArrayIterator(Iterator[] sources, IxFunction zipper) { + this.sources = sources; + this.zipper = zipper; + } + + @SuppressWarnings("unchecked") + @Override + protected boolean moveNext() { + Iterator[] iterators = sources; + int n = iterators.length; + T[] a = (T[])new Object[n]; + + for (int i = 0; i < n; i++) { + Iterator it = iterators[i]; + if (it.hasNext()) { + a[i] = it.next(); + } else { + done = true; + return false; + } + } + + value = zipper.apply(a); + hasValue = true; + + return true; + } + + } + +} diff --git a/src/main/java/ix/IxZipIterable.java b/src/main/java/ix/IxZipIterable.java new file mode 100644 index 0000000..74b2681 --- /dev/null +++ b/src/main/java/ix/IxZipIterable.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import ix.IxZipArray.ZipArrayIterator; + +final class IxZipIterable extends Ix { + + final Iterable> sources; + + final IxFunction zipper; + + IxZipIterable(Iterable> sources, IxFunction zipper) { + this.sources = sources; + this.zipper = zipper; + } + + @SuppressWarnings("unchecked") + @Override + public Iterator iterator() { + + Iterable[] src = new Iterable[8]; + int n = 0; + + for (Iterable it : sources) { + if (n == src.length) { + src = Arrays.copyOf(src, n + (n >> 1)); + } + src[n++] = it; + } + + Iterator[] iterators = new Iterator[n]; + for (int i = 0; i < n; i++) { + iterators[i] = (Iterator)src[i].iterator(); + } + + return new ZipArrayIterator(iterators, zipper); + } +} diff --git a/src/main/java/ix/exceptions/package-info.java b/src/main/java/ix/NumberToLongHelper.java similarity index 77% rename from src/main/java/ix/exceptions/package-info.java rename to src/main/java/ix/NumberToLongHelper.java index 7dc5a46..92c268a 100644 --- a/src/main/java/ix/exceptions/package-info.java +++ b/src/main/java/ix/NumberToLongHelper.java @@ -1,19 +1,26 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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. - */ -/** - * Contains exception classes. - */ -package ix.exceptions; \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +enum NumberToLongHelper implements IxFunction { + INSTANCE; + + @Override + public Long apply(Number t1) { + return t1.longValue(); + } +} \ No newline at end of file diff --git a/src/main/java/ix/Pair.java b/src/main/java/ix/Pair.java deleted file mode 100644 index 081e6d1..0000000 --- a/src/main/java/ix/Pair.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -/** - * A pair of two objects. - * @param the first type - * @param the second type - */ -public final class Pair { - /** The first object. */ - public final T first; - /** The second object. */ - public final U second; - /** - * Construct a pair. - * @param first the first object - * @param second the second object - */ - public Pair(T first, U second) { - this.first = first; - this.second = second; - } - /** - * Construct a pair. - * @param the first type - * @param the second type - * @param first the first object - * @param second the second object - * @return the pair - */ - public static Pair of(T first, U second) { - return new Pair(first, second); - } - @Override - public boolean equals(Object obj) { - if (obj instanceof Pair) { - Pair that = (Pair)obj; - return - (this.first == that.first || (this.first != null && this.first.equals(that.first))) - && (this.second == that.second || (this.second != null && this.second.equals(that.second))); - } - return false; - } - @Override - public int hashCode() { - return (17 + (first != null ? first.hashCode() : 0)) * 31 + (second != null ? second.hashCode() : 0); - } - @Override - public String toString() { - return "(" + first + ", " + second + ")"; - } -} diff --git a/src/main/java/ix/SelfComparator.java b/src/main/java/ix/SelfComparator.java new file mode 100644 index 0000000..6e4aef0 --- /dev/null +++ b/src/main/java/ix/SelfComparator.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Comparator; + +@SuppressWarnings("rawtypes") +enum SelfComparator implements Comparator { + INSTANCE + ; + + @SuppressWarnings("unchecked") + @Override + public int compare(Comparable o1, Comparable o2) { + return o1.compareTo(o2); + } +} diff --git a/src/main/java/ix/ToListHelper.java b/src/main/java/ix/ToListHelper.java new file mode 100644 index 0000000..f894f51 --- /dev/null +++ b/src/main/java/ix/ToListHelper.java @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +enum ToListHelper implements IxSupplier>, IxConsumer2, Object>, IxFunction, Object[]> { + INSTANCE; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static IxSupplier> initialFactory() { + return (IxSupplier)INSTANCE; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static IxConsumer2, T> collector() { + return (IxConsumer2)INSTANCE; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static IxFunction, Object[]> toArray() { + return (IxFunction)INSTANCE; + } + @Override + public void accept(List t1, Object t2) { + t1.add(t2); + } + + @Override + public List get() { + return new ArrayList(); + } + + @Override + public Object[] apply(List t) { + return t.toArray(); + } + +} diff --git a/src/main/java/ix/exceptions/MultiIOException.java b/src/main/java/ix/exceptions/MultiIOException.java deleted file mode 100644 index 6b15dba..0000000 --- a/src/main/java/ix/exceptions/MultiIOException.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.exceptions; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Exception that collects other IOException instances. - *

Note: unfortunately, we can't use Java 7's addSuppressed for - * this purpose as Reactive4Java is aimed at Java 6.

- */ -public class MultiIOException extends IOException { - /** */ - private static final long serialVersionUID = 7860115538280839361L; - /** The inner exceptions. */ - protected final List innerExceptions = new ArrayList(); - /** Default constructor with no message or cause. */ - public MultiIOException() { - super(); - } - /** - * Constructor with the error message. - * @param message the message - */ - public MultiIOException(String message) { - super(message); - } - /** - * Constructor with the cause. - * @param cause the cause - */ - public MultiIOException(Throwable cause) { - super(cause); - } - /** - * Constructor with the message and cause. - * @param message the message - * @param cause the cause - */ - public MultiIOException(String message, Throwable cause) { - super(message, cause); - } - /** - * Adds an exception to the inner exception list. - * @param ex the exception to add - */ - public void add(IOException ex) { - innerExceptions.add(ex); - } - /** - * @return t Returns the list of inner exceptions which can be freely modified. - */ - public List innerExceptions() { - return new ArrayList(innerExceptions); - } - /** - * Adds the exception to the given MultiIOException. If multi is null, a new - * messageless MultiIOException is created and returned. - * @param multi the target MultiIOException. If null, a new instance is created. - * @param ex the exception to add - * @return the multi value if non null or a new MultiIOException - */ - public static MultiIOException createOrAdd(MultiIOException multi, IOException ex) { - if (multi == null) { - multi = new MultiIOException(); - } - multi.add(ex); - return multi; - } -} diff --git a/src/main/java/ix/exceptions/TooManyElementsException.java b/src/main/java/ix/exceptions/TooManyElementsException.java deleted file mode 100644 index 1ef9e0d..0000000 --- a/src/main/java/ix/exceptions/TooManyElementsException.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.exceptions; - -/** - * Exception for cases when too many elements are contained - * within a collection or observable. Its the dual - * of NoSuchElementException. - */ -public class TooManyElementsException extends RuntimeException { - /** */ - private static final long serialVersionUID = 3390531861721818769L; - /** - * A message and cause-less constructor. - */ - public TooManyElementsException() { - super(); - } - - /** - * Construct the exception by using a message and a cause. - * @param message the message - * @param cause the cause - */ - public TooManyElementsException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Construct the exception by using a message only. - * @param message the message - */ - public TooManyElementsException(String message) { - super(message); - } - - /** - * Construct the exception by using a cause only. - * @param cause the cause - */ - public TooManyElementsException(Throwable cause) { - super(cause); - } - -} diff --git a/src/main/java/ix/internal/operators/AggregateIterable.java b/src/main/java/ix/internal/operators/AggregateIterable.java deleted file mode 100644 index 4c97739..0000000 --- a/src/main/java/ix/internal/operators/AggregateIterable.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; -import rx.functions.Func2; - -/** - * Aggregates the source values via a sum function and - * applies a divide function to return the final result. - * - * @param the source sequence element type - * @param the the accumulated type - * @param the result type - */ -public final class AggregateIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - /** The summing function. */ - private final Func2 sum; - /** The divider function. */ - private final Func2 divide; - - /** - * Constructor, initializes the fields. - * @param source the source sequence - * @param sum the sum function - * @param divide the division function - */ - public AggregateIterable(Iterable source, - Func2 sum, - Func2 divide) { - this.source = source; - this.sum = sum; - this.divide = divide; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The single result container. */ - final SingleContainer> result = new SingleContainer>(); - /** We have finished the aggregation. */ - boolean done; - @Override - public boolean hasNext() { - if (!done) { - done = true; - if (result.isEmpty()) { - try { - U intermediate = null; - int count = 0; - try { - while (it.hasNext()) { - intermediate = sum.call(intermediate, it.next()); - count++; - } - } finally { - Interactive.unsubscribe(it); - } - if (count > 0) { - result.add(Interactive.some(divide.call(intermediate, count))); - } - } catch (Throwable t) { - result.add(Interactive.err(t)); - } - } - } - return !result.isEmpty(); - } - - @Override - public V next() { - if (hasNext()) { - return Interactive.value(result.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/AllIterable.java b/src/main/java/ix/internal/operators/AllIterable.java deleted file mode 100644 index 3840c46..0000000 --- a/src/main/java/ix/internal/operators/AllIterable.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; -import rx.functions.Func1; - -/** - * Returns an iterable which returns a single true if - * the predicate matches all elements in the source sequence - * or false otherwise. - * - * @param the source value type - */ -public final class AllIterable implements Iterable { - /** The source. */ - private final Iterable source; - /** The predicate. */ - private final Func1 predicate; - /** - * Constructor, initializes the fields. - * @param source the source sequence - * @param predicate the predicate function - */ - public AllIterable(Iterable source, - Func1 predicate) { - this.source = source; - this.predicate = predicate; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The peek ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - /** Completed. */ - boolean done; - @Override - public boolean hasNext() { - if (peek.isEmpty() && !done) { - try { - if (it.hasNext()) { - while (it.hasNext()) { - T value = it.next(); - if (!predicate.call(value)) { - peek.add(Interactive.some(false)); - return true; - } - } - peek.add(Interactive.some(true)); - } - done = true; - } catch (Throwable t) { - peek.add(Interactive.err(t)); - done = true; - } finally { - Interactive.unsubscribe(it); - } - } - return !peek.isEmpty(); - } - - @Override - public Boolean next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/AnyIterable.java b/src/main/java/ix/internal/operators/AnyIterable.java deleted file mode 100644 index 18a807d..0000000 --- a/src/main/java/ix/internal/operators/AnyIterable.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence that returns a single true if the source sequence contains any - * element. - * - * @param the element type - */ -public final class AnyIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - - public AnyIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source's iterator. */ - Iterator it = source.iterator(); - final SingleContainer peek = new SingleContainer(); - /** Query once. */ - boolean once = true; - @Override - public boolean hasNext() { - if (once) { - once = false; - if (peek.isEmpty()) { - peek.add(it.hasNext()); - } - } - return !peek.isEmpty(); - } - - @Override - public Boolean next() { - if (hasNext()) { - return peek.take(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/BufferIterable.java b/src/main/java/ix/internal/operators/BufferIterable.java deleted file mode 100644 index 6653375..0000000 --- a/src/main/java/ix/internal/operators/BufferIterable.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import rx.Notification; - -/** - * Iterable sequence containing a list of subsequent values from the source sequence - * up to a given buffer size each. - * - * @param the value type - */ -public final class BufferIterable implements Iterable> { - /** The source sequence. */ - private final Iterable source; - /** The buffer size. */ - private final int bufferSize; - - public BufferIterable(Iterable source, int bufferSize) { - this.source = source; - this.bufferSize = bufferSize; - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The current buffer. */ - final SingleContainer>> peek = new SingleContainer>>(); - /** Did the source finish? */ - boolean done; - @Override - public boolean hasNext() { - if (peek.isEmpty() && !done) { - try { - if (it.hasNext()) { - try { - List buffer = new ArrayList(); - while (it.hasNext() && buffer.size() < bufferSize) { - buffer.add(it.next()); - } - if (buffer.size() > 0) { - peek.add(Interactive.some(buffer)); - } - } catch (Throwable t) { - done = true; - peek.add(Interactive.>err(t)); - } - } else { - done = true; - } - } finally { - Interactive.unsubscribe(it); - } - } - return !peek.isEmpty(); - } - - @Override - public List next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/CastIterable.java b/src/main/java/ix/internal/operators/CastIterable.java deleted file mode 100644 index 7180e68..0000000 --- a/src/main/java/ix/internal/operators/CastIterable.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -public final class CastIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Class token; - - public CastIterable(Iterable source, Class token) { - this.source = source; - this.token = token; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public T next() { - return token.cast(it.next()); - } - - @Override - public void remove() { - it.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/CollectIterable.java b/src/main/java/ix/internal/operators/CollectIterable.java deleted file mode 100644 index 7094d94..0000000 --- a/src/main/java/ix/internal/operators/CollectIterable.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.*; - -import rx.functions.*; - -/** - * Collects source values into a custom collection and emits that single collection. - * @param the source value type - * @param the target collection type - * @since 0.92.3 - */ -public final class CollectIterable implements Iterable { - - final Iterable source; - - final Func0 collectionSupplier; - - final Action2 collector; - - public CollectIterable(Iterable source, Func0 collectionSupplier, Action2 collector) { - this.source = source; - this.collectionSupplier = collectionSupplier; - this.collector = collector; - } - - @Override - public Iterator iterator() { - C collection = collectionSupplier.call(); - - Iterator it = source.iterator(); - - return new CollectIterator(collection, it, collector); - } - - static final class CollectIterator implements Iterator { - final Action2 collector; - - C collection; - - Iterator it; - - boolean once; - - public CollectIterator(C collection, Iterator it, Action2 collector) { - this.collection = collection; - this.it = it; - this.collector = collector; - } - - @Override - public boolean hasNext() { - if (!once) { - once = true; - final C c = collection; - final Iterator o = it; - final Action2 a = collector; - while (o.hasNext()) { - a.call(c, o.next()); - } - return true; - } - return collection != null; - } - - @Override - public C next() { - if (hasNext()) { - C c = collection; - collection = null; - return c; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/src/main/java/ix/internal/operators/ConcatIterable.java b/src/main/java/ix/internal/operators/ConcatIterable.java deleted file mode 100644 index b155366..0000000 --- a/src/main/java/ix/internal/operators/ConcatIterable.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public final class ConcatIterable implements Iterable { - /** The source sequences. */ - private final Iterable> sources; - - public ConcatIterable(Iterable> sources) { - this.sources = sources; - } - - @Override - public Iterator iterator() { - final Iterator> si = sources.iterator(); - if (si.hasNext()) { - return new Iterator() { - /** The current iterable. */ - Iterator iter = si.next().iterator(); - /** Save the last iterator since hasNext might run forward into other iterators. */ - Iterator itForRemove; - @Override - public boolean hasNext() { - while (!iter.hasNext()) { - if (!si.hasNext()) { - return false; - } - iter = si.next().iterator(); - } - return true; - } - - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - itForRemove = iter; - return iter.next(); - } - - @Override - public void remove() { - if (itForRemove == null) { - throw new IllegalStateException(); - } - itForRemove.remove(); - itForRemove = null; - } - }; - } - return Interactive.empty().iterator(); - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/CountIterable.java b/src/main/java/ix/internal/operators/CountIterable.java deleted file mode 100644 index 9351e4c..0000000 --- a/src/main/java/ix/internal/operators/CountIterable.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class CountIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - - public CountIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator iterator() { - final Iterator it = source.iterator(); - return new Iterator() { - /** The peek ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - /** Computation already done. */ - boolean done; - @Override - public boolean hasNext() { - if (!done) { - if (peek.isEmpty()) { - int count = 0; - try { - while (it.hasNext()) { - it.next(); - count++; - } - peek.add(Interactive.some(count)); - } catch (Throwable t) { - peek.add(Interactive.err(t)); - } finally { - done = true; - Interactive.unsubscribe(it); - } - } - } - return !peek.isEmpty(); - } - - @Override - public Integer next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/DematerializeIterable.java b/src/main/java/ix/internal/operators/DematerializeIterable.java deleted file mode 100644 index 6ae6b81..0000000 --- a/src/main/java/ix/internal/operators/DematerializeIterable.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class DematerializeIterable implements Iterable { - /** The source sequence. */ - private final Iterable> source; - - public DematerializeIterable( - Iterable> source) { - this.source = source; - } - - @Override - public Iterator iterator() { - final Iterator> it = source.iterator(); - return new Iterator() { - final SingleContainer> peek = new SingleContainer>(); - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - if (it.hasNext()) { - Notification o = it.next(); - if (o.isOnCompleted()) { - return false; - } - peek.add(o); - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/DoOnCompletedIterable.java b/src/main/java/ix/internal/operators/DoOnCompletedIterable.java deleted file mode 100644 index 5c1ce29..0000000 --- a/src/main/java/ix/internal/operators/DoOnCompletedIterable.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.functions.Action0; - -public final class DoOnCompletedIterable implements Iterable { - private final Action0 action; - /** The source sequence. */ - private final Iterable source; - - public DoOnCompletedIterable(Action0 action, - Iterable source) { - this.action = action; - this.source = source; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The iterator. */ - final Iterator it = source.iterator(); - /** After the last. */ - boolean last; - @Override - public boolean hasNext() { - if (!it.hasNext()) { - if (!last) { - last = true; - action.call(); - } - return false; - } - return true; - } - - @Override - public T next() { - if (hasNext()) { - return it.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/DoOnEachIterable.java b/src/main/java/ix/internal/operators/DoOnEachIterable.java deleted file mode 100644 index 72b5907..0000000 --- a/src/main/java/ix/internal/operators/DoOnEachIterable.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; -import rx.functions.Action0; -import rx.functions.Action1; - -public final class DoOnEachIterable implements Iterable { - private final Action1 error; - private final Action0 finish; - /** The source sequence. */ - private final Iterable source; - - public DoOnEachIterable(Action1 error, - Action0 finish, Iterable source) { - this.error = error; - this.finish = finish; - this.source = source; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The iterator. */ - final Iterator it = source.iterator(); - /** The peek ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - /** Finish or error once. */ - boolean once = true; - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - try { - if (it.hasNext()) { - peek.add(Interactive.some(it.next())); - } else { - if (once) { - once = false; - finish.call(); - } - } - } catch (Throwable t) { - peek.add(Interactive.err(t)); - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (it.hasNext()) { - Notification o = peek.take(); - if (o.isOnError() && once) { - once = false; - error.call(o.getThrowable()); - } - return Interactive.value(o); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/DoOnNextIterable.java b/src/main/java/ix/internal/operators/DoOnNextIterable.java deleted file mode 100644 index 25f34e5..0000000 --- a/src/main/java/ix/internal/operators/DoOnNextIterable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -import rx.functions.Action1; - -public final class DoOnNextIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Action1 action; - - public DoOnNextIterable(Iterable source, - Action1 action) { - this.source = source; - this.action = action; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - @Override - public boolean hasNext() { - return it.hasNext(); - } - @Override - public T next() { - T value = it.next(); - action.call(value); - return value; - } - @Override - public void remove() { - it.remove(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/DoWhileIterable.java b/src/main/java/ix/internal/operators/DoWhileIterable.java deleted file mode 100644 index 15365eb..0000000 --- a/src/main/java/ix/internal/operators/DoWhileIterable.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.functions.Func0; - -public final class DoWhileIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func0 gate; - - public DoWhileIterable(Iterable source, Func0 gate) { - this.source = source; - this.gate = gate; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** is this the first pass? */ - Iterator it = source.iterator(); - @Override - public boolean hasNext() { - while (true) { - if (it.hasNext()) { - return true; - } - if (gate.call()) { - it = source.iterator(); - } else { - break; - } - } - return false; - } - @Override - public T next() { - if (hasNext()) { - return it.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/EnumerationToIterator.java b/src/main/java/ix/internal/operators/EnumerationToIterator.java deleted file mode 100644 index 0b9a5bd..0000000 --- a/src/main/java/ix/internal/operators/EnumerationToIterator.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.Enumerator; -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class EnumerationToIterator implements Iterator { - /** The source enumerator. */ - private final Enumerator en; - /** The peek-ahead buffer. */ - final SingleContainer> peek = new SingleContainer>(); - /** Completion indicator. */ - boolean done; - - public EnumerationToIterator(Enumerator en) { - this.en = en; - } - - @Override - public boolean hasNext() { - if (!done && peek.isEmpty()) { - try { - if (en.next()) { - peek.add(Interactive.some(en.current())); - } else { - done = true; - } - } catch (Throwable t) { - done = true; - peek.add(Interactive.err(t)); - } - } - return peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/ErrorIterable.java b/src/main/java/ix/internal/operators/ErrorIterable.java deleted file mode 100644 index 7693b6b..0000000 --- a/src/main/java/ix/internal/operators/ErrorIterable.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence which throws a specific exception when the first element is retrieved. - * - * @param the value type, ignored - */ -public final class ErrorIterable implements Iterable { - /** The exception to throw on the first element. */ - private final Throwable t; - /** - * Constructor, sets the exception. - * @param t the exception to throw - */ - public ErrorIterable(Throwable t) { - this.t = t; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** First call? */ - boolean first = true; - @Override - public boolean hasNext() { - return first; - } - - @Override - public T next() { - if (first) { - first = false; - if (t instanceof RuntimeException) { - throw (RuntimeException)t; - } - throw new RuntimeException(t); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new IllegalStateException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/FilterIndexedIterable.java b/src/main/java/ix/internal/operators/FilterIndexedIterable.java deleted file mode 100644 index aaca605..0000000 --- a/src/main/java/ix/internal/operators/FilterIndexedIterable.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.functions.Func0; -import rx.functions.Func2; - -public final class FilterIndexedIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func0> predicateFactory; - - public FilterIndexedIterable( - Iterable source, - Func0> predicateFactory) { - this.source = source; - this.predicateFactory = predicateFactory; - } - - @Override - public Iterator iterator() { - final Func2 predicate = predicateFactory.call(); - final Iterator it = source.iterator(); - return new Iterator() { - /** The current element count. */ - int count; - /** The temporary store for peeked elements. */ - final SingleContainer peek = new SingleContainer(); - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - while (it.hasNext()) { - T value = it.next(); - if (predicate.call(count, value)) { - peek.add(value); - count++; - return true; - } - count++; - } - return false; - } - return true; - } - - @Override - public T next() { - if (hasNext()) { - return peek.take(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/FlatMapIterable.java b/src/main/java/ix/internal/operators/FlatMapIterable.java deleted file mode 100644 index b53be5c..0000000 --- a/src/main/java/ix/internal/operators/FlatMapIterable.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.functions.Func1; - -public final class FlatMapIterable implements Iterable { - private final Func1> selector; - /** The source sequence. */ - private final Iterable source; - - public FlatMapIterable( - Func1> selector, - Iterable source) { - this.selector = selector; - this.source = source; - } - - @Override - public Iterator iterator() { - final Iterator it = source.iterator(); - return new Iterator() { - /** The current selected iterator. */ - Iterator sel; - @Override - public boolean hasNext() { - if (sel == null || !sel.hasNext()) { - while (!Thread.currentThread().isInterrupted()) { - if (it.hasNext()) { - sel = selector.call(it.next()).iterator(); - if (sel.hasNext()) { - return true; - } - } else { - break; - } - } - return false; - } - return true; - } - - @Override - public U next() { - if (hasNext()) { - return sel.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - if (sel == null) { - throw new IllegalStateException(); - } - sel.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/GenerateIterable.java b/src/main/java/ix/internal/operators/GenerateIterable.java deleted file mode 100644 index c2b3602..0000000 --- a/src/main/java/ix/internal/operators/GenerateIterable.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.functions.Func1; - -/** - * Iterable sequence similar to a for-loop which generates sequence of values by - * using callback functions. - * - * @param the value type - */ -public final class GenerateIterable implements Iterable { - /** The initial value. */ - private final T seed; - /** Function to generate the next value. */ - private final Func1 next; - /** Function to test for termination condition. */ - private final Func1 predicate; - - /** - * Constructor, sets the fields. - * @param seed the initial value - * @param next the function to generate the next value - * @param predicate function to test for termination - */ - public GenerateIterable(T seed, Func1 next, - Func1 predicate) { - this.seed = seed; - this.next = next; - this.predicate = predicate; - } - - @Override - public Iterator iterator() { - return new Iterator() { - T value = seed; - @Override - public boolean hasNext() { - return predicate.call(value); - } - - @Override - public T next() { - if (hasNext()) { - T current = value; - value = next.call(value); - return current; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/GenerateIterableTimed.java b/src/main/java/ix/internal/operators/GenerateIterableTimed.java deleted file mode 100644 index beae798..0000000 --- a/src/main/java/ix/internal/operators/GenerateIterableTimed.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.concurrent.TimeUnit; - -import rx.functions.Func1; - -public final class GenerateIterableTimed implements Iterable { - private final Func1 predicate; - private final Func1 next; - private final T seed; - private final long initialDelay; - private final long betweenDelay; - private final TimeUnit unit; - - public GenerateIterableTimed(Func1 predicate, - Func1 next, T seed, long initialDelay, - long betweenDelay, TimeUnit unit) { - this.predicate = predicate; - this.next = next; - this.seed = seed; - this.initialDelay = initialDelay; - this.betweenDelay = betweenDelay; - this.unit = unit; - } - - @Override - public Iterator iterator() { - return new Iterator() { - T value = seed; - /** Keeps track of whether there should be an initial delay? */ - boolean shouldInitialWait = true; - /** Keeps track of whether there should be an initial delay? */ - boolean shouldBetweenWait; - @Override - public boolean hasNext() { - if (shouldInitialWait) { - shouldInitialWait = false; - try { - unit.sleep(initialDelay); - } catch (InterruptedException e) { - return false; // FIXME not soure about this - } - } else { - if (shouldBetweenWait) { - shouldBetweenWait = false; - try { - unit.sleep(betweenDelay); - } catch (InterruptedException e) { - return false; // FIXME not soure about this - } - } - } - return predicate.call(value); - } - - @Override - public T next() { - if (hasNext()) { - shouldBetweenWait = true; - T current = value; - value = next.call(value); - return current; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/Interactive.java b/src/main/java/ix/internal/operators/Interactive.java deleted file mode 100644 index dc812ef..0000000 --- a/src/main/java/ix/internal/operators/Interactive.java +++ /dev/null @@ -1,2867 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.CloseableIterable; -import ix.CloseableIterator; -import ix.Enumerable; -import ix.Enumerator; -import ix.GroupedIterable; -import ix.Pair; -import ix.internal.util.IxHelperFunctions; -import ix.internal.util.LinkedBuffer; - -import java.io.Closeable; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import rx.Notification; -import rx.Scheduler; -import rx.Subscription; -import rx.exceptions.Exceptions; -import rx.functions.Action0; -import rx.functions.Action1; -import rx.functions.Actions; -import rx.functions.Func0; -import rx.functions.Func1; -import rx.functions.Func2; -import rx.schedulers.Schedulers; - -/** - * The interactive (i.e., Iterable based) counterparts - * of the Reactive operators. - *

The implementations of the operators are partially derived - * from the Reactive operators.

- * @see rx.Observable - */ -public final class Interactive { - /** - * Creates an iterable which traverses the source iterable and maintains a running sum value based - * on the sum function parameter. Once the source is depleted, it - * applies the divide function and returns its result. - * This operator is a general base for averaging (where {@code sum(u, t) => u + t}, {@code divide(u, index) => u / index}), - * summing (where {@code sum(u, t) => u + t}, and {@code divide(u, index) => u)}), - * minimum, maximum, etc. - * If the traversal of the source fails due an exception, that exception is reflected on the - * {@code next()} call of the returned iterator. - * The returned iterator will throw an UnsupportedOperationException - * for its remove() method. - * @param the source element type - * @param the intermediate aggregation type - * @param the resulting aggregation type - * @param source the source of Ts - * @param sum the function which takes the current intermediate value, - * the current source value and should produce a new intermediate value. - * for the first element of T, the U parameter will receive null - * @param divide the function which takes the last intermediate value and a total count of Ts seen and should return the final aggregation value. - * @return the new iterable - */ - public static Iterable aggregate( - final Iterable source, - final Func2 sum, - final Func2 divide) { - return new AggregateIterable(source, sum, divide); - } - /** - * Returns an iterable which contains true if all - * elements of the source iterable satisfy the predicate. - * The operator might return a false before fully iterating the source. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param source the source of Ts - * @param predicate the predicate - * @return the new iterable - */ - public static Iterable all( - final Iterable source, - final Func1 predicate) { - return new AllIterable(source, predicate); - } - /** - * Tests if there is any element of the source that satisfies the given predicate function. - * @param the source element type - * @param source the source of Ts - * @param predicate the predicate tester function - * @return the new iterable - */ - - public static Iterable any( - final Iterable source, - final Func1 predicate) { - return any(filter(source, predicate)); - } - /** - * Determines if the given source has any elements at all. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type, irrelevant here - * @param source the source of Ts - * @return the new iterable with a single true or false - */ - - public static Iterable any( - final Iterable source) { - return new AnyIterable(source); - } - /** - * Returns a pair of the maximum argument and value from the given sequence. - * @param the element type of the sequence - * @param the value type for the comparison, must be self comparable - * @param source the source sequence - * @param valueSelector the value selector function - * @return the pair of the first maximum element and value, null if the sequence was empty - */ - public static > Pair argAndMax( - Iterable source, - Func1 valueSelector) { - return argAndMax(source, valueSelector, IxHelperFunctions.comparator()); - } - /** - * Returns a pair of the maximum argument and value from the given sequence. - * @param the element type - * @param the value type - * @param source the source sequence of Ts - * @param valueSelector the selector to extract the value from T - * @param valueComparator the comparator to compare two values - * @return the first pair of max argument and value or null if the source sequence was empty - */ - public static Pair argAndMax( - Iterable source, - Func1 valueSelector, - Comparator valueComparator) { - T arg = null; - V max = null; - boolean hasElement = false; - Iterator it = source.iterator(); - try { - while (it.hasNext()) { - T item = it.next(); - V itemValue = valueSelector.call(item); - if (!hasElement || valueComparator.compare(max, itemValue) < 0) { - arg = item; - max = itemValue; - } - hasElement = true; - } - if (hasElement) { - return Pair.of(arg, max); - } - } finally { - unsubscribe(it); - } - return null; - } - /** - * Returns a pair of the maximum argument and value from the given sequence. - * @param the element type of the sequence - * @param the value type for the comparison, must be self comparable - * @param source the source sequence - * @param valueSelector the value selector function - * @return the pair of the first maximum element and value, null if the sequence was empty - */ - public static > Pair argAndMin( - Iterable source, - Func1 valueSelector) { - return argAndMin(source, valueSelector, IxHelperFunctions.comparator()); - } - /** - * Returns a pair of the minimum argument and value from the given sequence. - * @param the element type - * @param the value type - * @param source the source sequence of Ts - * @param valueSelector the selector to extract the value from T - * @param valueComparator the comparator to compare two values - * @return the first pair of min argument and value or null if the source sequence was empty - */ - public static Pair argAndMin( - Iterable source, - Func1 valueSelector, - final Comparator valueComparator) { - return argAndMax(source, valueSelector, new Comparator() { - @Override - public int compare(V o1, V o2) { - return valueComparator.compare(o2, o1); - } - }); - } - /** - * Returns an iterable which averages the source BigDecimal values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source of BigDecimal values - * @return the new iterable - */ - - public static Iterable averageBigDecimal( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public BigDecimal call(BigDecimal param1, BigDecimal param2) { - return param1 != null ? param1.add(param2) : param2; - } - }, - new Func2() { - @Override - public BigDecimal call(BigDecimal param1, Integer param2) { - return param1.divide(new BigDecimal(param2), BigDecimal.ROUND_HALF_UP); - } - } - ); - } - /** - * Returns an iterable which averages the source BigInteger values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source of BigInteger values - * @return the new iterable - */ - - public static Iterable averageBigInteger( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public BigInteger call(BigInteger param1, BigInteger param2) { - return param1 != null ? param1.add(param2) : param2; - } - }, - new Func2() { - @Override - public BigDecimal call(BigInteger param1, Integer param2) { - return new BigDecimal(param1).divide(new BigDecimal(param2), BigDecimal.ROUND_HALF_UP); - } - } - ); - } - /** - * Returns an iterable which averages the source Double values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source of Double values - * @return the new iterable - */ - - public static Iterable averageDouble( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Double call(Double param1, Double param2) { - return param1 != null ? param1 + param2 : param2.doubleValue(); - } - }, - new Func2() { - @Override - public Double call(Double param1, Integer param2) { - return param1 / param2; - } - } - ); - } - /** - * Returns an iterable which averages the source Float values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source of Float values - * @return the new iterable - */ - - public static Iterable averageFloat( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Float call(Float param1, Float param2) { - return param1 != null ? param1 + param2 : param2.floatValue(); - } - }, - new Func2() { - @Override - public Float call(Float param1, Integer param2) { - return param1 / param2; - } - } - ); - } - /** - * Returns an iterable which averages the source Integer values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source of Integer values - * @return the new iterable - */ - - public static Iterable averageInt( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Double call(Double param1, Integer param2) { - return param1 != null ? param1 + param2 : param2.doubleValue(); - } - }, - new Func2() { - @Override - public Double call(Double param1, Integer param2) { - return param1 / param2; - } - } - ); - } - /** - * Returns an iterable which averages the source Integer values. - * The returned iterator will throw an UnsupportedOperationException - * for its remove() method. - * @param source the source of Integer values - * @return the new iterable - */ - - public static Iterable averageLong( - Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Double call(Double param1, Long param2) { - return param1 != null ? param1 + param2 : param2.doubleValue(); - } - }, - new Func2() { - @Override - public Double call(Double param1, Integer param2) { - return param1 / param2; - } - } - ); - } - /** - * Returns an iterable which buffers the source elements - * into bufferSize lists. - * FIXME what to do on empty source or last chunk? - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param source the source of Ts - * @param bufferSize the buffer size. - * @return the new iterable - */ - - public static Iterable> buffer( - final Iterable source, - final int bufferSize) { - if (bufferSize <= 0) { - throw new IllegalArgumentException("bufferSize <= 0"); - } - return new BufferIterable(source, bufferSize); - } - /** - * Concatenate the given iterable sources one - * after another in a way, that calling the second iterator() - * only happens when there is no more element in the first iterator. - *

The returned iterator forwards all remove() calls - * to the current source (e.g., you can remove the same elements from - * multiple collections with a single traversal on the concat result). - * @param the element type - * @param sources the list of iterables to concatenate - * @return a new iterable - */ - - public static Iterable concat( - final Iterable> sources) { - return new ConcatIterable(sources); - } - /** - * Concatenate the given iterable sources one - * after another in a way, that calling the second iterator() - * only happens when there is no more element in the first iterator. - *

The returned iterator forwards all remove() calls - * to the current source (first or next). - * @param the element type - * @param first the first iterable - * @param second the second iterable - * @return the new iterable - */ - - public static Iterable concat( - final Iterable first, - final Iterable second) { - List> list = new LinkedList>(); - list.add(first); - list.add(second); - return concat(list); - } - /** - * Returns an iterable which checks for the existence of the supplied - * value by comparing the elements of the source iterable using reference - * and equals(). The iterable then returns a single true or false. - * @param the source element type - * @param source the source - * @param value the value to check - * @return the new iterable - */ - - public static Iterable contains( - final Iterable source, final Object value) { - return any(source, new Func1() { - @Override - public Boolean call(T param1) { - return param1 == value || (param1 != null && param1.equals(value)); - } - }); - } - /** - * Counts the elements of the iterable source by using a 32 bit int. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @return the new iterable - */ - - public static Iterable count( - final Iterable source) { - return new CountIterable(source); - } - /** - * Counts the elements of the iterable source by using a 64 bit long. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @return the new iterable - */ - - public static Iterable countLong( - final Iterable source) { - return new LongCountIterable(source); - } - /** - * Defers the source iterable creation to registration time and - * calls the given func for the actual source. - * @param the element type - * @param func the function that returns an iterable. - * @return the new iterable - */ - - public static Iterable defer( - final Func0> func) { - return new DeferIterable(func); - } - /** - * Convert the source materialized elements into normal iterator behavior. - * The returned iterator will throw an UnsupportedOperationException for its remove() method. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element types - * @param source the source of T options - * @return the new iterable - */ - - public static Iterable dematerialize( - final Iterable> source) { - return new DematerializeIterable(source); - } - /** - * Returns an iterable which filters its elements based if they were ever seen before in - * the current iteration. - * Value equality is computed by reference equality and equals() - * @param the source element type - * @param source the source of Ts - * @return the new iterable - */ - - public static Iterable distinct( - final Iterable source) { - return distinct(source, IxHelperFunctions.identity(), IxHelperFunctions.identity()); - } - /** - * Returns an iterable which filters its elements by an unique key - * in a way that when multiple source items produce the same key, only - * the first one ever seen gets relayed further on. - * Key equality is computed by reference equality and equals() - * @param the source element type - * @param the key element type - * @param the output element type - * @param source the source of Ts - * @param keySelector the key selector for only-once filtering - * @param valueSelector the value select for the output of the first key cases - * @return the new iterable - */ - - public static Iterable distinct( - final Iterable source, - final Func1 keySelector, - final Func1 valueSelector) { - return map(filterIndexed(source, - new Func0>() { - @Override - public Func2 call() { - return new Func2() { - final Set memory = new HashSet(); - @Override - public Boolean call(Integer index, T param1) { - return memory.add(keySelector.call(param1)); - } - }; - } - }) - , new Func1() { - @Override - public V call(T param1) { - return valueSelector.call(param1); - } - }); - } - /** - * Creates an iterable which ensures that subsequent values of T are not equal (reference and equals). - * @param the element type - * @param source the source iterable - * @return the new iterable - */ - - public static Iterable distinctNext( - final Iterable source) { - return filterIndexed(source, - new Func0>() { - @Override - public Func2 call() { - return new Func2() { - /** Is this the first element? */ - boolean first = true; - /** The last seen element. */ - T last; - @Override - public Boolean call(Integer index, T param1) { - if (first) { - first = false; - last = param1; - return true; - } - if (last == param1 || (last != null && last.equals(param1))) { - last = param1; - return false; - } - last = param1; - return true; - } - }; - } - }); - } - /** - * Creates an iterable which ensures that subsequent values of - * T are not equal in respect to the extracted keys (reference and equals). - * @param the element type - * @param the key type - * @param source the source iterable - * @param keyExtractor the function to extract the keys which will be compared - * @return the new iterable - */ - - public static Iterable distinctNext( - final Iterable source, - final Func1 keyExtractor) { - return filterIndexed(source, - new Func0>() { - @Override - public Func2 call() { - return new Func2() { - /** Is this the first element? */ - boolean first = true; - /** The last seen element. */ - U last; - @Override - public Boolean call(Integer index, T param1) { - U key = keyExtractor.call(param1); - if (first) { - first = false; - last = key; - return true; - } - if (last == key || (last != null && last.equals(key))) { - last = key; - return false; - } - last = key; - return true; - } - }; - } - }); - } - /** - * Construct a new iterable which will invoke the specified action - * before the source value gets relayed through it. - * Can be used to inject side-effects before returning a value. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the returned element type - * @param source the source iterable - * @param action the action to invoke before each next() is returned. - * @return the new iterable - */ - - public static Iterable doOnNext( - final Iterable source, - final Action1 action) { - return new DoOnNextIterable(source, action); - } - /** - * Returns an iterable which reiterates over and over again on source - * as long as the gate is true. The gate function is checked only - * when a pass over the source stream was completed. - * Note that using this operator on an empty iterable may result - * in a direct infinite loop in hasNext() or next() calls depending on the gate function. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param source the source of Ts - * @param gate the gate function to stop the repeat - * @return the new iterable - */ - - public static Iterable doWhile( - final Iterable source, - final Func0 gate) { - return new DoWhileIterable(source, gate); - } - /** - * Determines whether two iterables contain equal elements in the same - * order. More specifically, this method returns {@code true} if - * {@code iterable1} and {@code iterable2} contain the same number of - * elements and every element of {@code iterable1} is equal to the - * corresponding element of {@code iterable2}. - * @param iterable1 the first iterable - * @param iterable2 the second iterable - * @return true if both iterables are either empty or contain the same number and equal items - */ - public static boolean elementsEqual(Iterable iterable1, - Iterable iterable2) { - Iterator iterator1 = iterable1.iterator(); - Iterator iterator2 = iterable2.iterator(); - return elementsEqual(iterator1, iterator2); - } - /** - * Compares two iterators wether they contain the same element in terms of numbers - * and nullsafe Object.equals(). - * @param iterator1 the first iterator - * @param iterator2 the second interator - * @return true if they are equal - */ - public static boolean elementsEqual( - Iterator iterator1, - Iterator iterator2) { - try { - while (iterator1.hasNext()) { - if (!iterator2.hasNext()) { - return false; - } - Object o1 = iterator1.next(); - Object o2 = iterator2.next(); - if (!equal(o1, o2)) { - return false; - } - } - return !iterator2.hasNext(); - } finally { - unsubscribe(iterator1); - unsubscribe(iterator2); - } - } - /** - * Returns an empty iterable which will not produce elements. - * Its hasNext() returns always false, - * next() throws a NoSuchElementException - * and remove() throws an IllegalStateException. - * Note that the Collections.emptyIterable() static method is introduced by Java 7. - * @param the element type, irrelevant - * @return the iterable - */ - @SuppressWarnings("unchecked") - - public static Iterable empty() { - return (Iterable)EMPTY_ITERABLE; - } - /** - * Creates an iterable sequence which returns all elements from source - * followed by the supplied value as last. - *

The returned iterable forwards all {@code remove()} - * methods to the source iterable, except the last element where it - * throws UnsupportedOperationException.

- * @param the element type - * @param source the source sequence - * @param value the value to append - * @return the new iterable - */ - - public static Iterable endWith( - final Iterable source, T value) { - return concat(source, just(value)); - } - /** - * Compare two object in a null-safe manner. - * @param a the first object - * @param b the second object - * @return true if both are null or equal according to Object.equals - */ - private static boolean equal(Object a, Object b) { - return (a == b) || ((a != null) && a.equals(b)); - } - - /** - * Creates an onError notification. - * @param the value type - * @param t the throwable - * @return the notification - */ - static Notification err(Throwable t) { - return Notification.createOnError(t); - } - /** - * Returns an iterable which executes the given action after - * the stream completes. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the element type - * @param source the source of Ts - * @param action the action to invoke - * @return the new iterable - */ - - public static Iterable doOnCompleted( - final Iterable source, - final Action0 action) { - return new DoOnCompletedIterable(action, source); - } - /** - * Returns the first element from the iterable sequence or - * throws a NoSuchElementException. - * @param the value type - * @param src the source sequence - * @return the first element - */ - public static T first(Iterable src) { - Iterator itor = src.iterator(); - try { - return itor.next(); - } finally { - unsubscribe(itor); - } - } - - /** - * Returns the first element from the sequence or the default - * value if this sequence is empty - * @param the value type - * @param src the source sequence - * @param defaultValue the default value to return - * @return the first or default value - * @since 0.91.2 - */ - public static T firstOrDefault(Iterable src, T defaultValue) { - Iterator itor = src.iterator(); - try { - if (itor.hasNext()) { - return itor.next(); - } - return defaultValue; - } finally { - Interactive.unsubscribe(itor); - } - } - - - /** - * Returns an iterable which runs the source iterable and - * returns elements from the iterable returned by the function call. - * The difference from flatMap is that the {@code Iterable<U>}s are - * created before their concatenation starts. - * @param the source element type - * @param the output element type - * @param source the source - * @param selector the result selector - * @return the new iterable - */ - - public static Iterable flatMapAll( - final Iterable source, - final Func1> selector) { - return concat(map(source, selector)); - } - /** - * Iterate over the source and submit each value to the - * given action. Basically, a for-each loop with pluggable - * action. - * This method is useful when the concrete values from the iterator - * are not needed but the iteration itself implies some side effects. - * @param the element type of the iterable - * @param source the iterable - * @param action the action to invoke on with element - */ - public static void forEach( - final Iterable source, - Action1 action) { - Iterator iter = source.iterator(); - try { - while (iter.hasNext()) { - T t = iter.next(); - action.call(t); - } - } finally { - unsubscribe(iter); - } - } - /** - * A generator function which returns Ts based on the termination condition and the way it computes the next values. - * This is equivalent to: - *

-     * T value = seed;
-     * while (predicate(value)) {
-     *     yield value;
-     *     value = next(value);
-     * }
-     * 
- *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param seed the initial value - * @param predicate the predicate to terminate the process - * @param next the function that computes the next value. - * @return the new iterable - */ - - public static Iterable generate( - final T seed, - final Func1 predicate, - final Func1 next) { - return new GenerateIterable(seed, next, predicate); - } - /** - * A generator function which returns Ts based on the termination condition and the way it computes the next values, - * but the first T to be returned is preceded by an initialDelay amount of wait and each - * subsequent element is then generated after betweenDelay sleep. - * The sleeping is blocking the current thread which invokes the hasNext()/next() methods. - * This is equivalent to: - *

-     * T value = seed;
-     * sleep(initialDelay);
-     * if (predicate(value)) {
-     *     yield value;
-     * }
-     * value = next(value);
-     * sleep(betweenDelay);
-     * while (predicate(value)) {
-     *     yield value;
-     *     value = next(value);
-     *     sleep(betweenDelay);
-     * }
-     * 
- *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param seed the initial value - * @param predicate the predicate to terminate the process - * @param next the function that computes the next value. - * @param initialDelay the initial delay - * @param betweenDelay the between delay - * @param unit the time unit for initialDelay and betweenDelay - * @return the new iterable - */ - - public static Iterable generate( - final T seed, - final Func1 predicate, - final Func1 next, - final long initialDelay, - final long betweenDelay, - final TimeUnit unit) { - return new GenerateIterableTimed(predicate, next, seed, initialDelay, - betweenDelay, unit); - - } - /** - * Creates an iterable which traverses the source iterable, - * and based on the key selector, groups values of T into GroupedIterables, - * which can be iterated over later on. - * The equivalence of the keys are determined via reference - * equality and equals() equality. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the result group keys - * @param source the source of Ts - * @param keySelector the key selector - * @return the new iterable - */ - - public static Iterable> groupBy( - final Iterable source, - final Func1 keySelector - ) { - return groupBy(source, keySelector, IxHelperFunctions.identity()); - } - /** - * Creates an iterable which traverses the source iterable, - * and based on the key selector, groups values extracted by valueSelector into GroupedIterables, - * which can be iterated over later on. - * The equivalence of the keys are determined via reference - * equality and equals() equality. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the result group element type - * @param the result group keys - * @param source the source of Ts - * @param keySelector the key selector - * @param valueSelector the value selector - * @return the new iterable - */ - - public static Iterable> groupBy( - final Iterable source, - final Func1 keySelector, - final Func1 valueSelector) { - return distinct(new Iterable>() { - @Override - public Iterator> iterator() { - final Map> groups = new LinkedHashMap>(); - final Iterator it = source.iterator(); - return new Iterator>() { - Iterator> groupIt; - @Override - public boolean hasNext() { - return it.hasNext() || (groupIt != null && groupIt.hasNext()); - } - - @Override - public GroupedIterable next() { - if (hasNext()) { - if (groupIt == null) { - try { - while (it.hasNext()) { - T t = it.next(); - V v = keySelector.call(t); - U u = valueSelector.call(t); - GroupedIterable g = groups.get(v); - if (g == null) { - g = new GroupedIterable(v); - groups.put(v, g); - } - g.add(u); - } - } finally { - unsubscribe(it); - } - groupIt = groups.values().iterator(); - } - return groupIt.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } - }, new Func1, V>() { - @Override - public V call(GroupedIterable param1) { - return param1.getKey(); - } - - }, IxHelperFunctions.>identity()); - } - /** - * Returns an iterable which invokes the given next - * action for each element and the finish action when - * the source completes. - * @param the source element type - * @param source the source of Ts - * @param next the action to invoke on each element - * @param finish the action to invoke after the last element - * @return the new iterable - */ - - public static Iterable doOnEach( - final Iterable source, - Action1 next, - Action0 finish) { - return doOnEach(source, next, Actions.empty(), finish); - } - /** - * Returns an iterable which invokes the given next - * action for each element and error when an exception is thrown. - * @param the source element type - * @param source the source of Ts - * @param next the action to invoke on each element - * @param error the error action to invoke for an error - * @return the new iterable - */ - - public static Iterable doOnEach( - final Iterable source, - final Action1 next, - final Action1 error) { - return doOnEach(source, next, error, Actions.empty()); - } - /** - * Returns an iterable which invokes the given next - * action for each element and the finish action when - * the source completes and error when an exception is thrown. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param source the source of Ts - * @param next the action to invoke on each element - * @param error the error action to invoke for an error - * @param finish the action to invoke after the last element - * @return the new iterable - */ - - public static Iterable doOnEach( - final Iterable source, - final Action1 next, - final Action1 error, - final Action0 finish) { - return new DoOnEachIterable(error, finish, source); - } - /** - * Returns a single true if the target iterable is empty. - * @param source source iterable with any type - * @return the new iterable - */ - - public static Iterable isEmpty( - final Iterable source) { - return map(any(source), IxHelperFunctions.negate()); - } - /** - * Concatenates the source strings one after another and uses the given separator. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param source the source - * @param separator the separator to use - * @return the new iterable - */ - - public static Iterable join( - final Iterable source, - final String separator) { - return aggregate(source, - new Func2() { - @Override - public StringBuilder call(StringBuilder param1, Object param2) { - if (param1 == null) { - param1 = new StringBuilder(); - } else { - param1.append(separator); - } - param1.append(param2); - return param1; - } - }, - new Func2() { - @Override - public String call(StringBuilder param1, Integer param2) { - return param1.toString(); - } - } - ); - } - /** - * Returns the last element of the iterable or throws a NoSuchElementException if the iterable is empty. - * @param the source element type - * @param source the source of Ts - * @return the last value - */ - public static T last( - final Iterable source) { - Iterator it = source.iterator(); - try { - if (it.hasNext()) { - T t; - - do { - t = it.next(); - } while (it.hasNext()); - - return t; - } - } finally { - unsubscribe(it); - } - throw new NoSuchElementException(); - } - - /** - * Returns the last element of this sequence or the default value if - * this sequence is empty. - * @param the source element type - * @param source the source of Ts - * @param defaultValue the default value to return if this sequence is empty - * @return the last value - */ - public static T lastOrDefault( - final Iterable source, T defaultValue) { - Iterator it = source.iterator(); - try { - if (it.hasNext()) { - T t; - - do { - t = it.next(); - } while (it.hasNext()); - - return t; - } - return defaultValue; - } finally { - unsubscribe(it); - } - } - /** - * Creates an iterable which is a transforms the source - * elements by using the selector function. - * The function receives the current index and the current element. - * @param the source element type - * @param the output element type - * @param source the source iterable - * @param selector the selector function - * @return the new iterable - */ - - public static Iterable map( - final Iterable source, - final Func1 selector) { - return mapIndexed(source, new Func2() { - @Override - public U call(Integer param1, T param2) { - return selector.call(param2); - } - }); - } - /** - * Creates an iterable which is a transforms the source - * elements by using the selector function. - * The function receives the current index and the current element. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param the output element type - * @param source the source iterable - * @param selector the selector function - * @return the new iterable - */ - - public static Iterable mapIndexed( - final Iterable source, - final Func2 selector) { - return new MapIndexedIterable(source, selector); - } - /** - * Transforms the sequence of the source iterable into an option sequence of - * Notification.some(), Notification.none() and Notification.error() values, depending on - * what the source's hasNext() and next() produces. - * The returned iterator will throw an UnsupportedOperationException for its remove() method. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param source the source of at least Ts. - * @return the new iterable - */ - - public static Iterable> materialize( - final Iterable source) { - return new MaterializeIterable(source); - } - /** - * Returns the maximum value of the given iterable source. - * @param the element type, which must be self comparable - * @param source the source elements - * @return the new iterable - */ - - public static > Iterable max( - final Iterable source) { - return aggregate(source, IxHelperFunctions.max(), - IxHelperFunctions.identityFirst()); - } - /** - * Returns the maximum value of the given iterable source in respect to the supplied comparator. - * @param the element type, which must be self comparable - * @param source the source elements - * @param comparator the comparator to use - * @return the new iterable - */ - - public static Iterable max( - final Iterable source, - final Comparator comparator) { - return aggregate(source, IxHelperFunctions.max(comparator), IxHelperFunctions.identityFirst()); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied key selector. - * @param the source element type, which must be self comparable - * @param source the source of Ts - * @return the new iterable - */ - - public static > Iterable> maxBy( - final Iterable source) { - return minMax(source, IxHelperFunctions.identity(), IxHelperFunctions.comparator(), true); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied comparator. - * @param the source element type - * @param source the source of Ts - * @param comparator the key comparator - * @return the new iterable - */ - - public static Iterable> maxBy( - final Iterable source, - final Comparator comparator) { - return minMax(source, IxHelperFunctions.identity(), comparator, true); - } - /** - * Returns an iterator which will produce a single List of the maximum values encountered - * in the source stream based on the supplied key selector. - * @param the source element type - * @param the key type, which must be self-comparable - * @param source the source of Ts - * @param keySelector the selector for keys - * @return the new iterable - */ - - public static > Iterable> maxBy( - final Iterable source, - final Func1 keySelector) { - return minMax(source, keySelector, IxHelperFunctions.comparator(), true); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector and comparator. - * @param the source element type - * @param the key type - * @param source the source of Ts - * @param keySelector the selector for keys - * @param keyComparator the key comparator - * @return the new iterable - */ - - public static Iterable> maxBy( - final Iterable source, - final Func1 keySelector, - final Comparator keyComparator) { - return minMax(source, keySelector, keyComparator, true); - } - /** - * Enumerates the source iterable once and caches its results. - * Any iterator party will basically drain this cache, e.g., - * reiterating over this iterable will produce no results. - * Note: the name is not a misspelling, see Memoization. - * FIXME not sure about the buffer sizes. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param source the source of Ts - * @param bufferSize the size of the buffering - * @return the new iterable - */ - - public static Iterable memoize( - final Iterable source, - final int bufferSize) { - if (bufferSize < 0) { - throw new IllegalArgumentException("bufferSize < 0"); - } - return new MemoizeIterable(source, bufferSize); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the values. - * Note: the name is not a misspelling, see Memoization. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param source the source of Ts - * @return the new iterable - */ - - public static Iterable memoizeAll( - final Iterable source) { - final Iterator it = source.iterator(); - final LinkedBuffer buffer = new LinkedBuffer(); - return new MemoizeAllIterable(it, buffer); - } - /** - * Merges a bunch of iterable streams where each of the iterable will run by - * a scheduler and their events are merged together in a single stream. - * The returned iterator throws an UnsupportedOperationException in its remove() method. - * @param the element type - * @param sources the iterable of source iterables. - * @return the new iterable - */ - - public static Iterable merge( - final Iterable> sources) { - return merge(sources, scheduler()); - } - /** - * Merges a bunch of iterable streams where each of the iterable will run by - * a scheduler and their events are merged together in a single stream. - * The returned iterator throws an UnsupportedOperationException in its remove() method. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param sources the iterable of source iterables. - * @param scheduler the scheduler for running each inner iterable in parallel - * @return the new iterable - */ - - public static Iterable merge( - final Iterable> sources, - final Scheduler scheduler) { - return new MergeIterable(scheduler, sources); - } - /** - * Merges two iterable streams. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param first the first iterable - * @param second the second iterable - * @return the resulting stream of Ts - */ - - public static Iterable merge( - final Iterable first, - final Iterable second) { - List> list = new ArrayList>(2); - list.add(first); - list.add(second); - return merge(list); - } - /** - * Returns the minimum value of the given iterable source. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type, which must be self comparable - * @param source the source elements - * @return the new iterable - */ - - public static > Iterable min( - final Iterable source) { - return aggregate(source, IxHelperFunctions.min(), IxHelperFunctions.identityFirst()); - } - /** - * Returns the minimum value of the given iterable source in respect to the supplied comparator. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type, which must be self comparable - * @param source the source elements - * @param comparator the comparator to use - * @return the new iterable - */ - - public static Iterable min( - final Iterable source, - final Comparator comparator) { - return aggregate(source, IxHelperFunctions.min(comparator), IxHelperFunctions.identityFirst()); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type, which must be self comparable - * @param source the source of Ts - * @return the new iterable - */ - - public static > Iterable> minBy( - final Iterable source) { - return minMax(source, IxHelperFunctions.identity(), IxHelperFunctions.comparator(), false); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied comparator. - * @param the source element type - * @param source the source of Ts - * @param comparator the key comparator - * @return the new iterable - */ - - public static Iterable> minBy( - final Iterable source, - final Comparator comparator) { - return minMax(source, IxHelperFunctions.identity(), comparator, false); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the key type, which must be self-comparable - * @param source the source of Ts - * @param keySelector the selector for keys - * @return the new iterable - */ - - public static > Iterable> minBy( - final Iterable source, - final Func1 keySelector) { - return minMax(source, keySelector, IxHelperFunctions.comparator(), false); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector and comparator. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the key type - * @param source the source of Ts - * @param keySelector the selector for keys - * @param keyComparator the key comparator - * @return the new iterable - */ - - public static Iterable> minBy( - final Iterable source, - final Func1 keySelector, - final Comparator keyComparator) { - return minMax(source, keySelector, keyComparator, false); - } - /** - * Returns an iterator which will produce a single List of the minimum values encountered - * in the source stream based on the supplied key selector and comparator. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the key type - * @param source the source of Ts - * @param keySelector the selector for keys - * @param keyComparator the key comparator - * @param max should the computation return the minimums or the maximums - * @return the new iterable - */ - - static Iterable> minMax( - final Iterable source, - final Func1 keySelector, - final Comparator keyComparator, - final boolean max) { - return new MinMaxIterable(keySelector, source, max, keyComparator); - } - /** - * Wraps the given source sequence into a CloseableIterable instance - * where the inner CloseableIterator.close() method calls the supplied action. - * @param the element type - * @param src the source sequence - * @param close the close action. - * @return the new closeable iterable - */ - public static CloseableIterable newCloseableIterable( - final Iterable src, - final Action0 close - ) { - return new CloseableIterable() { - @Override - public CloseableIterator iterator() { - return newCloseableIterator(src.iterator(), close); - } - }; - } - /** - * Wraps the given source sequence into a CloseableIterable instance - * where the inner CloseableIterator.close() method calls the supplied action. - * @param the element type - * @param src the source sequence - * @param close the close action. - * @return the new closeable iterable - */ - - public static CloseableIterable newCloseableIterable( - final Iterable src, - final Action1> close - ) { - return new CloseableIterable() { - @Override - public CloseableIterator iterator() { - return newCloseableIterator(src.iterator(), close); - } - }; - } - /** - * Wraps the given source sequence into a CloseableIterable instance - * where the inner CloseableIterator.close() method calls the supplied closeable object. - * @param the element type - * @param src the source sequence - * @param close the closeable object. - * @return the new closeable iterable - */ - - public static CloseableIterable newCloseableIterable( - final Iterable src, - final Closeable close - ) { - return new CloseableIterable() { - @Override - public CloseableIterator iterator() { - return newCloseableIterator(src.iterator(), close); - } - }; - } - /** - * Wraps the supplied iterator into a CloseableIterator which calls the supplied - * close action. - * @param the element type - * @param src the source iterator - * @param close the close action - * @return the new closeable iterator - */ - - public static CloseableIterator newCloseableIterator( - final Iterator src, - final Action0 close - ) { - return new CloseableIterator() { - final AtomicBoolean once = new AtomicBoolean(); - @Override - public boolean hasNext() { - return src.hasNext(); - } - - @Override - public boolean isUnsubscribed() { - return once.get(); - } - - @Override - public T next() { - return src.next(); - } - - @Override - public void remove() { - src.remove(); - } - @Override - public void unsubscribe() { - if (once.compareAndSet(false, true)) { - close.call(); - } - } - }; - } - /** - * Wraps the supplied iterator into a CloseableIterator which calls the supplied - * close action with the given source iterator object. - * @param the element type - * @param src the source iterator - * @param close the close action - * @return the new closeable iterator - */ - - public static CloseableIterator newCloseableIterator( - final Iterator src, - final Action1> close - ) { - return new CloseableIterator() { - final AtomicBoolean once = new AtomicBoolean(); - @Override - public boolean hasNext() { - return src.hasNext(); - } - - @Override - public boolean isUnsubscribed() { - return once.get(); - } - - @Override - public T next() { - return src.next(); - } - - @Override - public void remove() { - src.remove(); - } - @Override - public void unsubscribe() { - if (once.compareAndSet(false, true)) { - close.call(src); - } - } - }; - } - /** - * Wraps the supplied iterator into a CloseableIterator which calls the supplied - * closeable instance. - * @param the element type - * @param src the source iterator - * @param close the closeable instance - * @return the new closeable iterator - */ - public static CloseableIterator newCloseableIterator( - final Iterator src, - final Closeable close - ) { - return new CloseableIterator() { - final AtomicBoolean once = new AtomicBoolean(); - @Override - public boolean hasNext() { - return src.hasNext(); - } - - @Override - public boolean isUnsubscribed() { - return once.get(); - } - - @Override - public T next() { - return src.next(); - } - - @Override - public void remove() { - src.remove(); - } - @Override - public void unsubscribe() { - if (once.compareAndSet(false, true)) { - try { - close.close(); - } catch (IOException ex) { - //ignored - } - } - } - - }; - } - /** - * Creates a new iterable sequence by wrapping the given function to - * provide the iterator. - * @param the element type - * @param the iterator type - * @param body the body function returning an iterator - * @return the iterable sequence - */ - public static > Iterable newIterable( - final Func0 body) { - return new Iterable() { - @Override - public Iterator iterator() { - return body.call(); - } - }; - } - /** - * A functional way of creating a new iterator from the supplied - * hasNext and next callbacks. - *

The returned iterator throws a UnsupportedOperationException - * in its remove method.

- * @param the element type - * @param hasNext function that returns true if more elements are available. - * @param next function that returns the next element - * @return the created iterator - */ - public static Iterator newIterator( - final Func0 hasNext, - final Func0 next) { - return new Iterator() { - @Override - public boolean hasNext() { - return hasNext.call(); - } - @Override - public T next() { - return next.call(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - /** - * Constructs an iterator instance by wrapping the supplied functions - * into the same-named iterator methods. - * @param the element type - * @param hasNext function that returns true if more elements are available. - * @param next function that returns the next element - * @param remove function to remove the current element - * @return the created iterator - */ - public static Iterator newIterator( - final Func0 hasNext, - final Func0 next, - final Action0 remove - ) { - return new Iterator() { - @Override - public boolean hasNext() { - return hasNext(); - } - @Override - public T next() { - return next.call(); - } - @Override - public void remove() { - remove.call(); - } - }; - } - /** - * Creates an onCompleted notification. - * @param the value type - * @return the notification - */ - static Notification none() { - return Notification.createOnCompleted(); - } - /** - * Casts the source iterable into a different type by using a type token. - * If the source contains a wrong element, the next() - * will throw a ClassCastException. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the result element type - * @param source the arbitrary source - * @param token the type token - * @return the new iterable - */ - - public static Iterable ofType( - final Iterable source, - final Class token) { - return new CastIterable(source, token); - } - /** - * Creates an iterable which if iterates over the source and encounters an exception, - * the iteration is continued on the new iterable returned by the handler function. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the element type - * @param source the source iterable. - * @param handler the exception handler. - * @return the new iterable - */ - - public static Iterable onErrorResumeNext( - final Iterable source, - final Func1> handler) { - return new OnErrorResumeNextIterable(source, handler); - } - /** - * Creates an iterable which if iterates over the source and encounters an exception, it simply stops the iteration, consuming the exception. - * @param the element type - * @param source the source iterable. - * @return the new iterable - */ - - public static Iterable onErrorTerminate( - final Iterable source) { - Iterable e = empty(); - return onErrorResumeNext(source, IxHelperFunctions.constant(e)); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the source element type, must be self comparable - * @param source the source of Ts - * @return the new iterable - */ - - public static > Iterable orderBy( - final Iterable source - ) { - return orderBy(source, IxHelperFunctions.identity(), IxHelperFunctions.comparator()); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the source element type, must be self comparable - * @param source the source of Ts - * @param comparator the value comparator - * @return the new iterable - */ - - public static Iterable orderBy( - final Iterable source, - final Comparator comparator - ) { - return orderBy(source, IxHelperFunctions.identity(), comparator); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the source element type - * @param the key type for the ordering, must be self comparable - * @param source the source of Ts - * @param keySelector the key selector for comparison - * @return the new iterable - */ - - public static > Iterable orderBy( - final Iterable source, - final Func1 keySelector - ) { - return orderBy(source, keySelector, IxHelperFunctions.comparator()); - } - /** - * Returns an iterable which traverses the entire - * source iterable and creates an ordered list - * of elements. Once the source iterator completes, - * the elements are streamed to the output. - * @param the source element type - * @param the key type for the ordering - * @param source the source of Ts - * @param keySelector the key selector for comparison - * @param keyComparator the key comparator function - * @return the new iterable - */ - - public static Iterable orderBy( - final Iterable source, - final Func1 keySelector, - final Comparator keyComparator - ) { - return new OrderByIterable(source, keyComparator, keySelector); - } - /** - * Creates an observer with debugging purposes. - * It prints the submitted values to STDOUT separated by commas and line-broken by 80 characters, the exceptions to STDERR - * and prints an empty newline when it receives a finish(). - * @param the value type - * @return the observer - */ - - public static Action1 print() { - return print(", ", 80); - } - /** - * Creates an observer with debugging purposes. - * It prints the submitted values to STDOUT, the exceptions to STDERR - * and prints an empty newline when it receives a finish(). - * @param the value type - * @param separator the separator to use between subsequent values - * @param maxLineLength how many characters to print into each line - * @return the observer - */ - - public static Action1 print(final String separator, final int maxLineLength) { - return new PrintAction1(separator, maxLineLength); - } - /** - * Creates an action for debugging purposes. - * It prints the submitted values to STDOUT with a line break. - * @param the value type - * @return the observer - */ - - public static Action1 println() { - return new Action1() { - @Override - public void call(T value) { - System.out.println(value); - } - }; - } - /** - * Creates an action for debugging purposes. - * It prints the submitted values to STDOUT with a line break. - * @param the value type - * @param prefix the prefix to use when printing - * @return the action - */ - - public static Action1 println(final String prefix) { - return new Action1() { - @Override - public void call(T value) { - System.out.print(prefix); - System.out.println(value); - } - }; - } - /** - * Applies the func function for a shared instance of the source, - * e.g., func.call(share(source)). - * @param the source element type - * @param the return types - * @param source the source of Ts - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - */ - - public static Iterable prune( - final Iterable source, - final Func1, ? extends Iterable> func) { - return func.call(share(source)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the same cached values. - *

The returned iterator will throw an UnsupportedOperationException - * for remove() method of its first element, then it might throw for any - * subsequent element, depending on the source iterable.

- * @param the source element type - * @param the return types - * @param source the source of Ts - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @param initial the initial value to append to the output stream - * @return the new iterable - */ - @SuppressWarnings("unchecked") - - public static Iterable publish( - final Iterable source, - final Func1, ? extends Iterable> func, - final U initial) { - return startWith(func.call(memoizeAll(source)), initial); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the return types - * @param source the source of Ts - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - * TODO check - */ - - public static Iterable publish( - final Iterable source, - final Func1, ? extends Iterable> func) { - return func.call(memoizeAll(source)); - } - /** - * Creates an integer iterator which returns numbers from the start position in the count size. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param start the starting value. - * @param count the number of elements to return, negative count means counting down from the start. - * @return the iterator. - */ - - public static Iterable range(final int start, final int count) { - return new RangeIterable(start, count); - } - /** - * Creates an long iterator which returns numbers from the start position in the count size. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param start the starting value. - * @param count the number of elements to return, negative count means counting down from the start. - * @return the iterator. - */ - - public static Iterable range(final long start, final long count) { - return new LongRangeIterable(start, count); - } - /** - * Relays the source iterable's values until the gate returns false. - * @param the source element type - * @param source the source of Ts - * @param gate the gate to stop the relaying - * @return the new iterable - */ - - public static Iterable relayWhile( - final Iterable source, - final Func0 gate) { - return filterIndexed(source, new Func0>() { - @Override - public Func2 call() { - return new Func2() { - /** The activity checker which turns to false once the gate returns false. */ - boolean active = true; - @Override - public Boolean call(Integer param1, T param2) { - active &= gate.call(); - return active; - } - }; - } - }); - } - /** - * Creates an iterable sequence which returns the given value indefinitely. - *

(E.g., having the hasNext() always return true and the next() always return the value.

- *

The returned iterable does not support the {@code remove()} method.

- * @param the value type - * @param value the value to repeat - * @return the iterable - */ - public static Iterable repeat(final T value) { - return new RepeatIterable(value); - } - /** - * Returns an iterable which repeats the given single value the specified number of times. - *

The returned iterable does not support the {@code remove()} method.

- * @param the value type - * @param value the value to repeat - * @param count the repeat amount - * @return the iterable - */ - public static Iterable repeat(final T value, final int count) { - return new RepeatCountIterable(count, value); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator may only see one source element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the return types - * @param source the source of Ts - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @return the new iterable - */ - - public static Iterable replay( - final Iterable source, - final Func1, ? extends Iterable> func) { - return func.call(memoize(source, 0)); - } - /** - * The returned iterable ensures that the source iterable is only traversed once, regardless of - * how many iterator attaches to it and each iterator see only the some cached values. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the source element type - * @param the return types - * @param source the source of Ts - * @param func invoke the function on the buffering iterable and return an iterator over it. - * @param bufferSize the buffer size - * @return the new iterable - */ - - public static Iterable replay( - final Iterable source, - final Func1, ? extends Iterable> func, - final int bufferSize) { - return func.call(memoize(source, bufferSize)); - } - /** - * Creates an iterable which resumes with the next iterable from the sources when one throws an exception or completes normally. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param sources the list of sources to try one after another - * @return the new iterable - */ - - public static Iterable onErrorResumeNext( - final Iterable> sources) { - return new OnErrorResumeNext(sources); - } - /** - * Creates an iterable which resumes with the next iterable from the sources when one throws an exception. - * @param the source element type - * @param first the first source - * @param second the second source - * @return the new iterable - */ - - public static Iterable onErrorResumeNext( - final Iterable first, - final Iterable second) { - List> list = new ArrayList>(2); - list.add(first); - list.add(second); - return onErrorResumeNext(list); - } - /** - * Creates an iterator which attempts to re-iterate the source if it threw an exception. - *

-     * while (count-- > 0) {
-     * 	  try {
-     *        for (T t : source) {
-     *            yield t;
-     *        }
-     *        break;
-     *    } catch (Throwable t) {
-     *        if (count <= 0) {
-     *            throw t;
-     *        }
-     *    }
-     * }
-     * 
- *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source type - * @param source the source of Ts - * @param count the number of retry attempts - * @return the new iterable - */ - - public static Iterable retry( - final Iterable source, - final int count) { - return new RetryIterable(count, source); - } - /** - * Iterates over the given source without using its returned value. - * This method is useful when the concrete values from the iterator - * are not needed but the iteration itself implies some side effects. - * @param source the source iterable to run through - */ - public static void run( - final Iterable source) { - forEach(source, Actions.empty()); - } - /** - * Generates an iterable which acts like a running sum when iterating over the source iterable, e.g., - * For each element in T, it computes a value by using the current aggregation value and returns it. - * The first call to the aggregator function will receive a zero for its first argument. - * @param the source element type - * @param the destination element type - * @param source the source of Ts - * @param aggregator the function which takes the current running aggregation value, the current element and produces a new aggregation value. - * @return the new iterable - * TODO rework - */ - - public static Iterable scan( - final Iterable source, - final Func2 aggregator) { - return scan(source, null, aggregator); - } - /** - * Generates an iterable which acts like a running sum when iterating over the source iterable, e.g., - * For each element in T, it computes a value by using the current aggregation value and returns it. - * The first call to the aggregator function will receive a zero for its first argument. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param the destination element type - * @param source the source of Ts - * @param seed the initial value of the running aggregation - * @param aggregator the function which takes the current running aggregation value, the current element and produces a new aggregation value. - * @return the new iterable - */ - - public static Iterable scan( - final Iterable source, - final U seed, - final Func2 aggregator) { - return new ScanIterable(source, aggregator, seed); - } - /** - * @return the current default pool used by the Observables methods - */ - - static Scheduler scheduler() { - return Schedulers.computation(); - } - /** - * Creates an iterable which returns a stream of Us for each source Ts. - * The iterable stream of Us is returned by the supplied selector function. - *

The returned iterator forwards all remove() calls - * to the current source (which might not accept it). - * @param the source element type - * @param the output element type - * @param source the source - * @param selector the selector for multiple Us for each T - * @return the new iterable - */ - - public static Iterable flatMap( - final Iterable source, - final Func1> selector) { - return new FlatMapIterable(selector, source); - } - /** - * Returns an iterable which ensures the source iterable is - * only traversed once and clients may take values from each other, - * e.g., they share the same iterator. - * @param the source element type - * @param source the source iterable - * @return the new iterable - */ - - public static Iterable share( - final Iterable source) { - return new ShareIterable(source); - } - /** - * Shares the source sequence within the specified - * selector function where each iterator can fetch - * the next element from the source. - * @param the source element type - * @param the result element type - * @param source the source sequence - * @param selector the selector function - * @return the new iterable - * TODO Builder - */ - - public static Iterable share( - final Iterable source, - final Func1, ? extends Iterable> selector - ) { - return new ShareSelectorIterable(source, selector); - } - /** - * Creates an iterable which returns only a single element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param value the value to return - * @return the new iterable - */ - - public static Iterable just(final T value) { - return new JustIterable(value); - } - /** - * Immediately returns the number of elements in {@code iterable}. - * @param iterable the input sequence - * @return the number of elements in the sequence - */ - public static int size(Iterable iterable) { - return first(count(iterable)); - } - - /** - * Skips the specified amount of items at the beginning of the source sequence. - * @param the element type - * @param source the source iterable - * @param num the number of elements to skip - * @return the new iterable - */ - public static Iterable skip(final Iterable source, final int num) { - return new Skip(source, num); - } - - /** - * Returns an iterable which skips the last num elements from the - * source iterable. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @param num the number of elements to skip at the end - * @return the new iterable - */ - - public static Iterable skipLast( - final Iterable source, - final int num) { - return new SkipLastIterable(source, num); - } - /** - * Creates an onNext notification. - * @param the value type - * @param value the value to wrap - * @return the notification - */ - static Notification some(T value) { - return Notification.createOnNext(value); - } - /** - * Returns an iterable which prefixes the source iterable values - * by a constant. - * It is equivalent to concat(singleton(value), source). - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method for the first element, and might - * throw for subsequent elements, depending on the source iterable.

- * @param the element type - * @param source the source iterable - * @param value the value to prefix - * @return the new iterable. - */ - - public static Iterable startWith( - Iterable source, - final T... value) { - return concat(Arrays.asList(value), source); - } - /** - * Creates an iterable which returns two subsequent items from the source - * iterable as pairs of values. If the {@code source} contains zero or one elements, this - * iterable will be empty. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @return the new iterable - */ - public static Iterable> subsequent(final Iterable source) { - return new SubsequentIterable(source); - } - /** - * Creates an iterable which returns {@code count} subsequent items from the source - * iterable as sequence of values. - * If the {@code source} contains less than {@code count} elements, this - * iterable will be empty. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @param count the element count - * @return the new iterable - */ - public static Iterable> subsequent( - final Iterable source, - final int count) { - if (count <= 0) { - throw new IllegalArgumentException("Count must be > 0"); - } - if (count == 1) { - return map(source, new Func1>() { - @Override - public Iterable call(T param1) { - return just(param1); - } - }); - } - return new SubsequentCountIterable(source, count); - } - /** - * Sum the source of Integer values and return it as a single element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source - * @return the new iterable - */ - - public static Iterable sumBigDecimal( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumBigDecimal(), IxHelperFunctions.identityFirst() - ); - } - /** - * Sum the source of Integer values and return it as a single element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source - * @return the new iterable - */ - - public static Iterable sumBigInteger( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumBigInteger(), IxHelperFunctions.identityFirst() - ); - } - /** - * Sum the source of Double values and returns it as a single element. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param source the source - * @return the new iterable - */ - - public static Iterable sumDouble( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumDouble(), IxHelperFunctions.identityFirst() - ); - } - /** - * Sum the source of Float values and returns it as a single element. - * @param source the source - * @return the new iterable - */ - - public static Iterable sumFloat( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumFloat(), IxHelperFunctions.identityFirst() - ); - } - /** - * Sum the source of Integer values and returns it as a single element. - * @param source the source - * @return the new iterable - */ - - public static Iterable sumInt( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumInteger(), IxHelperFunctions.identityFirst() - ); - } - /** - * Computes and signals the sum of the values of the Integer source by using - * a double intermediate representation. - * The source may not send nulls. An empty source produces an empty sum - * @param source the source of integers to aggregate. - * @return the observable for the sum value - */ - - public static Iterable sumIntAsDouble( - final Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Double call(Double param1, Integer param2) { - return param1 + param2; - } - }, - IxHelperFunctions.identityFirst() - ); - } - /** - * Sum the source of Long values and returns it as a single element. - * @param source the source - * @return the new iterable - */ - - public static Iterable sumLong( - Iterable source) { - return aggregate(source, - IxHelperFunctions.sumLong(), IxHelperFunctions.identityFirst() - ); - } - /** - * Computes and signals the sum of the values of the Long sourceby using - * a double intermediate representation. - * The source may not send nulls. - * @param source the source of longs to aggregate. - * @return the observable for the sum value - */ - - public static Iterable sumLongAsDouble( - final Iterable source) { - return aggregate(source, - new Func2() { - @Override - public Double call(Double param1, Long param2) { - return param1 + param2; - } - }, - IxHelperFunctions.identityFirst() - ); - } - /** - * Returns an iterable, which will query the selector for a key, then - * queries the map for an Iterable. The returned iterator will - * then traverse that Iterable. If the map does not contain an - * element, az empty iterable is used. - * @param the key type - * @param the output type - * @param selector the key selector - * @param options the available options in - * @return the new iterable - */ - - public static Iterable switchCase( - final Func0 selector, - final Map> options) { - return new SwitchCaseIterable(selector, options); - - } - /** - * Returns the iterable which returns the first num element. - * from the source iterable. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param source the source of Ts - * @param num the number of items to take - * @return the new iterable - */ - - public static Iterable take( - final Iterable source, - final int num) { - return new TakeIterable(num, source); - } - /** - * Returns an iterable which takes only the last num elements from the - * source iterable. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param source the source iterable - * @param num the number of elements to skip at the end - * @return the new iterable - */ - - public static Iterable takeLast( - final Iterable source, - final int num) { - return new TakeLastIterable(source, num); - } - /** - * Returns an iterator which will throw the given - * Throwable exception when the client invokes - * next() the first time. Any subsequent - * next() call will simply throw a NoSuchElementException. - * Calling remove() will always throw a IllegalStateException. - * If the given Throwable instance extends a RuntimeException, it is throws - * as is, but when the throwable is a checked exception, it is wrapped - * into a RuntimeException. - * @param the element type, irrelevant - * @param t the exception to throw - * @return the new iterable - */ - - public static Iterable error( - final Throwable t) { - return new ErrorIterable(t); - } - /** - * Convert the source Iterable into the Enumerable semantics. - * @param the source element type - * @param e the iterable - * @return the new enumerable - */ - - public static Enumerable toEnumerable( - final Iterable e) { - return new Enumerable() { - @Override - - public Enumerator enumerator() { - return toEnumerator(e.iterator()); - } - }; - } - /** - * Convert the given iterator to the Enumerator semantics. - * @param the element type - * @param it the source iterator - * @return the new enumerator - */ - - public static Enumerator toEnumerator( - final Iterator it) { - return new IteratorToEnumerator(it); - } - /** - * Convert the source enumerable into the Iterable semantics. - * @param the source element type - * @param e the enumerable - * @return the new iterable - */ - - public static Iterable toIterable( - final Enumerable e) { - return new Iterable() { - @Override - public Iterator iterator() { - return toIterator(e.enumerator()); - } - }; - } - /** - * Takes the input elements and returns an iterable which - * traverses the array. The supplied array is - * shared by the iterator. Any changes to the array will be - * reflected by the iterator - *

The resulting {@code Iterable} does not support {@code remove()}.

- * @param the element type - * @param ts the input array - * @return the iterable for the array - */ - - public static Iterable toIterable(final T... ts) { - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - /** The current location. */ - int index; - /** The lenght. */ - final int size = ts.length; - @Override - public boolean hasNext() { - return index < size; - } - @Override - public T next() { - if (hasNext()) { - return ts[index++]; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - /** - * Takes the input elements and returns an iterable which - * traverses the array between the two indexes. The supplied array is - * shared by the iterator. Any changes to the array will be - * reflected by the iterator. - *

The resulting {@code Iterable} does not support {@code remove()}.

- * @param the element type - * @param from the starting index inclusive - * @param to the end index exclusive - * @param ts the input array - * @return the iterable for the array - */ - - public static Iterable toIterablePart( - final int from, - final int to, - final T... ts) { - return new PartialIterable(from, ts, to); - } - /** - * Convert the given enumerator to the Iterator semantics. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the element type - * @param en the source enumerator - * @return the new iterator - */ - - public static Iterator toIterator( - final Enumerator en) { - return new EnumerationToIterator(en); - } - /** - * Call unsubscribe on the iterator if it implements the Subscription interface. - * @param iter the iterator to unsubscribe - */ - public static void unsubscribe(Iterator iter) { - if (iter instanceof Subscription) { - ((Subscription)iter).unsubscribe(); - } - } - /** - * Returns an iterable which is associated with a closeable handler. - * Once the source iterable is completed, it invokes the Closeable.close() on the handler. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the source element type - * @param the closeable type - * @param resource the function which returns a resource token - * @param usage the function which gives an iterable for a resource token. - * @return the new iterable - */ - - public static Iterable using( - final Func0 resource, - final Func1> usage) { - return new UsingIterable(resource, usage); - } - /** - * Extracts the notification value, exception or throws NoSuchElementException. - * @param the value type - * @param notif the notification to extract from - * @return the value - */ - static T value(Notification notif) { - if (notif.isOnNext()) { - return notif.getValue(); - } else - if (notif.isOnError()) { - Exceptions.propagate(notif.getThrowable()); - } - throw new NoSuchElementException(); - } - /** - * Creates an iterable which filters the source iterable with the - * given predicate factory function. The predicate returned by the factory receives an index - * telling how many elements were processed thus far. - * Use this construct if you want to use some memorizing predicate function (e.g., filter by subsequent distinct, filter by first occurrences only) - * which need to be invoked per iterator() basis. - *

The returned iterator forwards all remove() calls - * to the source.

- * @param the element type - * @param source the source iterable - * @param predicateFactory the predicate factory which should return a new predicate function for each iterator. - * @return the new iterable - */ - - public static Iterable filterIndexed( - final Iterable source, - final Func0> predicateFactory) { - return new FilterIndexedIterable(source, predicateFactory); - } - /** - * Creates an iterable which filters the source iterable with the - * given predicate function. The predicate receives the value and - * must return a boolean whether to accept that entry. - * @param the element type - * @param source the source iterable - * @param predicate the predicate function - * @return the new iterable - */ - - public static Iterable filter( - final Iterable source, - final Func1 predicate) { - return filterIndexed(source, IxHelperFunctions.constant0(new Func2() { - @Override - public Boolean call(Integer param1, T param2) { - return predicate.call(param2); - } - })); - } - /** - * Creates an iterable which filters the source iterable with the - * given predicate factory function. The predicate returned by the factory receives an index - * telling how many elements were processed thus far. - * @param the element type - * @param source the source iterable - * @param predicate the predicate - * @return the new iterable - */ - - public static Iterable filterIndexed( - final Iterable source, - final Func2 predicate) { - return filterIndexed(source, IxHelperFunctions.constant0(predicate)); - } - /** - * Pairs each element from both iterable sources and - * combines them into a new value by using the combiner - * function. - *

The returned iterator will throw an UnsupportedOperationException - * for its remove() method.

- * @param the left source type - * @param the right source type - * @param the result type - * @param left the left source - * @param right the right source - * @param combiner the combiner function - * @return the new iterable - */ - - public static Iterable zip( - final Iterable left, - final Iterable right, - final Func2 combiner) { - return new ZipIterable(left, right, combiner); - } - /** The common empty iterator. */ - private static final Iterator EMPTY_ITERATOR = new Iterator() { - @Override - public boolean hasNext() { - return false; - } - @Override - public Object next() { - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new IllegalStateException(); - } - }; - /** The common empty iterable. */ - private static final Iterable EMPTY_ITERABLE = new Iterable() { - @Override - public Iterator iterator() { - return EMPTY_ITERATOR; - } - }; - - // TODO IBuffer publish(Iterable) - - // TODO memoize(Iterable) - - // TODO memoize(Iterable, Func) - - // TODO memoize(Iterable, int, Func) - - // TODO throwException(Func) - - // TODO catchException(Iterable>) - - // TODO catchException(Iterable, Iterable) - - // TODO retry(Iterable) - - // TODO resumeOnError(Iterable...) - - // TODO ifThen(Func, Iterable) - - // TODO ifThen(Func, Iterable, Iterable) - - // TODO whileDo(Func, Iterable) - - // TODO switchCase(Func, Map>, Iterable) - - // TODO selectMany(Iterable, Iterable) - - // TODO forEach(Iterable, Action) - - // TODO forEach(Iterable, Action) - - // TODO invoke(Iterable, Observer) - - // TODO buffer(Iterable, int, int) - - // TODO ignoreValues(Iterable) - - // TODO distinct(Iterable, Func2) - - // TODO distinct(Iterable, Func, Func) - - // TODO distinctNext(Iterable, Func, Func, Func>) - - // TODO repeat(Iterable) - - // TODO repeat(Iterable, count) - - /** Utility class. */ - private Interactive() { - // utility class - } -} diff --git a/src/main/java/ix/internal/operators/IteratorToEnumerator.java b/src/main/java/ix/internal/operators/IteratorToEnumerator.java deleted file mode 100644 index 2c03de0..0000000 --- a/src/main/java/ix/internal/operators/IteratorToEnumerator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.Enumerator; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public final class IteratorToEnumerator implements Enumerator { - /** The source sequence. */ - private final Iterator it; - /** The current value. */ - T value; - /** The current value is set. */ - boolean hasValue; - - public IteratorToEnumerator(Iterator it) { - this.it = it; - } - - @Override - public T current() { - if (hasValue) { - return value; - } - throw new NoSuchElementException(); - } - - @Override - public boolean next() { - if (it.hasNext()) { - value = it.next(); - hasValue = true; - return false; - } - hasValue = false; - return false; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/JustIterable.java b/src/main/java/ix/internal/operators/JustIterable.java deleted file mode 100644 index a43e71f..0000000 --- a/src/main/java/ix/internal/operators/JustIterable.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence with a specific single value. - * - * @param the value type - */ -public final class JustIterable implements Iterable { - /** The value to return. */ - private final T value; - /** - * Constructor with the single value. - * @param value the value - */ - public JustIterable(T value) { - this.value = value; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** Return the only element? */ - boolean first = true; - @Override - public boolean hasNext() { - return first; - } - - @Override - public T next() { - if (first) { - first = false; - return value; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/LongCountIterable.java b/src/main/java/ix/internal/operators/LongCountIterable.java deleted file mode 100644 index 86978b5..0000000 --- a/src/main/java/ix/internal/operators/LongCountIterable.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class LongCountIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - - public LongCountIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator iterator() { - final Iterator it = source.iterator(); - return new Iterator() { - /** The peek ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - /** Computation already done. */ - boolean done; - @Override - public boolean hasNext() { - if (!done) { - if (peek.isEmpty()) { - long count = 0; - try { - while (it.hasNext()) { - it.next(); - count++; - } - peek.add(Interactive.some(count)); - } catch (Throwable t) { - peek.add(Interactive.err(t)); - } finally { - done = true; - Interactive.unsubscribe(it); - } - } - } - return !peek.isEmpty(); - } - - @Override - public Long next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/LongRangeIterable.java b/src/main/java/ix/internal/operators/LongRangeIterable.java deleted file mode 100644 index 09ad5d9..0000000 --- a/src/main/java/ix/internal/operators/LongRangeIterable.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence with long values from a start value producing count values. - */ -public final class LongRangeIterable implements Iterable { - /** The start value. */ - private final long start; - /** The number of elements to return. */ - private final long count; - /** - * Constructor, sets the fields. - * @param start the start value - * @param count number of values - */ - public LongRangeIterable(long start, long count) { - this.start = start; - this.count = count; - } - - @Override - public Iterator iterator() { - return new Iterator() { - long current = start; - @Override - public boolean hasNext() { - return current < start + count; - } - @Override - public Long next() { - if (hasNext()) { - return current++; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MapIndexedIterable.java b/src/main/java/ix/internal/operators/MapIndexedIterable.java deleted file mode 100644 index 49b9444..0000000 --- a/src/main/java/ix/internal/operators/MapIndexedIterable.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -import rx.functions.Func2; - -public final class MapIndexedIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func2 selector; - - public MapIndexedIterable(Iterable source, - Func2 selector) { - this.source = source; - this.selector = selector; - } - - @Override - public Iterator iterator() { - final Iterator it = source.iterator(); - return new Iterator() { - /** The current counter. */ - int count; - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public U next() { - return selector.call(count++, it.next()); - } - - @Override - public void remove() { - it.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MaterializeIterable.java b/src/main/java/ix/internal/operators/MaterializeIterable.java deleted file mode 100644 index 523fe1a..0000000 --- a/src/main/java/ix/internal/operators/MaterializeIterable.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class MaterializeIterable implements Iterable> { - /** The source sequence. */ - private final Iterable source; - - public MaterializeIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator> iterator() { - final Iterator it = source.iterator(); - return new Iterator>() { - /** The peeked value or exception. */ - final SingleContainer> peek = new SingleContainer>(); - /** The source iterator threw an exception. */ - boolean broken; - @Override - public boolean hasNext() { - if (!broken) { - try { - if (peek.isEmpty()) { - if (it.hasNext()) { - T t = it.next(); - peek.add(Interactive.some(t)); - } else { - peek.add(Interactive.none()); - broken = true; - } - } - } catch (Throwable t) { - broken = true; - peek.add(Interactive.err(t)); - } - } - return !peek.isEmpty(); - } - - @Override - public Notification next() { - if (hasNext()) { - return peek.take(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MemoizeAllIterable.java b/src/main/java/ix/internal/operators/MemoizeAllIterable.java deleted file mode 100644 index 99aa87e..0000000 --- a/src/main/java/ix/internal/operators/MemoizeAllIterable.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.LinkedBuffer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public final class MemoizeAllIterable implements Iterable { - /** The source sequence. */ - private final Iterator it; - private final LinkedBuffer buffer; - - public MemoizeAllIterable(Iterator it, - LinkedBuffer buffer) { - this.it = it; - this.buffer = buffer; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The element count. */ - int count = 0; - /** The current node pointer. */ - LinkedBuffer.N pointer = buffer.head; - @Override - public boolean hasNext() { - return count < buffer.size || it.hasNext(); - } - - @Override - public T next() { - if (hasNext()) { - if (count < buffer.size) { - T value = pointer.next.value; - pointer = pointer.next; - count++; - return value; - } else { - T value = it.next(); - buffer.add(value); - count++; - pointer = pointer.next; - return value; - } - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MemoizeIterable.java b/src/main/java/ix/internal/operators/MemoizeIterable.java deleted file mode 100644 index 29114f1..0000000 --- a/src/main/java/ix/internal/operators/MemoizeIterable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.CircularBuffer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Memoizes the source sequence with a given buffer size. - * - * @param the element type - */ -public final class MemoizeIterable implements Iterable { - /** The buffer size. */ - private final int bufferSize; - /** The source iterator. */ - Iterator it; - /** The ring buffer of the memory. */ - final CircularBuffer buffer; - /** - * Constructor, sets the buffer size and takes an iterator from source. - * @param source the source iterable - * @param bufferSize the buffer size - */ - public MemoizeIterable(Iterable source, int bufferSize) { - this.bufferSize = bufferSize; - it = source.iterator(); - buffer = new CircularBuffer(bufferSize); - } - - @Override - public Iterator iterator() { - return new Iterator() { - int myHead; - - @Override - public boolean hasNext() { - return buffer.tail() > Math.max(myHead, buffer.head()) || it.hasNext(); - } - - @Override - public T next() { - if (hasNext()) { - if (buffer.tail() == myHead) { - T value = it.next(); - if (bufferSize > 0) { - buffer.add(value); - } - myHead++; - return value; - } else { - myHead = Math.max(myHead, buffer.head()); - T value = buffer.get(myHead); - myHead++; - return value; - } - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MergeIterable.java b/src/main/java/ix/internal/operators/MergeIterable.java deleted file mode 100644 index f2e5087..0000000 --- a/src/main/java/ix/internal/operators/MergeIterable.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicInteger; - -import rx.Notification; -import rx.Scheduler; -import rx.functions.Action0; -import rx.internal.util.SubscriptionList; - -public final class MergeIterable implements Iterable { - private final Scheduler scheduler; - /** The source sequences. */ - private final Iterable> sources; - - public MergeIterable(Scheduler scheduler, - Iterable> sources) { - this.scheduler = scheduler; - this.sources = sources; - } - - @Override - public Iterator iterator() { - final BlockingQueue> queue = new LinkedBlockingQueue>(); - final AtomicInteger wip = new AtomicInteger(1); - final SubscriptionList handlers = new SubscriptionList(); - final Scheduler.Worker worker = scheduler.createWorker(); - handlers.add(worker); - for (final Iterable iter : sources) { - Action0 r = new Action0() { - @Override - public void call() { - try { - final Iterator fiter = iter.iterator(); - try { - while (fiter.hasNext()) { - T t = fiter.next(); - if (!Thread.currentThread().isInterrupted()) { - queue.add(Interactive.some(t)); - } - } - } finally { - Interactive.unsubscribe(fiter); - } - if (wip.decrementAndGet() == 0) { - if (!Thread.currentThread().isInterrupted()) { - queue.add(Interactive.none()); - } - } - } catch (Throwable t) { - queue.add(Interactive.err(t)); - } - } - }; - wip.incrementAndGet(); - handlers.add(worker.schedule(r)); - } - if (wip.decrementAndGet() == 0) { - queue.add(Interactive.none()); - } - return new Iterator() { - final SingleContainer> peek = new SingleContainer>(); - /** Are we broken? */ - boolean broken; - @Override - public boolean hasNext() { - if (!broken) { - if (peek.isEmpty()) { - try { - Notification t = queue.take(); - if (t.isOnNext()) { - peek.add(t); - } else - if (t.isOnError()) { - peek.add(t); - broken = true; - } - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - return false; // FIXME not sure about this - } - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - try { - return Interactive.value(peek.take()); - } catch (RuntimeException ex) { - handlers.unsubscribe(); - throw ex; - } - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/MinMaxIterable.java b/src/main/java/ix/internal/operators/MinMaxIterable.java deleted file mode 100644 index cd5803e..0000000 --- a/src/main/java/ix/internal/operators/MinMaxIterable.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import rx.Notification; -import rx.functions.Func1; - -/** - * Iterable sequence that returns the minimum or maximum of the source sequence - * according to a key selector and key comparator. - * - * @param the source value type - * @param the key value type - */ -public final class MinMaxIterable implements Iterable> { - /** Returns a key for a value. */ - private final Func1 keySelector; - /** The source sequence. */ - private final Iterable source; - /** Find the maximum? */ - private final boolean max; - /** Compares two keys. */ - private final Comparator keyComparator; - - /** - * Constructor, initializes the fields. - * @param keySelector the key selector function - * @param source the source sequenec - * @param max find the maximum? - * @param keyComparator the key comparator function - */ - public MinMaxIterable(Func1 keySelector, - Iterable source, boolean max, - Comparator keyComparator) { - this.keySelector = keySelector; - this.source = source; - this.max = max; - this.keyComparator = keyComparator; - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The single result container. */ - final SingleContainer>> result = new SingleContainer>>(); - /** We have finished the aggregation. */ - boolean done; - @Override - public boolean hasNext() { - if (!done) { - done = true; - if (result.isEmpty()) { - try { - List intermediate = null; - U lastKey = null; - try { - while (it.hasNext()) { - T value = it.next(); - U key = keySelector.call(value); - if (intermediate == null) { - intermediate = new ArrayList(); - lastKey = key; - intermediate.add(value); - } else { - int c = keyComparator.compare(lastKey, key); - if ((c < 0 && max) || (c > 0 && !max)) { - intermediate = new ArrayList(); - lastKey = key; - c = 0; - } - if (c == 0) { - intermediate.add(value); - } - } - } - } finally { - Interactive.unsubscribe(it); - } - if (intermediate != null) { - result.add(Interactive.some(intermediate)); - } - } catch (Throwable t) { - result.add(Interactive.>err(t)); - } - } - } - return !result.isEmpty(); - } - - @Override - public List next() { - if (hasNext()) { - return Interactive.value(result.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/OnErrorResumeNext.java b/src/main/java/ix/internal/operators/OnErrorResumeNext.java deleted file mode 100644 index 59df97a..0000000 --- a/src/main/java/ix/internal/operators/OnErrorResumeNext.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class OnErrorResumeNext implements Iterable { - /** The source sequences. */ - private final Iterable> sources; - - public OnErrorResumeNext( - Iterable> sources) { - this.sources = sources; - } - - @Override - public Iterator iterator() { - final Iterator> iter0 = sources.iterator(); - if (iter0.hasNext()) { - return new Iterator() { - /** The current iterator. */ - Iterator it = iter0.next().iterator(); - /** The memorized iterator for the remove call. */ - Iterator itForRemove = null; - /** The peek ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - while (!Thread.currentThread().isInterrupted()) { - try { - if (it.hasNext()) { - peek.add(Interactive.some(it.next())); - break; - } else { - if (iter0.hasNext()) { - it = iter0.next().iterator(); - } else { - break; - } - } - } catch (Throwable t) { - if (iter0.hasNext()) { - it = iter0.next().iterator(); - } else { - peek.add(Interactive.err(t)); - break; - } - } - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - itForRemove = it; - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - if (itForRemove == null) { - throw new IllegalStateException(); - } - itForRemove.remove(); - itForRemove = null; - } - }; - } - return Interactive.empty().iterator(); - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/OnErrorResumeNextIterable.java b/src/main/java/ix/internal/operators/OnErrorResumeNextIterable.java deleted file mode 100644 index ab703c1..0000000 --- a/src/main/java/ix/internal/operators/OnErrorResumeNextIterable.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.exceptions.Exceptions; -import rx.functions.Func1; - -public final class OnErrorResumeNextIterable implements - Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func1> handler; - - public OnErrorResumeNextIterable( - Iterable source, - Func1> handler) { - this.source = source; - this.handler = handler; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The current iterator. */ - Iterator it = source.iterator(); - /** The last iterator used by next(). */ - Iterator itForRemove; - /** The peek ahead container. */ - final SingleContainer peek = new SingleContainer(); - /** Indicate that we switched to the handler. */ - boolean usingHandler; - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - while (!Thread.currentThread().isInterrupted()) { - try { - if (it.hasNext()) { - itForRemove = it; - peek.add(it.next()); - } - break; - } catch (Throwable t) { - if (!usingHandler) { - Interactive.unsubscribe(it); - it = handler.call(t).iterator(); - usingHandler = true; - } else { - Exceptions.propagate(t); - } - } - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - return peek.take(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - if (itForRemove == null) { - throw new IllegalStateException(); - } - itForRemove.remove(); - itForRemove = null; - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/OrderByIterable.java b/src/main/java/ix/internal/operators/OrderByIterable.java deleted file mode 100644 index e96c1bc..0000000 --- a/src/main/java/ix/internal/operators/OrderByIterable.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import rx.functions.Func1; - -/** - * Iterable sequence which sorts the source (finite) sequence accoring to the given - * key selector and key comparator functions. - * - * @param the source type - * @param the key type - */ -public final class OrderByIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - /** The key comparator function. */ - private final Comparator keyComparator; - /** The key selector function. */ - private final Func1 keySelector; - /** - * Constructor, initializes the fields. - * @param source the source sequence - * @param keyComparator the key comparator function - * @param keySelector the key selector function - */ - public OrderByIterable(Iterable source, - Comparator keyComparator, - Func1 keySelector) { - this.source = source; - this.keyComparator = keyComparator; - this.keySelector = keySelector; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The buffer. */ - List buffer; - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The buffer iterator. */ - Iterator bufIterator; - @Override - public boolean hasNext() { - if (buffer == null) { - buffer = new ArrayList(); - try { - while (it.hasNext()) { - buffer.add(it.next()); - } - } finally { - Interactive.unsubscribe(it); - } - Collections.sort(buffer, new Comparator() { - @Override - public int compare(T o1, T o2) { - U key1 = keySelector.call(o1); - U key2 = keySelector.call(o2); - return keyComparator.compare(key1, key2); - } - }); - bufIterator = buffer.iterator(); - } - return bufIterator.hasNext(); - } - - @Override - public T next() { - if (hasNext()) { - return bufIterator.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/PartialIterable.java b/src/main/java/ix/internal/operators/PartialIterable.java deleted file mode 100644 index cbd3d4a..0000000 --- a/src/main/java/ix/internal/operators/PartialIterable.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence which returns values from a range in an array of items. - * - * @param the value type - */ -public final class PartialIterable implements Iterable { - /** The source index, inclusive. */ - private final int from; - /** The array of values. */ - private final T[] ts; - /** The destination index, exclusive. */ - private final int to; - /** - * Constructor, initalizes the fields. - * @param from the source index, inclusive - * @param ts the array of values - * @param to the destination index, exclusive - */ - public PartialIterable(int from, T[] ts, int to) { - this.from = from; - this.ts = ts; - this.to = to; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The current location. */ - int index = from; - /** The lenght. */ - final int size = ts.length; - @Override - public boolean hasNext() { - return index < size && index < to; - } - @Override - public T next() { - if (hasNext()) { - return ts[index++]; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/PrintAction1.java b/src/main/java/ix/internal/operators/PrintAction1.java deleted file mode 100644 index c7debe8..0000000 --- a/src/main/java/ix/internal/operators/PrintAction1.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import rx.functions.Action1; -/** - * Helper action that prints elements to the console. - * - * @param the source value type - */ -public final class PrintAction1 implements Action1 { - /** The separator between elements. */ - private final String separator; - /** The maximum length of a line. */ - private final int maxLineLength; - /** Indicator for the first element. */ - boolean first = true; - /** The current line length. */ - int len; - - /** - * Constructor, initializes the fields. - * @param separator the separator between elements - * @param maxLineLength the maximum lenght of a line - */ - public PrintAction1(String separator, int maxLineLength) { - this.separator = separator; - this.maxLineLength = maxLineLength; - } - - @Override - public void call(T value) { - String s = String.valueOf(value); - if (first) { - first = false; - System.out.print(s); - len = s.length(); - } else { - if (len + separator.length() + s.length() > maxLineLength) { - if (len == 0) { - System.out.print(separator); - System.out.print(s); - len = s.length() + separator.length(); - } else { - System.out.println(separator); - System.out.print(s); - len = s.length(); - } - } else { - System.out.print(separator); - System.out.print(s); - len += s.length() + separator.length(); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/RangeIterable.java b/src/main/java/ix/internal/operators/RangeIterable.java deleted file mode 100644 index 7241649..0000000 --- a/src/main/java/ix/internal/operators/RangeIterable.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence of integer values from a start value and count values. - */ -public final class RangeIterable implements Iterable { - /** The start value. */ - private final int start; - /** The number of values. */ - private final int count; - /** - * Constructor, initializes the fields. - * @param start the start value - * @param count the number of elements - */ - public RangeIterable(int start, int count) { - this.start = start; - this.count = count; - } - - @Override - public Iterator iterator() { - return new Iterator() { - int current = start; - @Override - public boolean hasNext() { - return current < start + count; - } - @Override - public Integer next() { - if (hasNext()) { - return current++; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/ReduceIterable.java b/src/main/java/ix/internal/operators/ReduceIterable.java deleted file mode 100644 index 75de92e..0000000 --- a/src/main/java/ix/internal/operators/ReduceIterable.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.*; - -import rx.functions.*; - -/** - * Combines subsequent values into a single value that is then returned. - * @param the source value type - * @since 0.92.3 - */ -public final class ReduceIterable implements Iterable { - - final Iterable source; - - final Func2 reducer; - - public ReduceIterable(Iterable source, Func2 reducer) { - this.source = source; - this.reducer = reducer; - } - - @Override - public Iterator iterator() { - Iterator it = source.iterator(); - - return new ReduceIterator(it, reducer); - } - - static final class ReduceIterator implements Iterator { - final Func2 reducer; - - Iterator it; - - boolean once; - - boolean hasValue; - - T result; - - public ReduceIterator(Iterator it, Func2 reducer) { - this.it = it; - this.reducer = reducer; - } - - @Override - public boolean hasNext() { - if (!once) { - once = true; - - final Iterator o = it; - final Func2 f = reducer; - - if (o.hasNext()) { - T r = o.next(); - - while (o.hasNext()) { - r = f.call(r, o.next()); - } - - result = r; - hasValue = true; - } - } - return hasValue; - } - - @Override - public T next() { - if (hasNext()) { - T c = result; - result = null; - hasValue = false; - return c; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } -} diff --git a/src/main/java/ix/internal/operators/RepeatCountIterable.java b/src/main/java/ix/internal/operators/RepeatCountIterable.java deleted file mode 100644 index 15ae55d..0000000 --- a/src/main/java/ix/internal/operators/RepeatCountIterable.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence which repeates the same value a certain number of times. - * - * @param the value type - */ -public final class RepeatCountIterable implements Iterable { - /** The repeat count. */ - private final int count; - /** The value to repeat. */ - private final T value; - - /** - * Constructor, initializes the fields. - * @param count the repeat count - * @param value the value to repeat - */ - public RepeatCountIterable(int count, T value) { - this.count = count; - this.value = value; - } - - @Override - public Iterator iterator() { - return new Iterator() { - int index; - @Override - public boolean hasNext() { - return index < count; - } - @Override - public T next() { - if (hasNext()) { - index++; - return value; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/RepeatIterable.java b/src/main/java/ix/internal/operators/RepeatIterable.java deleted file mode 100644 index c6aecbb..0000000 --- a/src/main/java/ix/internal/operators/RepeatIterable.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -/** - * Iterable sequence which repeates the same value indefinitely. - * - * @param the value type - */ -public final class RepeatIterable implements Iterable { - /** The value to repeat. */ - private final T value; - /** - * Constructor, sets the value. - * @param value the value to repeat - */ - public RepeatIterable(T value) { - this.value = value; - } - - @Override - public Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - return true; - } - @Override - public T next() { - return value; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/RetryIterable.java b/src/main/java/ix/internal/operators/RetryIterable.java deleted file mode 100644 index 5f1b157..0000000 --- a/src/main/java/ix/internal/operators/RetryIterable.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class RetryIterable implements Iterable { - private final int count; - /** The source sequence. */ - private final Iterable source; - - public RetryIterable(int count, Iterable source) { - this.count = count; - this.source = source; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The retry count. */ - int retries = count; - /** The peek store. */ - final SingleContainer> peek = new SingleContainer>(); - /** The current iterator. */ - Iterator it = source.iterator(); - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - while (it.hasNext()) { - try { - peek.add(Interactive.some(it.next())); - break; - } catch (Throwable t) { - if (retries-- > 0) { - it = source.iterator(); - } else { - peek.add(Interactive.err(t)); - break; - } - } - } - } - return !peek.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/ScanIterable.java b/src/main/java/ix/internal/operators/ScanIterable.java deleted file mode 100644 index 5023cdd..0000000 --- a/src/main/java/ix/internal/operators/ScanIterable.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; - -import rx.functions.Func2; - -public final class ScanIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final Func2 aggregator; - private final U seed; - - public ScanIterable(Iterable source, - Func2 aggregator, U seed) { - this.source = source; - this.aggregator = aggregator; - this.seed = seed; - } - - @Override - public Iterator iterator() { - final Iterator it = source.iterator(); - return new Iterator() { - /** The current value. */ - U current = seed; - - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public U next() { - current = aggregator.call(current, it.next()); - return current; - } - - @Override - public void remove() { - it.remove(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/SkipLastIterable.java b/src/main/java/ix/internal/operators/SkipLastIterable.java deleted file mode 100644 index 1bcb7a9..0000000 --- a/src/main/java/ix/internal/operators/SkipLastIterable.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.CircularBuffer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class SkipLastIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final int num; - - public SkipLastIterable(Iterable source, int num) { - this.source = source; - this.num = num; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The temporary buffer. */ - final CircularBuffer> buffer = new CircularBuffer>(num); - @Override - public boolean hasNext() { - try { - while (buffer.size() < num && it.hasNext()) { - buffer.add(Interactive.some(it.next())); - } - } catch (Throwable t) { - buffer.add(Interactive.err(t)); - } finally { - Interactive.unsubscribe(it); - } - return buffer.size() == num && it.hasNext(); - } - - @Override - public T next() { - if (hasNext()) { - return Interactive.value(buffer.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/SubsequentCountIterable.java b/src/main/java/ix/internal/operators/SubsequentCountIterable.java deleted file mode 100644 index c1cb3eb..0000000 --- a/src/main/java/ix/internal/operators/SubsequentCountIterable.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.NoSuchElementException; - -public final class SubsequentCountIterable implements - Iterable> { - /** The source sequence. */ - private final Iterable source; - private final int count; - - public SubsequentCountIterable(Iterable source, int count) { - this.source = source; - this.count = count; - } - - @Override - public Iterator> iterator() { - // get the first count-1 elements - final LinkedList ll = new LinkedList(); - final Iterator it = source.iterator(); - int cnt = 0; - try { - while (it.hasNext() && cnt < count - 1) { - ll.add(it.next()); - cnt++; - } - } finally { - Interactive.unsubscribe(it); - } - if (cnt < count - 1) { - return Interactive.>empty().iterator(); - } - return new Iterator>() { - @Override - public boolean hasNext() { - return it.hasNext(); - } - @Override - public Iterable next() { - if (hasNext()) { - ll.add(it.next()); - ll.removeFirst(); - return new ArrayList(ll); - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/SubsequentIterable.java b/src/main/java/ix/internal/operators/SubsequentIterable.java deleted file mode 100644 index 87d5fef..0000000 --- a/src/main/java/ix/internal/operators/SubsequentIterable.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.Pair; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public final class SubsequentIterable implements - Iterable> { - /** The source sequence. */ - private final Iterable source; - - public SubsequentIterable(Iterable source) { - this.source = source; - } - - @Override - public Iterator> iterator() { - final Iterator it = source.iterator(); - if (!it.hasNext()) { - return Interactive.>empty().iterator(); - } - final T flast = it.next(); - return new Iterator>() { - /** The last source value. */ - T last = flast; - @Override - public boolean hasNext() { - return it.hasNext(); - } - @Override - public Pair next() { - if (hasNext()) { - T curr = it.next(); - Pair ret = Pair.of(last, curr); - last = curr; - return ret; - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/SwitchCaseIterable.java b/src/main/java/ix/internal/operators/SwitchCaseIterable.java deleted file mode 100644 index 9b6789b..0000000 --- a/src/main/java/ix/internal/operators/SwitchCaseIterable.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.Map; - -import rx.functions.Func0; - -public final class SwitchCaseIterable implements Iterable { - private final Func0 selector; - private final Map> options; - - public SwitchCaseIterable(Func0 selector, Map> options) { - this.selector = selector; - this.options = options; - } - - @Override - public Iterator iterator() { - Iterable it = options.get(selector.call()); - return it != null ? it.iterator() : Interactive.empty().iterator(); - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/TakeIterable.java b/src/main/java/ix/internal/operators/TakeIterable.java deleted file mode 100644 index 30271de..0000000 --- a/src/main/java/ix/internal/operators/TakeIterable.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterable sequence that takes the first elements of the source sequence. - * - * @param the value type - */ -public final class TakeIterable implements Iterable { - /** The number of items to take. */ - private final int num; - /** The source sequence. */ - private final Iterable source; - /** - * Constructor, initializes the fields. - * @param num the number of items to take - * @param source the source sequence - */ - public TakeIterable(int num, Iterable source) { - this.num = num; - this.source = source; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The counter. */ - int count; - /** The source iterator. */ - final Iterator it = source.iterator(); - @Override - public boolean hasNext() { - return count < num && it.hasNext(); - } - - @Override - public T next() { - if (hasNext()) { - count++; - return it.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - it.remove(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/TakeLastIterable.java b/src/main/java/ix/internal/operators/TakeLastIterable.java deleted file mode 100644 index 5c039d2..0000000 --- a/src/main/java/ix/internal/operators/TakeLastIterable.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.CircularBuffer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; - -public final class TakeLastIterable implements Iterable { - /** The source sequence. */ - private final Iterable source; - private final int num; - - public TakeLastIterable(Iterable source, int num) { - this.source = source; - this.num = num; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The source iterator. */ - final Iterator it = source.iterator(); - /** The temporary buffer. */ - final CircularBuffer> buffer = new CircularBuffer>(num); - @Override - public boolean hasNext() { - try { - while (it.hasNext()) { - buffer.add(Interactive.some(it.next())); - } - } catch (Throwable t) { - buffer.add(Interactive.err(t)); - } finally { - Interactive.unsubscribe(it); - } - return !buffer.isEmpty(); - } - - @Override - public T next() { - if (hasNext()) { - return Interactive.value(buffer.take()); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/ToIterable.java b/src/main/java/ix/internal/operators/ToIterable.java deleted file mode 100644 index 006c409..0000000 --- a/src/main/java/ix/internal/operators/ToIterable.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.ObservableToIterableAdapter; -import ix.internal.util.ObserverToIteratorSink; -import ix.internal.util.SingleOption; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -import rx.Notification; -import rx.Observable; -import rx.Subscription; - -/** - * Convert the given observable instance into a classical iterable instance. - *

The resulting iterable does not support the {@code remove()} method.

- * @param the element type to iterate - */ -public final class ToIterable extends ObservableToIterableAdapter { - /** - * Constructor. - * @param observable the observable to convert - */ - public ToIterable(Observable observable) { - super(observable); - } - - @Override - protected ObserverToIteratorSink run(Subscription handle) { - return new ObserverToIteratorSink(handle) { - /** The queue. */ - final BlockingQueue> queue = new LinkedBlockingQueue>(); - @Override - public void onNext(T value) { - queue.add(Notification.createOnNext(value)); - } - - @Override - public void onError(Throwable ex) { - done(); - - queue.add(Notification.createOnError(ex)); - } - - @Override - public void onCompleted() { - done(); - - queue.add(Notification.createOnCompleted()); - } - - @Override - public boolean tryNext(SingleOption out) { - try { - Notification o = queue.take(); - - if (o.isOnCompleted()) { - return false; - } - out.addOption(o); - } catch (InterruptedException ex) { - out.addError(ex); - } - return true; - } - - }; - } -} diff --git a/src/main/java/ix/internal/operators/UsingIterable.java b/src/main/java/ix/internal/operators/UsingIterable.java deleted file mode 100644 index 864fe36..0000000 --- a/src/main/java/ix/internal/operators/UsingIterable.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.CloseableIterator; - -import java.io.Closeable; -import java.io.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.concurrent.atomic.AtomicBoolean; - -import rx.functions.Func0; -import rx.functions.Func1; - -public final class UsingIterable implements Iterable { - private final Func0 resource; - private final Func1> usage; - - public UsingIterable(Func0 resource, - Func1> usage) { - this.resource = resource; - this.usage = usage; - } - - @Override - public Iterator iterator() { - final U c = resource.call(); - return new CloseableIterator() { - /** The iterator. */ - final Iterator it = usage.call(c).iterator(); - /** Run once the it has no more elements. */ - final AtomicBoolean once = new AtomicBoolean(); - @Override - public boolean hasNext() { - if (it.hasNext()) { - return true; - } - unsubscribe(); - return false; - } - - @Override - public boolean isUnsubscribed() { - return once.get(); - } - - @Override - public T next() { - if (hasNext()) { - return it.next(); - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - it.remove(); - } - @Override - public void unsubscribe() { - if (once.compareAndSet(false, true)) { - try { - c.close(); - } catch (IOException ex) { - // ignored - } - } - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/operators/ZipIterable.java b/src/main/java/ix/internal/operators/ZipIterable.java deleted file mode 100644 index 75239aa..0000000 --- a/src/main/java/ix/internal/operators/ZipIterable.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.operators; - -import ix.internal.util.SingleContainer; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import rx.Notification; -import rx.functions.Func2; - -/** - * Iterable sequence containing the zipped values of two other sequences. - * - * @param the first source value type - * @param the second source value type - * @param the result value type - */ -public final class ZipIterable implements Iterable { - /** The first source sequence. */ - private final Iterable left; - /** The second source sequence. */ - private final Iterable right; - /** The function that combines values from the two sources. */ - private final Func2 combiner; - - /** - * Constructor, initializes the fields. - * @param left the first sequence - * @param right the second sequence - * @param combiner the combinator function - */ - public ZipIterable(Iterable left, Iterable right, - Func2 combiner - ) { - this.right = right; - this.combiner = combiner; - this.left = left; - } - - @Override - public Iterator iterator() { - return new Iterator() { - /** The left iterator. */ - final Iterator ts = left.iterator(); - /** The right iterator. */ - final Iterator us = right.iterator(); - /** The peek-ahead container. */ - final SingleContainer> peek = new SingleContainer>(); - @Override - public boolean hasNext() { - if (peek.isEmpty()) { - try { - if (ts.hasNext() && us.hasNext()) { - peek.add(Interactive.some(combiner.call(ts.next(), us.next()))); - } - } catch (Throwable t) { - peek.add(Interactive.err(t)); - } - } - return !peek.isEmpty(); - } - @Override - public V next() { - if (hasNext()) { - return Interactive.value(peek.take()); - } - throw new NoSuchElementException(); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/util/CircularBuffer.java b/src/main/java/ix/internal/util/CircularBuffer.java deleted file mode 100644 index 90497c4..0000000 --- a/src/main/java/ix/internal/util/CircularBuffer.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -import java.util.NoSuchElementException; - -/** - * A simple circular buffer with absolute indices. - * @param the contained element type - */ -public class CircularBuffer { - /** The buffer. */ - final Object[] buffer; - /** The head pointer. */ - int head; - /** The tail pointer. */ - int tail; - /** - * Construct a new circular buffer. - * @param size the buffer size - */ - public CircularBuffer(int size) { - buffer = new Object[size]; - } - /** - * Add a new value to the buffer. - * If the buffer would overflow, it automatically removes the current head element. - * @param value the value - */ - public void add(T value) { - buffer[(tail++) % buffer.length] = value; - if (size() > buffer.length) { - head++; - } - } - /** - * Retrieve a buffer element based on an absolute index. - * @param index the absolute index - * @return the value - */ - @SuppressWarnings("unchecked") - public T get(int index) { - if (index < head) { - throw new IllegalArgumentException("read before head"); - } - if (index >= tail) { - throw new IllegalArgumentException("read after tail"); - } - return (T)buffer[index % buffer.length]; - } - /** - * @return Takes the head of the buffer. - */ - @SuppressWarnings("unchecked") - public T take() { - if (tail == head) { - throw new NoSuchElementException(); - } - int idx = head++ % buffer.length; - T value = (T)buffer[idx]; - buffer[idx] = null; - return value; - } - /** @return is the buffer empty? */ - public boolean isEmpty() { - return head == tail; - } - /** @return the current size of the buffer. */ - public int size() { - return tail - head; - } - /** @return the current head index. */ - public int head() { - return head; - } - /** @return the current tail index. */ - public int tail() { - return tail; - } -} diff --git a/src/main/java/ix/internal/util/IxHelperFunctions.java b/src/main/java/ix/internal/util/IxHelperFunctions.java deleted file mode 100644 index f29da91..0000000 --- a/src/main/java/ix/internal/util/IxHelperFunctions.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; - -import rx.functions.Func0; -import rx.functions.Func1; -import rx.functions.Func2; - -/** - * Helper class with function types. - */ -public final class IxHelperFunctions { - /** - * Creates a function which returns always the same value. - * @param the parameter type, irrelevant - * @param the value type to return - * @param value the value to return - * @return the function - */ - public static Func1 constant(final Result value) { - return new Func1() { - @Override - public Result call(Param1 param1) { - return value; - } - }; - } - /** - * Creates a function which returns always the same value. - * @param the value type to return - * @param value the value to return - * @return the function - */ - public static Func0 constant0(final T value) { - return new Func0() { - @Override - public T call() { - return value; - } - }; - } - - /** - * Returns a function which returns the greater of its parameters. - * If only one of the parameters is null, the other parameter is returned. - * If both parameters are null, null is returned. - * @param the parameter types, which must be self-comparable - * @return the function - */ - public static > Func2 max() { - return new Func2() { - @Override - public T call(T param1, T param2) { - if (param1 == null || param2 == null) { - if (param2 == null) { - return param1; - } - return param2; - } - return param1.compareTo(param2) < 0 ? param2 : param1; - } - }; - } - /** - * Returns a function which returns the smaller of its parameters. - * If only one of the parameters is null, the other parameter is returned. - * If both parameters are null, null is returned. - * @param the parameter types, which must be self-comparable - * @return the function - */ - public static > Func2 min() { - return new Func2() { - @Override - public T call(T param1, T param2) { - if (param1 == null || param2 == null) { - if (param2 == null) { - return param1; - } - return param2; - } - return param1.compareTo(param2) > 0 ? param2 : param1; - } - }; - } - /** A helper function which returns its first parameter. */ - private static final Func2 IDENTITY_FIRST = new Func2() { - @Override - public Object call(Object param1, Object param2) { - return param1; - } - }; - /** A helper function which returns its second parameter. */ - private static final Func2 IDENTITY_SECOND = new Func2() { - @Override - public Object call(Object param1, Object param2) { - return param2; - } - }; - /** - * Returns a helper function of two parameters which always returns its first parameter. - * @param the result and the first parameter type - * @param the second parameter type, irrelevant - * @return the function - */ - @SuppressWarnings("unchecked") - public static Func2 identityFirst() { - return (Func2)IDENTITY_FIRST; - } - /** - * Returns a helper function of two parameters which always returns its second parameter. - * @param the result and the second parameter type - * @param the first parameter type, irrelevant - * @return the function - */ - @SuppressWarnings("unchecked") - public static Func2 identitySecond() { - return (Func2)IDENTITY_SECOND; - } - /** - * Returns a function which returns the greater of its parameters in respect to the supplied Comparator. - * If only one of the parameters is null, the other parameter is returned. - * If both parameters are null, null is returned. - * @param the parameter types, which must be self-comparable - * @param comparator the value comparator - * @return the function - */ - public static Func2 max( - final Comparator comparator) { - return new Func2() { - @Override - public T call(T param1, T param2) { - if (param1 == null || param2 == null) { - if (param2 == null) { - return param1; - } - return param2; - } - return comparator.compare(param1, param2) < 0 ? param2 : param1; - } - }; - } - /** - * Returns a function which returns the smaller of its parameters in respect to the supplied Comparator. - * If only one of the parameters is null, the other parameter is returned. - * If both parameters are null, null is returned. - * @param the parameter types, which must be self-comparable - * @param comparator the value comparator - * @return the function - */ - public static Func2 min( - final Comparator comparator) { - return new Func2() { - @Override - public T call(T param1, T param2) { - if (param1 == null || param2 == null) { - if (param2 == null) { - return param1; - } - return param2; - } - return comparator.compare(param1, param2) > 0 ? param2 : param1; - } - }; - } - /** - * Returns a convenience comparator which basically compares - * objects which implement the Comparable - * interface. The comparator is null safe in the manner, - * that nulls are always less than any non-nulls. - * To have a comparator which places nulls last, use the comparator0() method. - * @param the element types to compare - * @return the comparator - * @see IxHelperFunctions#comparator0() - */ - public static > Comparator comparator() { - return new Comparator() { - @Override - public int compare(T o1, T o2) { - if (o1 == null) { - if (o2 == null) { - return 0; - } - return -1; - } - if (o2 == null) { - return 1; - } - return o1.compareTo(o2); - } - }; - } - /** - * Returns a convenience comparator which basically compares objects which implement the Comparable - * interface. The comparator is null safe in the manner, that nulls are always greater than any non-nulls. - * To have a comparator which places nulls first, use the comparator() method. - * @param the element types to compare - * @return the comparator - */ - public static > Comparator comparator0() { - return new Comparator() { - @Override - public int compare(T o1, T o2) { - if (o1 == null) { - if (o2 == null) { - return 0; - } - return 1; - } - if (o2 == null) { - return -1; - } - return o1.compareTo(o2); - } - }; - } - /** - * Creates a new comparator which reverses the order of the comparison. - * @param the element type, which must be self comparable - * @return the new comparator - */ - public static > Comparator comparatorReverse() { - return new Comparator() { - @Override - public int compare(T o1, T o2) { - return o2.compareTo(o1); - } - }; - } - /** - * Creates a new comparator which reverses the order produced by the given - * normal comparator. - * @param the element type - * @param normal the normal comparator - * @return the new comparator - */ - public static Comparator comparatorReverse( - final Comparator normal) { - return new Comparator() { - @Override - public int compare(T o1, T o2) { - return normal.compare(o2, o1); - } - }; - } - /** Function to sum integers in aggregators. */ - static final Func2 SUM_INTEGER = new Func2() { - @Override - public Integer call(Integer param1, Integer param2) { - return param1 != null ? param1 + param2 : param2; - } - }; - /** Function to sum integers in aggregators. */ - static final Func2 SUM_FLOAT = new Func2() { - @Override - public Float call(Float param1, Float param2) { - return param1 != null ? param1 + param2 : param2; - } - }; - /** Function to sum integers in aggregators. */ - static final Func2 SUM_DOUBLE = new Func2() { - @Override - public Double call(Double param1, Double param2) { - return param1 != null ? param1 + param2 : param2; - } - }; - /** Function to sum integers in aggregators. */ - static final Func2 SUM_LONG = new Func2() { - @Override - public Long call(Long param1, Long param2) { - return param1 != null ? param1 + param2 : param2; - } - }; - /** Function to sum integers in aggregators. */ - static final Func2 SUM_BIGINTEGER = new Func2() { - @Override - public BigInteger call(BigInteger param1, BigInteger param2) { - return param1 != null ? param1.add(param2) : param2; - } - }; - /** Function to sum integers in aggregators. */ - static final Func2 SUM_BIGDECIMAL = new Func2() { - @Override - public BigDecimal call(BigDecimal param1, BigDecimal param2) { - return param1 != null ? param1.add(param2) : param2; - } - }; - /** - * Retuns a function that adds two BigDecimal numbers and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumBigDecimal() { - return SUM_BIGDECIMAL; - } - /** - * Retuns a function that adds two BigInteger numbers and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumBigInteger() { - return SUM_BIGINTEGER; - } - /** - * Retuns a function that adds two Double number and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumDouble() { - return SUM_DOUBLE; - } - /** - * Retuns a function that adds two Float number and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumFloat() { - return SUM_FLOAT; - } - /** - * Retuns a function that adds two Integer number and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumInteger() { - return SUM_INTEGER; - } - /** - * Retuns a function that adds two Long number and - * returns a new one. - *

If the first parameter is null, it returns the second parameter.

- * @return Function to sum integers in aggregators. - */ - public static Func2 sumLong() { - return SUM_LONG; - } - /** - * A list creator factory. - * @param the value type - * @return a function which creates a new empty instance of the given concrete list implementation. - */ - public static Func0> arrayListProvider() { - return new Func0>() { - @Override - public ArrayList call() { - return new ArrayList(); - } - }; - } - /** - * A list creator factory for Func1 that ignores the parameter. - * @param the value type - * @param the function parameter type, ignored - * @return a function which creates a new empty instance of - * the given concrete list implementation. - */ - public static Func1> arrayListProvider1() { - return new Func1>() { - @Override - public ArrayList call(U ignored) { - return new ArrayList(); - } - }; - } - /** - * A list creator factory. - * @param the value type - * @return a function which creates a new empty instance of the given concrete list implementation. - */ - public static Func0> linkedListProvider() { - return new Func0>() { - @Override - public LinkedList call() { - return new LinkedList(); - } - }; - } - /** - * A map creator factory. - * @param the key type - * @param the value type - * @return a function which creates a new empty instance of the given concrete map implementation. - */ - public static Func0> hashMapProvider() { - return new Func0>() { - @Override - public HashMap call() { - return new HashMap(); - } - }; - } - /** - * A map creator factory. - * @param the key type - * @param the value type - * @return a function which creates a new empty instance of the given concrete map implementation. - */ - public static Func0> treeMapProvider() { - return new Func0>() { - @Override - public TreeMap call() { - return new TreeMap(); - } - }; - } - /** - * A map creator factory. - * @param the key type - * @param the value type - * @param keyComparator the key comparator function - * @return a function which creates a new empty instance of the given concrete map implementation. - */ - public static Func0> treeMapProvider(final Comparator keyComparator) { - return new Func0>() { - @Override - public TreeMap call() { - return new TreeMap(keyComparator); - } - }; - } - /** - * A map creator factory. - * @param the key type - * @param the value type - * @return a function which creates a new empty instance of the given concrete map implementation. - */ - public static Func0> linkedHashMapProvider() { - return new Func0>() { - @Override - public LinkedHashMap call() { - return new LinkedHashMap(); - } - }; - } - /** - * A map creator factory. - * @param the key type - * @param the value type - * @return a function which creates a new empty instance of the given concrete map implementation. - */ - public static Func0> concurrentHashMapProvider() { - return new Func0>() { - @Override - public ConcurrentHashMap call() { - return new ConcurrentHashMap(); - } - }; - } - /** - * A set creation provider. - * @param the element type - * @return the function which creates an empty instance of the set - */ - public static Func0> hashSetProvider() { - return new Func0>() { - @Override - public HashSet call() { - return new HashSet(); - } - }; - } - /** - * A set creation provider. - * @param the element type - * @return the function which creates an empty instance of the set - */ - public static Func0> treeSetProvider() { - return new Func0>() { - @Override - public TreeSet call() { - return new TreeSet(); - } - }; - } - /** - * A set creation provider. - * @param the element type - * @param elementComparator the custom element comparator - * @return the function which creates an empty instance of the set - */ - public static Func0> treeSetProvider(final Comparator elementComparator) { - return new Func0>() { - @Override - public TreeSet call() { - return new TreeSet(elementComparator); - } - }; - } - /** - * @return Returns a function that negates the incoming boolean value. - */ - public static Func1 negate() { - return new Func1() { - @Override - public Boolean call(Boolean param1) { - return param1 == Boolean.TRUE ? Boolean.FALSE : Boolean.TRUE; - } - }; - } - /** A function that returns its parameter. */ - private static final Func1 IDENTITY = new Func1() { - @Override - public Object call(Object t1) { - return t1; - }; - }; - /** - * @param the input and result type - * @return a function which returns the single parameter value as its result. - */ - @SuppressWarnings("unchecked") - public static Func1 identity() { - return (Func1)IDENTITY; - } - /** Utility class. */ - private IxHelperFunctions() { - } -} diff --git a/src/main/java/ix/internal/util/LinkedBuffer.java b/src/main/java/ix/internal/util/LinkedBuffer.java deleted file mode 100644 index d468581..0000000 --- a/src/main/java/ix/internal/util/LinkedBuffer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -/** - * A linked buffer, which can be only filled and queried. - * @param the element type - */ -public final class LinkedBuffer { - /** - * The node. - * @param the element type - */ - public static class N { - /** The element value. */ - public T value; - /** The next node. */ - public LinkedBuffer.N next; - } - /** The head pointer. */ - public final LinkedBuffer.N head = new LinkedBuffer.N(); - /** The tail pointer. */ - public LinkedBuffer.N tail = head; - /** The size. */ - public int size; - /** - * Add a new value. - * @param value the new value - */ - public void add(T value) { - LinkedBuffer.N n = new LinkedBuffer.N(); - n.value = value; - tail.next = n; - tail = n; - size++; - } -} \ No newline at end of file diff --git a/src/main/java/ix/internal/util/ObservableToIterableAdapter.java b/src/main/java/ix/internal/util/ObservableToIterableAdapter.java deleted file mode 100644 index 544a785..0000000 --- a/src/main/java/ix/internal/util/ObservableToIterableAdapter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -import ix.CloseableIterable; -import ix.CloseableIterator; -import rx.Observable; -import rx.Subscription; -import rx.subscriptions.CompositeSubscription; - -/** - * Base class to help receive values from an observable sequence - * through customizable iterator and observer. - * @param the observed element type - * @param the iterated element type - */ -public abstract class ObservableToIterableAdapter -implements CloseableIterable { - /** The observable instance. */ - protected final Observable observable; - /** - * Constructor, saves the source observable. - * @param observable the source observable - */ - public ObservableToIterableAdapter(Observable observable) { - this.observable = observable; - } - @Override - public CloseableIterator iterator() { - CompositeSubscription handle = new CompositeSubscription(); - ObserverToIteratorSink it = run(handle); - Subscription c = observable.subscribe(it); - // this won't add C if the handle is already closed - handle.add(c); - return it; - } - /** - * The factory method to return an iterator and hand over the close handle - * to the original registration to the source. - * @param handle the close handle - * @return the closeable iterator - */ - protected abstract ObserverToIteratorSink run(Subscription handle); -} diff --git a/src/main/java/ix/internal/util/ObserverToIteratorSink.java b/src/main/java/ix/internal/util/ObserverToIteratorSink.java deleted file mode 100644 index 171edec..0000000 --- a/src/main/java/ix/internal/util/ObserverToIteratorSink.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -import rx.Observer; -import ix.CloseableIterator; - -import java.util.NoSuchElementException; - -import rx.Subscription; - -/** - * Base class to help transition from reactive to interactive - * world. - * @param the observed type - * @param the returned value type - */ -public abstract class ObserverToIteratorSink implements Observer, - CloseableIterator { - /** Indicate that the stream has finished. */ - protected boolean done; - /** The original handle to the observer registration. */ - protected final Subscription handle; - /** The current value. */ - protected final SingleOption current = new SingleOption(); - /** - * Constructor, saves the handle. - * @param handle the handle to close when the stream finishes. - */ - public ObserverToIteratorSink(Subscription handle) { - this.handle = handle; - } - @Override - public boolean hasNext() { - if (!done) { - if (current.isEmpty()) { - if (!tryNext(current)) { - done = true; - unsubscribe(); - return false; - } - } - return true; - } - return false; - } - - @Override - public U next() { - if (hasNext()) { - if (current.hasError()) { - done = true; - unsubscribe(); - } - return current.take(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - @Override - public void unsubscribe() { - handle.unsubscribe(); - } - @Override - public boolean isUnsubscribed() { - return handle.isUnsubscribed(); - } - /** Closes this iterator and suppresses exceptions. */ - protected void done() { - unsubscribe(); - } - /** - * Try to get the next value. - * @param out the output where to put the value - * @return true if value was available - */ - public abstract boolean tryNext(SingleOption out); -} diff --git a/src/main/java/ix/internal/util/SingleContainer.java b/src/main/java/ix/internal/util/SingleContainer.java deleted file mode 100644 index 652f169..0000000 --- a/src/main/java/ix/internal/util/SingleContainer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -/** - * Helper class that stores a single element. - * The caller may add a new element only when the container is empty and - * the caller may take the contained element if there is one. - * Use the isEmpty() to check for the status - * The add and take methods might throw IllegalStateException, - * which should indicate a library bug. - * Typically used by the Interactive methods to help them conform with the Iterable contract, - * e.g., hasNext() is idempotent, but next() might - * be called without hasNext() to be called at all. - * The container is not thread-safe. - * @param the contained element type - */ -public class SingleContainer { - /** The currently stored value. */ - T value; - /** The state. */ - boolean empty = true; - /** - * Add a new value. Might throw an IllegalStateException when the container already has a value. - * @param value the new value - */ - public void add(T value) { - if (empty) { - this.value = value; - empty = false; - } else { - throw new IllegalStateException("occupied"); - } - } - /** - * @return the content or throws an IllegalStateException when the container is empty. - */ - public T take() { - if (!empty) { - T v = value; - value = null; - empty = true; - return v; - } - throw new IllegalStateException("empty"); - } - /** - * @return true if there is nothing contained - */ - public boolean isEmpty() { - return empty; - } -} diff --git a/src/main/java/ix/internal/util/SingleOption.java b/src/main/java/ix/internal/util/SingleOption.java deleted file mode 100644 index 034c771..0000000 --- a/src/main/java/ix/internal/util/SingleOption.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix.internal.util; - -import rx.Notification; -import rx.exceptions.Exceptions; - -/** - * Container that may contain a single value or an exception, but not both. - *

The caller may add a single value or exception to this - * container. Any subsequent add attempt results in IllegalStateException. - *

The caller may retrieve the value or exception from this container, - * which is then removed from the container; the caller may add - * a new value or exception. If the caller attempts to remove - * a value or exception after a value, it will result in IllegalStateException.

- *

The class is not thread safe.

- * @param the contained value type - */ -public final class SingleOption { - /** Indicator for having a value or error. */ - protected boolean hasContent; - /** The contained value. */ - protected T value; - /** The stored exception. */ - protected Throwable error; - /** - * Add a new value to the container. - * The container must be empty. - * @param value the value to add - */ - public void add(T value) { - ensureEmpty(); - hasContent = true; - this.value = value; - } - /** - * Add a new error to the container. - * The container must be empty. - * @param ex the exception to add - */ - public void addError(Throwable ex) { - ensureEmpty(); - hasContent = true; - this.error = ex; - } - /** - * @return test if the container is empty - */ - public boolean isEmpty() { - return !hasContent; - } - /** Throws an IllegalStateException if the container is full. */ - protected void ensureEmpty() { - if (hasContent) { - throw new IllegalStateException("Full"); - } - } - /** Throws an IllegalStateException if the container is empty. */ - protected void ensureFull() { - if (!hasContent) { - throw new IllegalStateException("Empty"); - } - } - /** - * Takes the current value or throws a RuntimeException - * if there is an error instead. - *

The container must be full, and gets empty after the call.

- * @return the value contained - */ - public T take() { - ensureFull(); - hasContent = false; - Throwable t = error; - if (t != null) { - error = null; - Exceptions.propagate(t); - } - T result = value; - value = null; - return result; - } - /** - * Takes just the exception from this container. - * The container becomes empty after the call. - * If the container doesn't hold an exception, an - * IllegalStateException is thrown. - * @return the exception - */ - public Throwable takeError() { - ensureFull(); - Throwable t = error; - if (t != null) { - error = null; - return t; - } - throw new IllegalStateException("no error"); - } - /** - * @return check if there is an error in this container - */ - public boolean hasError() { - return hasContent && error != null; - } - /** - * @return Consumes the content of this container in a form of - * an option instance. The container becomes empty after it. - */ - public Notification option() { - if (hasContent) { - Throwable t = error; - if (t != null) { - error = null; - return Notification.createOnError(t); - } - T v = value; - value = null; - return Notification.createOnNext(v); - } - return Notification.createOnCompleted(); - } - /** - * Add a new optional value to the container. - * The container must be empty. - * Throws IllegalArgumentException if o is None. - * @param o the option to add - */ - public void addOption(Notification o) { - if (o.isOnNext()) { - add(o.getValue()); - } else - if (o.isOnError()) { - addError(o.getThrowable()); - } else { - throw new IllegalArgumentException("OnCompleted Notification has no meaning here"); - } - } -} diff --git a/src/test/java/ix/FirstOrDefaultTest.java b/src/test/java/ix/AggregateTest.java similarity index 62% rename from src/test/java/ix/FirstOrDefaultTest.java rename to src/test/java/ix/AggregateTest.java index 602ef52..6702184 100644 --- a/src/test/java/ix/FirstOrDefaultTest.java +++ b/src/test/java/ix/AggregateTest.java @@ -16,27 +16,32 @@ package ix; -import org.junit.*; +import org.junit.Test; -public class FirstOrDefaultTest { +public class AggregateTest { @Test - public void nonEmpty() { - int v = Ix.just(1).firstOrDefault(2); - - Assert.assertEquals(1, v); + public void normal() { + + Ix source = Ix.range(1, 10).sumInt(); + + IxTestHelper.assertValues(source, 55); } @Test - public void empty() { - int v = Ix.empty().firstOrDefault(2); - - Assert.assertEquals(2, v); + public void just() { + + Ix source = Ix.just(1).sumInt(); + + IxTestHelper.assertValues(source, 1); } @Test - public void longerNonEmpty() { - int v = Ix.range(100, 100).firstOrDefault(1); - Assert.assertEquals(100, v); + public void empty() { + + Ix source = Ix.empty().sumInt(); + + IxTestHelper.assertValues(source); } + } diff --git a/src/test/java/ix/AnyAllTest.java b/src/test/java/ix/AnyAllTest.java new file mode 100644 index 0000000..82fe86d --- /dev/null +++ b/src/test/java/ix/AnyAllTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class AnyAllTest { + + @Test + public void anyFound() { + Ix source = Ix.range(1, 5).any(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 3; + } + }); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void anyNotFound() { + Ix source = Ix.range(1, 5).any(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 0; + } + }); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void anyEmpty() { + Ix source = Ix.empty().any(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 3; + } + }); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void allTrue() { + Ix source = Ix.range(1, 5).all(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v < 6; + } + }); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void allFalse() { + Ix source = Ix.range(1, 5).all(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void allEmpty() { + Ix source = Ix.empty().all(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } + + +} diff --git a/src/test/java/ix/AsComposeTest.java b/src/test/java/ix/AsComposeTest.java new file mode 100644 index 0000000..d903725 --- /dev/null +++ b/src/test/java/ix/AsComposeTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class AsComposeTest { + + @Test + public void normal() { + Integer value = Ix.range(1, 5).as(new IxFunction, Integer>() { + @Override + public Integer apply(Ix ix) { + return ix.first(); + } + }); + + Assert.assertEquals(1, value.intValue()); + } + + @Test + public void compose() { + Ix source = Ix.range(1, 5).compose(new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix ix) { + final int[] index = { 1 }; + return ix.map(new IxFunction() { + @Override + public String apply(Integer v) { + return v + "-" + (index[0]++); + } + }); + } + }); + + IxTestHelper.assertValues(source, "1-1", "2-2", "3-3", "4-4", "5-5"); + + IxTestHelper.assertValues(source, "1-1", "2-2", "3-3", "4-4", "5-5"); + } +} diff --git a/src/test/java/ix/AverageTest.java b/src/test/java/ix/AverageTest.java new file mode 100644 index 0000000..16e2c91 --- /dev/null +++ b/src/test/java/ix/AverageTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class AverageTest { + + @Test + public void normalFloat() { + Ix source = Ix.range(1, 5).averageFloat(); + + IxTestHelper.assertValues(source, 3f); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justFloat() { + Ix source = Ix.just(1).averageFloat(); + + IxTestHelper.assertValues(source, 1f); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void emptyFloat() { + Ix source = Ix.empty().averageFloat(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalDouble() { + Ix source = Ix.range(1, 5).averageDouble(); + + IxTestHelper.assertValues(source, 3d); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justDouble() { + Ix source = Ix.just(1).averageDouble(); + + IxTestHelper.assertValues(source, 1d); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void emptyDouble() { + Ix source = Ix.empty().averageDouble(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/BufferPredicateTest.java b/src/test/java/ix/BufferPredicateTest.java new file mode 100644 index 0000000..c71f4dd --- /dev/null +++ b/src/test/java/ix/BufferPredicateTest.java @@ -0,0 +1,153 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.Test; + +public class BufferPredicateTest { + + @SuppressWarnings("unchecked") + @Test + public void splitNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3), Arrays.asList(4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void splitNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList()); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(10, 3), Arrays.asList(10, 4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(10), Arrays.asList(10)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilNormal() { + Ix> source = Ix.fromArray(1, 2, 10, 3, 10, 4) + .bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2, 10), Arrays.asList(3, 10), Arrays.asList(4)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilNormalEmpty() { + Ix> source = Ix.fromArray(1, 2, 10, 10) + .bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2, 10), Arrays.asList(10)); + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void splitEmpty() { + Ix> source = Ix.empty().bufferSplit(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source); + } + + @SuppressWarnings("unchecked") + @Test + public void whileEmpty() { + Ix> source = Ix.empty().bufferWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v != 10; + } + }); + + IxTestHelper.assertValues(source); + } + + @SuppressWarnings("unchecked") + @Test + public void untilEmpty() { + Ix> source = Ix.empty().bufferUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 10; + } + }); + + IxTestHelper.assertValues(source); + } +} diff --git a/src/test/java/ix/BufferTest.java b/src/test/java/ix/BufferTest.java new file mode 100644 index 0000000..e88723f --- /dev/null +++ b/src/test/java/ix/BufferTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.Test; + +public class BufferTest { + + @SuppressWarnings("unchecked") + @Test + public void normal() { + Ix> source = Ix.range(1, 5).buffer(2); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalExactLength() { + Ix> source = Ix.range(1, 6).buffer(2); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalSameSkip() { + Ix> source = Ix.range(1, 5).buffer(2, 2); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalSameSkipExactLength() { + Ix> source = Ix.range(1, 6).buffer(2, 2); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalSkip() { + Ix> source = Ix.range(1, 5).buffer(2, 3); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(4, 5)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalSkipShorter() { + Ix> source = Ix.range(1, 4).buffer(2, 3); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2), Arrays.asList(4)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalSkipShortest() { + Ix> source = Ix.range(1, 3).buffer(2, 3); + + IxTestHelper.assertValues(source, Arrays.asList(1, 2)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalOverlap() { + Ix> source = Ix.range(1, 5).buffer(2, 1); + + IxTestHelper.assertValues(source, + Arrays.asList(1, 2), + Arrays.asList(2, 3), + Arrays.asList(3, 4), + Arrays.asList(4, 5), + Arrays.asList(5)); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalOverlapLonger() { + Ix> source = Ix.range(1, 10).buffer(3, 1); + + IxTestHelper.assertValues(source, + Arrays.asList(1, 2, 3), + Arrays.asList(2, 3, 4), + Arrays.asList(3, 4, 5), + Arrays.asList(4, 5, 6), + Arrays.asList(5, 6, 7), + Arrays.asList(6, 7, 8), + Arrays.asList(7, 8, 9), + Arrays.asList(8, 9, 10), + Arrays.asList(9, 10), + Arrays.asList(10) + ); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalOverlapSorter() { + Ix> source = Ix.range(1, 2).buffer(3, 2); + + IxTestHelper.assertValues(source, + Arrays.asList(1, 2) + ); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalOverlapEmpty() { + Ix> source = Ix.empty().buffer(3, 2); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void normalOverlapJust() { + Ix> source = Ix.just(1).buffer(3, 2); + + IxTestHelper.assertValues(source, Arrays.asList(1)); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/CharactersTest.java b/src/test/java/ix/CharactersTest.java new file mode 100644 index 0000000..01bbf45 --- /dev/null +++ b/src/test/java/ix/CharactersTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class CharactersTest { + + @Test + public void normal() { + Ix source = Ix.characters("Hello world!"); + + IxTestHelper.assertValues(source, + (int)'H', (int)'e', (int)'l', (int)'l', + (int)'o', (int)' ', (int)'w', (int)'o', (int)'r', (int)'l', + (int)'d', (int)'!'); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalRange() { + Ix source = Ix.characters("Hello world!", 2, 8); + + IxTestHelper.assertValues(source, + (int)'l', (int)'l', + (int)'o', (int)' ', (int)'w', (int)'o'); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void rangeChecks() { + String s = "Hello world"; + + try { + Ix.characters(s, -1, 1); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=-1, end=1, length=11", ex.getMessage()); + } + + try { + Ix.characters(s, 1, -1); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=1, end=-1, length=11", ex.getMessage()); + } + + try { + Ix.characters(s, 12, -1); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=12, end=-1, length=11", ex.getMessage()); + } + + try { + Ix.characters(s, 1, 12); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=1, end=12, length=11", ex.getMessage()); + } + + try { + Ix.characters(s, 12, 12); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=12, end=12, length=11", ex.getMessage()); + } + } +} diff --git a/src/test/java/ix/CollectTest.java b/src/test/java/ix/CollectTest.java index a2b7e70..9e84a46 100644 --- a/src/test/java/ix/CollectTest.java +++ b/src/test/java/ix/CollectTest.java @@ -16,65 +16,26 @@ package ix; -import java.util.*; +import static org.junit.Assert.assertEquals; -import org.junit.*; - -import rx.functions.*; +import org.junit.Test; public class CollectTest { @Test - public void single() { - - Object[] a = Ix.just(1).collect(new Func0>() { - @Override - public Collection call() { - return new ArrayList(); - } - }, new Action2, Integer>() { - @Override - public void call(Collection a, Integer b) { - a.add(b); - } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { Collections.singletonList(1) }, a); - } - - @Test - public void range() { - - Object[] a = Ix.range(1, 3).collect(new Func0>() { + public void normal() { + Ix source = Ix.range(1, 10).collect(new IxSupplier() { @Override - public Collection call() { - return new ArrayList(); + public Integer[] get() { + return new Integer[] { 0 }; } - }, new Action2, Integer>() { + }, new IxConsumer2() { @Override - public void call(Collection a, Integer b) { - a.add(b); + public void accept(Integer[] a, Integer b) { + a[0] += b; } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { Arrays.asList(1, 2, 3) }, a); - } + }); - @Test - public void empty() { - - Object[] a = Ix.empty().collect(new Func0>() { - @Override - public Collection call() { - return new ArrayList(); - } - }, new Action2, Integer>() { - @Override - public void call(Collection a, Integer b) { - a.add(b); - } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { Collections.emptyList() }, a); + assertEquals(55, source.first()[0].intValue()); } } diff --git a/src/test/java/ix/ConcatArrayTest.java b/src/test/java/ix/ConcatArrayTest.java new file mode 100644 index 0000000..0987a3f --- /dev/null +++ b/src/test/java/ix/ConcatArrayTest.java @@ -0,0 +1,192 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Arrays; + +import org.junit.*; + +public class ConcatArrayTest { + + @SuppressWarnings("unchecked") + @Test + public void normal() { + Ix source = Ix.concatArray(Ix.range(1, 5), Ix.range(6, 5)); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @SuppressWarnings("unchecked") + @Test + public void normalViaMerge() { + Ix source = Ix.mergeArray(Ix.range(1, 5), Ix.range(6, 5)); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + + @SuppressWarnings("unchecked") + @Test + public void just() { + Ix source = Ix.concatArray(Ix.just(1), Ix.just(2)); + + + IxTestHelper.assertValues(source, 1, 2); + } + + @SuppressWarnings("unchecked") + @Test + public void empty() { + Ix source = Ix.concatArray(Ix.empty(), Ix.empty()); + + + IxTestHelper.assertValues(source); + } + + @SuppressWarnings("unchecked") + @Test + public void mixed() { + Ix source = Ix.concatArray(Ix.empty(), Ix.range(1, 5), + Ix.empty(), Ix.just(6), Ix.empty()); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6); + } + + @SuppressWarnings("unchecked") + @Test + public void mixedTwo() { + Ix source = Ix.concatArray(Ix.range(1, 5), + Ix.empty(), Ix.just(6)); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6); + } + + @Test + public void emptyArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.concatArray(); + + Assert.assertSame(source.getClass().toString(), source, Ix.empty()); + } + + @Test + public void justArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.concatArray(Ix.just(1)); + + Assert.assertTrue(source.getClass().toString(), source instanceof IxScalarCallable); + } + + @SuppressWarnings("unchecked") + @Test + public void concatIterable() { + Ix source = Ix.concat(Arrays.asList(Ix.range(1, 5), Ix.range(6, 5))); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @SuppressWarnings("unchecked") + @Test + public void concatIterableViaMerge() { + Ix source = Ix.merge(Arrays.asList(Ix.range(1, 5), Ix.range(6, 5))); + + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void startWith() { + Ix source = Ix.range(1, 5).startWith(5, 4, 3, 2, 1); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5); + } + + @Test + public void startWithEmpty() { + Ix source = Ix.range(1, 5).startWith(); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void endWith() { + Ix source = Ix.range(1, 5).endWith(5, 4, 3, 2, 1); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1); + } + + @Test + public void endWithEmpty() { + Ix source = Ix.range(1, 5).endWith(); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void concatWith() { + Ix source = Ix.range(1, 5).concatWith(Ix.range(6, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void concatWithEmpty() { + Ix source = Ix.range(1, 5).concatWith(Ix.empty()); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void mergeWith() { + Ix source = Ix.range(1, 5).mergeWith(Ix.range(6, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void mergeWithEmpty() { + Ix source = Ix.range(1, 5).mergeWith(Ix.empty()); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void concat2() { + Ix source = Ix.concat(Ix.just(1), Ix.just(2)); + + IxTestHelper.assertValues(source, 1, 2); + } + + @Test + public void concat3() { + Ix source = Ix.concat(Ix.just(1), Ix.just(2), Ix.just(3)); + + IxTestHelper.assertValues(source, 1, 2, 3); + } + + @Test + public void concat4() { + Ix source = Ix.concat(Ix.just(1), Ix.just(2), Ix.just(3), Ix.just(4)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4); + } +} diff --git a/src/test/java/ix/ContainsTest.java b/src/test/java/ix/ContainsTest.java new file mode 100644 index 0000000..85f091d --- /dev/null +++ b/src/test/java/ix/ContainsTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ContainsTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).contains(3); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalNoReferenceEquals() { + Ix source = Ix.range(1, 5).contains(new Integer(3)); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void doesntContain() { + Ix source = Ix.range(1, 5).contains(6); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void doesntContainNull() { + Ix source = Ix.range(1, 5).contains(null); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().contains(6); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justNull() { + Ix source = Ix.just(null).contains(6); + + IxTestHelper.assertValues(source, false); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justNullContains() { + Ix source = Ix.just(null).contains(null); + + IxTestHelper.assertValues(source, true); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/CountTest.java b/src/test/java/ix/CountTest.java new file mode 100644 index 0000000..c075aa9 --- /dev/null +++ b/src/test/java/ix/CountTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class CountTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).count(); + + IxTestHelper.assertValues(source, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).count(); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().count(); + + IxTestHelper.assertValues(source, 0); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalLong() { + Ix source = Ix.range(1, 5).countLong(); + + IxTestHelper.assertValues(source, 5L); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justLong() { + Ix source = Ix.just(1).countLong(); + + IxTestHelper.assertValues(source, 1L); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void emptyLong() { + Ix source = Ix.empty().countLong(); + + IxTestHelper.assertValues(source, 0L); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/DeferTest.java b/src/test/java/ix/DeferTest.java new file mode 100644 index 0000000..7e35ede --- /dev/null +++ b/src/test/java/ix/DeferTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class DeferTest { + + @Test + public void normal() { + Ix source = Ix.defer(new IxSupplier>() { + int count; + @Override + public Iterable get() { + return Ix.range(++count, 2); + } + }); + + IxTestHelper.assertValues(source, 1, 2); + IxTestHelper.assertValues(source, 2, 3); + IxTestHelper.assertValues(source, 3, 4); + } +} diff --git a/src/test/java/ix/DistinctTest.java b/src/test/java/ix/DistinctTest.java new file mode 100644 index 0000000..159858b --- /dev/null +++ b/src/test/java/ix/DistinctTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class DistinctTest { + + @Test + public void normal() { + Ix source = Ix.fromArray(1, 2, 2, 1, 3, 4, 2).distinct(); + + IxTestHelper.assertValues(source, 1, 2, 3, 4); + } + + @Test + public void empty() { + Ix source = Ix.empty().distinct(); + + IxTestHelper.assertValues(source); + } + + @Test + public void normalSelector() { + Ix source = Ix.fromArray(1, 2, 2, 1, 3, 4, 2).distinct(new IxFunction() { + @Override + public Object apply(Integer v) { + return v & 1; + } + }); + + IxTestHelper.assertValues(source, 1, 2); + } +} diff --git a/src/test/java/ix/DistinctUntilChangedTest.java b/src/test/java/ix/DistinctUntilChangedTest.java new file mode 100644 index 0000000..591a343 --- /dev/null +++ b/src/test/java/ix/DistinctUntilChangedTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class DistinctUntilChangedTest { + + @Test + public void normal() { + Ix source = Ix.fromArray(1, 2, 2, 1, 3, 1, 1, 4, 4).distinctUntilChanged(); + + IxTestHelper.assertValues(source, 1, 2, 1, 3, 1, 4); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalComparer() { + Ix source = Ix.fromArray(1, 2, 2, 1, 3, 1, 1, 4, 4).distinctUntilChanged(new IxPredicate2() { + @Override + public boolean test(Integer a, Integer b) { + return (a & 1) == (b & 1); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 1, 4); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalSelector() { + Ix source = Ix.fromArray(1, 2, 2, 1, 3, 1, 1, 4, 4) + .distinctUntilChanged(new IxFunction() { + @Override + public Object apply(Integer v) { + return v & 1; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 1, 4); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().distinctUntilChanged(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/DoOnTest.java b/src/test/java/ix/DoOnTest.java new file mode 100644 index 0000000..497c77b --- /dev/null +++ b/src/test/java/ix/DoOnTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class DoOnTest { + + @Test + public void normal() { + final List values = new ArrayList(); + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + values.add(v); + } + }) + .doOnCompleted(new Runnable() { + @Override + public void run() { + values.add(100); + } + }) + ; + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5, 100), values); + } + + @Test + public void empty() { + final List values = new ArrayList(); + Ix source = Ix.empty() + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + values.add(v); + } + }) + .doOnCompleted(new Runnable() { + @Override + public void run() { + values.add(100); + } + }) + ; + IxTestHelper.assertValues(source); + Assert.assertEquals(Arrays.asList(100), values); + } +} diff --git a/src/test/java/ix/EmptyActionTest.java b/src/test/java/ix/EmptyActionTest.java new file mode 100644 index 0000000..0f5cc50 --- /dev/null +++ b/src/test/java/ix/EmptyActionTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class EmptyActionTest { + + @Test + public void normal() { + assertNotNull(IxEmptyAction.valueOf("INSTANCE")); + + assertEquals(1, IxEmptyAction.values().length); + } +} diff --git a/src/test/java/ix/EmptyTest.java b/src/test/java/ix/EmptyTest.java new file mode 100644 index 0000000..4477e3f --- /dev/null +++ b/src/test/java/ix/EmptyTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class EmptyTest { + + @Test + public void normal() { + Ix source = Ix.empty(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void removeThrows() { + Ix source = Ix.empty(); + + IxTestHelper.assertNoRemove(source); + + try { + source.iterator().remove(); + Assert.fail("Should have thrown UnsupportedOperationException"); + } catch (UnsupportedOperationException ex) { + // expected + } + } +} diff --git a/src/test/java/ix/EqualityHelperTest.java b/src/test/java/ix/EqualityHelperTest.java new file mode 100644 index 0000000..f742000 --- /dev/null +++ b/src/test/java/ix/EqualityHelperTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static ix.EqualityHelper.INSTANCE; +import static org.junit.Assert.*; + +import org.junit.Test; + +public class EqualityHelperTest { + + @Test + public void normal() { + assertTrue(INSTANCE.test(1, 1)); + assertTrue(INSTANCE.test(1, new Integer(1))); + + assertFalse(INSTANCE.test(null, 1)); + assertFalse(INSTANCE.test(1, null)); + assertFalse(INSTANCE.test(1, 2)); + + assertNotNull(EqualityHelper.valueOf("INSTANCE")); + + assertEquals(1, EqualityHelper.values().length); + } +} diff --git a/src/test/java/ix/EveryTest.java b/src/test/java/ix/EveryTest.java new file mode 100644 index 0000000..b8f2b06 --- /dev/null +++ b/src/test/java/ix/EveryTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class EveryTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).every(2); + + IxTestHelper.assertValues(source, 2, 4); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal2() { + Ix source = Ix.range(1, 5).every(1); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal3() { + Ix source = Ix.range(1, 5).every(10); + + IxTestHelper.assertValues(source); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void remove() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + + Ix.from(list).every(2).removeAll(); + + Assert.assertEquals(Arrays.asList(1, 3, 5), list); + } +} diff --git a/src/test/java/ix/ExceptTest.java b/src/test/java/ix/ExceptTest.java new file mode 100644 index 0000000..f166635 --- /dev/null +++ b/src/test/java/ix/ExceptTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ExceptTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).except(Ix.range(3, 5)); + + IxTestHelper.assertValues(source, 1, 2, 6, 7); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void firstEmpty() { + Ix source = Ix.empty().except(Ix.range(3, 5)); + + IxTestHelper.assertValues(source, 3, 4, 5, 6, 7); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void secondEmpty() { + Ix source = Ix.range(1, 5).except(Ix.empty()); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void firstInSecond() { + Ix source = Ix.range(1, 5).except(Ix.range(1, 3)); + + IxTestHelper.assertValues(source, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void firstInFirst() { + Ix source = Ix.range(1, 3).except(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void distinct() { + Ix source = Ix.range(1, 5).except(Ix.range(6, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void overlapWithDuplicates() { + Ix source = Ix.fromArray(1, 2, 2, 3, 4, 5).except(Ix.range(1, 3)); + + IxTestHelper.assertValues(source, 4, 5); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/FilterTest.java b/src/test/java/ix/FilterTest.java new file mode 100644 index 0000000..db5736d --- /dev/null +++ b/src/test/java/ix/FilterTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class FilterTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).filter(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }); + + IxTestHelper.assertValues(source, 1, 3, 5, 7, 9); + } + + @Test + public void empty() { + Ix source = Ix.empty().filter(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void empty2() { + Ix source = Ix.just(0).filter(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void removeComposes() { + List list = Ix.range(1, 10).collectToList().first(); + + Ix.from(list).filter(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }).removeAll(); + + Assert.assertEquals(Arrays.asList(2, 4, 6, 8, 10), list); + } +} diff --git a/src/test/java/ix/FirstTest.java b/src/test/java/ix/FirstTest.java new file mode 100644 index 0000000..8a53b07 --- /dev/null +++ b/src/test/java/ix/FirstTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.NoSuchElementException; + +import org.junit.*; + +public class FirstTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10); + + Assert.assertEquals(1, source.first().intValue()); + } + + @Test + public void just() { + Ix source = Ix.just(1); + + Assert.assertEquals(1, source.first().intValue()); + } + + @Test(expected = NoSuchElementException.class) + public void empty() { + Ix source = Ix.empty(); + + Assert.assertEquals(1, source.first().intValue()); + } + + @Test + public void emptyDefault() { + Ix source = Ix.empty(); + + Assert.assertEquals(100, source.first(100).intValue()); + } + + @Test + public void justDefault() { + Ix source = Ix.just(1); + + Assert.assertEquals(1, source.first(100).intValue()); + } + + @Test + public void rangeDefault() { + Ix source = Ix.range(1, 10); + + Assert.assertEquals(1, source.first(100).intValue()); + } + +} diff --git a/src/test/java/ix/FlattenIterableTest.java b/src/test/java/ix/FlattenIterableTest.java new file mode 100644 index 0000000..f893498 --- /dev/null +++ b/src/test/java/ix/FlattenIterableTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class FlattenIterableTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.range(v, 2); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalViaConcatMap() { + Ix source = Ix.range(1, 5).concatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.range(v, 2); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6); + } + + @Test + public void just() { + Ix source = Ix.just(1).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.range(v, 2); + } + }); + + IxTestHelper.assertValues(source, 1, 2); + } + + @Test + public void empty() { + Ix source = Ix.empty().flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.range(v, 2); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void rangeJust() { + Ix source = Ix.range(1, 2).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.just(v); + } + }); + + IxTestHelper.assertValues(source, 1, 2); + } + + @Test + public void rangeEmpty() { + Ix source = Ix.range(1, 2).flatMap(new IxFunction>() { + @Override + public Iterable apply(Integer v) { + return Ix.empty(); + } + }); + + IxTestHelper.assertValues(source); + } +} diff --git a/src/test/java/ix/ForeachTest.java b/src/test/java/ix/ForeachTest.java new file mode 100644 index 0000000..7d82cf9 --- /dev/null +++ b/src/test/java/ix/ForeachTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class ForeachTest implements IxConsumer, IxPredicate { + + List list; + + @Before + public void before() { + list = new ArrayList(); + } + + @Override + public void accept(Integer t) { + list.add(t); + } + + @Override + public boolean test(Integer t) { + list.add(t); + return list.size() < 5; + } + + @Test + public void normal() { + Ix source = Ix.range(1, 10); + + source.foreach(this); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), list); + } + + @Test + public void normalWhile() { + Ix source = Ix.range(1, 10); + + source.foreachWhile(this); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void normalWhileAll() { + Ix source = Ix.range(1, 5); + + source.foreachWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } +} diff --git a/src/test/java/ix/ForloopTest.java b/src/test/java/ix/ForloopTest.java new file mode 100644 index 0000000..fa3d40b --- /dev/null +++ b/src/test/java/ix/ForloopTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ForloopTest { + + @Test + public void normal() { + Ix source = Ix.forloop(1, new IxPredicate() { + @Override + public boolean test(Integer i) { + return i <= 5; + } + }, new IxFunction() { + @Override + public Integer apply(Integer i) { + return i + 1; + } + }, new IxFunction() { + @Override + public Integer apply(Integer i) { + return i * i; + } + }); + + IxTestHelper.assertValues(source, 1, 4, 9, 16, 25); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.forloop(1, new IxPredicate() { + @Override + public boolean test(Integer i) { + return false; + } + }, new IxFunction() { + @Override + public Integer apply(Integer i) { + return i + 1; + } + }, new IxFunction() { + @Override + public Integer apply(Integer i) { + return i * i; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/FromArrayTest.java b/src/test/java/ix/FromArrayTest.java new file mode 100644 index 0000000..959a440 --- /dev/null +++ b/src/test/java/ix/FromArrayTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class FromArrayTest { + + @Test + public void normal() { + Ix source = Ix.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void range() { + Ix source = Ix.fromArrayRange(1, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertValues(source, 2, 3, 4, 5, 6, 7, 8); + } + + @Test + public void empty() { + Ix source = Ix.fromArray(); + + Assert.assertSame(source.getClass().toString(), source, Ix.empty()); + } + + @Test + public void just() { + Ix source = Ix.fromArray(1); + + Assert.assertTrue(source.getClass().toString(), source instanceof IxScalarCallable); + } + + @Test + public void rangeChecks() { + try { + Ix.fromArrayRange(-1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=-1, end=1, length=10", ex.getMessage()); + } + + try { + Ix.fromArrayRange(1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=1, end=-1, length=10", ex.getMessage()); + } + + try { + Ix.fromArrayRange(12, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=12, end=-1, length=10", ex.getMessage()); + } + + try { + Ix.fromArrayRange(1, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=1, end=12, length=10", ex.getMessage()); + } + + try { + Ix.fromArrayRange(12, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + Assert.fail("Failed to throw IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + Assert.assertEquals("start=12, end=12, length=10", ex.getMessage()); + } + + } +} diff --git a/src/test/java/ix/FromTest.java b/src/test/java/ix/FromTest.java new file mode 100644 index 0000000..7b31271 --- /dev/null +++ b/src/test/java/ix/FromTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Arrays; + +import org.junit.*; + +public class FromTest { + + @Test + public void normal() { + Ix source = Ix.from(Arrays.asList(1, 2, 3, 4, 5)); + + Assert.assertTrue(source.getClass().toString(), source instanceof IxWrapper); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void noRewrapping() { + Ix source = Ix.from(Ix.range(1, 5)); + + Assert.assertFalse(source.getClass().toString(), source instanceof IxWrapper); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + +} diff --git a/src/test/java/ix/GenerateStatelessTest.java b/src/test/java/ix/GenerateStatelessTest.java new file mode 100644 index 0000000..70476d7 --- /dev/null +++ b/src/test/java/ix/GenerateStatelessTest.java @@ -0,0 +1,100 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.io.IOException; + +import org.junit.Test; + +public class GenerateStatelessTest { + + @Test + public void normal() { + Ix source = Ix.generate(new IxConsumer>() { + int count; + @Override + public void accept(IxEmitter t) { + t.onNext(++count); + if (count == 10) { + t.onComplete(); + } + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void empty() { + Ix source = Ix.generate(new IxConsumer>() { + @Override + public void accept(IxEmitter t) { + t.onComplete(); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = IllegalStateException.class) + public void never() { + Ix source = Ix.generate(new IxConsumer>() { + @Override + public void accept(IxEmitter t) { + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = IllegalArgumentException.class) + public void runtimeError() { + Ix source = Ix.generate(new IxConsumer>() { + @Override + public void accept(IxEmitter t) { + throw new IllegalArgumentException(); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = InternalError.class) + public void error() { + Ix source = Ix.generate(new IxConsumer>() { + @Override + public void accept(IxEmitter t) { + throw new InternalError(); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = RuntimeException.class) + public void exceptionError() { + Ix source = Ix.generate(new IxConsumer>() { + @Override + public void accept(IxEmitter t) { + throw new RuntimeException(new IOException()); + } + }); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/GenerateTest.java b/src/test/java/ix/GenerateTest.java new file mode 100644 index 0000000..2f87eea --- /dev/null +++ b/src/test/java/ix/GenerateTest.java @@ -0,0 +1,137 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.*; + +public class GenerateTest { + + IxSupplier stateFactory = new IxSupplier() { + @Override + public Integer get() { + return 0; + } + }; + + @Test + public void normal() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + int i = ++s; + t.onNext(i); + if (i == 10) { + t.onComplete(); + } + return i; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void normalState() { + final AtomicInteger value = new AtomicInteger(); + + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + int i = ++s; + t.onNext(i); + if (i == 10) { + t.onComplete(); + } + return i; + } + }, new IxConsumer() { + @Override + public void accept(Integer t) { + value.set(t); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + Assert.assertEquals(10, value.get()); + } + + @Test + public void empty() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + t.onComplete(); + return s; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = IllegalStateException.class) + public void never() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + return s; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = IllegalArgumentException.class) + public void runtimeError() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + throw new IllegalArgumentException(); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = InternalError.class) + public void error() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + throw new InternalError(); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test(expected = RuntimeException.class) + public void exceptionError() { + Ix source = Ix.generate(stateFactory, new IxFunction2, Integer>() { + @Override + public Integer apply(Integer s, IxEmitter t) { + throw new RuntimeException(new IOException()); + } + }); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/GroupByTest.java b/src/test/java/ix/GroupByTest.java new file mode 100644 index 0000000..dcdc8ea --- /dev/null +++ b/src/test/java/ix/GroupByTest.java @@ -0,0 +1,276 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class GroupByTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).groupBy(new IxFunction() { + @Override + public Object apply(Integer v) { + return v % 3; + } + }).flatMap(new IxFunction, Iterable>() { + @Override + public Iterable apply(GroupedIx v) { + return v; + } + }); + + IxTestHelper.assertValues(source, 1, 4, 7, 10, 2, 5, 8, 3, 6, 9); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void uniqueGroups() { + Ix source = Ix.range(1, 10).groupBy(new IxFunction() { + @Override + public Object apply(Integer v) { + return v; + } + }, + new IxFunction() { + @Override + public Integer apply(Integer v) { + return v * 10; + } + } + ).flatMap(new IxFunction, Iterable>() { + @Override + public Iterable apply(GroupedIx v) { + return v; + } + }); + + IxTestHelper.assertValues(source, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).groupBy(new IxFunction() { + @Override + public Object apply(Integer v) { + return v % 3; + } + }).flatMap(new IxFunction, Iterable>() { + @Override + public Iterable apply(GroupedIx v) { + return v; + } + }); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justNull() { + Ix source = Ix.just(null).groupBy(new IxFunction() { + @Override + public Object apply(Integer v) { + return 1; + } + }).flatMap(new IxFunction, Iterable>() { + @Override + public Iterable apply(GroupedIx v) { + return v; + } + }); + + IxTestHelper.assertValues(source, (Integer)null); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().groupBy(new IxFunction() { + @Override + public Object apply(Integer v) { + return v % 3; + } + }).flatMap(new IxFunction, Iterable>() { + @Override + public Iterable apply(GroupedIx v) { + return v; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void lockstep() { + final Iterator[] its = new Iterator[3]; + + Iterator main = Ix.range(1, 10).groupBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }).doOnNext(new IxConsumer>() { + @Override + public void accept(GroupedIx g) { + its[g.key()] = g.iterator(); + } + }) + .iterator(); + + Assert.assertNotNull(main.next()); + + Assert.assertEquals(1, its[1].next().intValue()); + + Assert.assertNotNull(main.next()); + + Assert.assertEquals(2, its[2].next().intValue()); + + Assert.assertTrue(its[2].hasNext()); + Assert.assertNotNull(main.next()); + + Assert.assertEquals(3, its[0].next().intValue()); + Assert.assertEquals(4, its[1].next().intValue()); + Assert.assertEquals(5, its[2].next().intValue()); + Assert.assertEquals(6, its[0].next().intValue()); + + Assert.assertEquals(7, its[1].next().intValue()); + Assert.assertEquals(8, its[2].next().intValue()); + Assert.assertEquals(9, its[0].next().intValue()); + Assert.assertEquals(10, its[1].next().intValue()); + + Assert.assertFalse(main.hasNext()); + Assert.assertFalse(its[0].hasNext()); + Assert.assertFalse(its[1].hasNext()); + Assert.assertFalse(its[2].hasNext()); + } + + + @SuppressWarnings("unchecked") + @Test + public void lockstepNull() { + final Iterator[] its = new Iterator[3]; + + Iterator main = Ix.range(1, 10).groupBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }, new IxFunction() { + @Override + public Integer apply(Integer v) { + return null; + } + }).doOnNext(new IxConsumer>() { + @Override + public void accept(GroupedIx g) { + its[g.key()] = g.iterator(); + } + }) + .iterator(); + + Assert.assertNotNull(main.next()); + + Assert.assertNull(its[1].next()); + + Assert.assertNotNull(main.next()); + + Assert.assertNull(its[2].next()); + + Assert.assertTrue(its[2].hasNext()); + Assert.assertNotNull(main.next()); + + Assert.assertNull(its[0].next()); + Assert.assertNull(its[1].next()); + Assert.assertNull(its[2].next()); + Assert.assertNull(its[0].next()); + + Assert.assertNull(its[1].next()); + Assert.assertNull(its[2].next()); + Assert.assertNull(its[0].next()); + Assert.assertNull(its[1].next()); + + Assert.assertFalse(main.hasNext()); + Assert.assertFalse(its[0].hasNext()); + Assert.assertFalse(its[1].hasNext()); + Assert.assertFalse(its[2].hasNext()); + } + @Test + public void sameGroupSubsequently() { + Ix> source = Ix.range(1, 5).groupBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return 1; + } + }); + + List> list = source.collectToList().first(); + + IxTestHelper.assertValues(Ix.concat(list), 1, 2, 3, 4, 5); + } + + @Test + public void sameGroupSubsequentlyNullValue() { + Ix> source = Ix.range(1, 5).groupBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return 1; + } + }, new IxFunction() { + @Override + public Integer apply(Integer v) { + return null; + } + }); + + List> list = source.collectToList().first(); + + IxTestHelper.assertValues(Ix.concat(list), null, null, null, null, null); + } + + @Test(expected = IllegalStateException.class) + public void iteratorOnce() { + Ix> source = Ix.range(1, 5).groupBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return 1; + } + }, new IxFunction() { + @Override + public Integer apply(Integer v) { + return null; + } + }); + + List> list = source.collectToList().first(); + + Assert.assertEquals("GroupedIterable[key=1, queue=5]", list.get(0).toString()); + + IxTestHelper.assertValues(list.get(0), null, null, null, null, null); + IxTestHelper.assertValues(list.get(0), null, null, null, null, null); + } +} diff --git a/src/test/java/ix/LastOrDefaultTest.java b/src/test/java/ix/HasElementsTest.java similarity index 62% rename from src/test/java/ix/LastOrDefaultTest.java rename to src/test/java/ix/HasElementsTest.java index 22879c0..fb697ea 100644 --- a/src/test/java/ix/LastOrDefaultTest.java +++ b/src/test/java/ix/HasElementsTest.java @@ -16,27 +16,22 @@ package ix; -import org.junit.*; +import org.junit.Test; -public class LastOrDefaultTest { - - @Test - public void nonEmpty() { - int v = Ix.just(1).lastOrDefault(2); - - Assert.assertEquals(1, v); - } +public class HasElementsTest { @Test public void empty() { - int v = Ix.empty().lastOrDefault(2); - - Assert.assertEquals(2, v); + Ix source = Ix.empty().hasElements(); + + IxTestHelper.assertValues(source, false); } @Test - public void longerNonEmpty() { - int v = Ix.range(100, 100).lastOrDefault(1); - Assert.assertEquals(199, v); + public void nonempty() { + Ix source = Ix.just(1).hasElements(); + + IxTestHelper.assertValues(source, true); } + } diff --git a/src/test/java/ix/HelperTest.java b/src/test/java/ix/HelperTest.java new file mode 100644 index 0000000..1615271 --- /dev/null +++ b/src/test/java/ix/HelperTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class HelperTest { + + @Test + public void toListHelper() { + Assert.assertEquals(1, ToListHelper.values().length); + + Assert.assertNotNull(ToListHelper.valueOf("INSTANCE")); + } + + @Test + public void identityHelper() { + Assert.assertEquals(1, IdentityHelper.values().length); + + Assert.assertNotNull(IdentityHelper.valueOf("INSTANCE")); + } + + @Test + public void numberToLongHelper() { + Assert.assertEquals(1, NumberToLongHelper.values().length); + + Assert.assertNotNull(NumberToLongHelper.valueOf("INSTANCE")); + } +} diff --git a/src/test/java/ix/HideTest.java b/src/test/java/ix/HideTest.java new file mode 100644 index 0000000..4089ac9 --- /dev/null +++ b/src/test/java/ix/HideTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class HideTest { + + @Test + public void normal() { + Ix source = Ix.just(1); + + Assert.assertTrue(source instanceof IxScalarCallable); + + Assert.assertFalse((source.hide()) instanceof IxScalarCallable); + } +} diff --git a/src/test/java/ix/IgnoreElementsTest.java b/src/test/java/ix/IgnoreElementsTest.java new file mode 100644 index 0000000..fc20800 --- /dev/null +++ b/src/test/java/ix/IgnoreElementsTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class IgnoreElementsTest { + + @Test + public void range() { + Ix source = Ix.range(1, 5).ignoreElements(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().ignoreElements(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/IntersectTest.java b/src/test/java/ix/IntersectTest.java new file mode 100644 index 0000000..48df2da --- /dev/null +++ b/src/test/java/ix/IntersectTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class IntersectTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).intersect(Ix.range(3, 5)); + + IxTestHelper.assertValues(source, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void same() { + Ix source = Ix.range(1, 5).intersect(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void distinct() { + Ix source = Ix.range(1, 5).intersect(Ix.range(6, 5)); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void distinctEmptyFirst() { + Ix source = Ix.empty().intersect(Ix.range(6, 5)); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void distinctEmptySecond() { + Ix source = Ix.range(1, 5).intersect(Ix.empty()); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/IxOperatorsArePackageFinalTest.java b/src/test/java/ix/IxOperatorsArePackageFinalTest.java new file mode 100644 index 0000000..b33f248 --- /dev/null +++ b/src/test/java/ix/IxOperatorsArePackageFinalTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.io.File; +import java.lang.reflect.Modifier; +import java.net.URL; + +import org.junit.*; + +public class IxOperatorsArePackageFinalTest { + + @Test + public void checkOperatorsFinal() throws Exception { + + URL u = IxOperatorsArePackageFinalTest.class.getResource(IxOperatorsArePackageFinalTest.class.getSimpleName() + ".class"); + + File f = new File(u.toURI()); + + File g = f.getParentFile(); + + File[] files = g.listFiles(); + + StringBuilder b = new StringBuilder(); + + if (files != null && files.length != 0) { + for (File h : files) { + if (h.getName().contains("Test") + || h.getName().contains("Perf") + || h.getName().contains("$")) { + continue; + } + + Class clazz = Class.forName("ix." + h.getName().replace(".class", "")); + + if ((clazz.getModifiers() & Modifier.FINAL) == 0 + && (clazz.getModifiers() & Modifier.ABSTRACT) == 0 + && (clazz.getModifiers() & Modifier.INTERFACE) == 0) { + b.append("java.lang.RuntimeException: " + h.getName() + " is not final\r\n") + .append(" at ").append(clazz.getName()).append(" (").append(h.getName()).append(":1)\r\n\r\n"); + } + } + } + + if (b.length() != 0) { + System.out.println(b); + + Assert.fail(b.toString()); + } + } +} diff --git a/src/test/java/ix/IxTest.java b/src/test/java/ix/IxTest.java new file mode 100644 index 0000000..b413efd --- /dev/null +++ b/src/test/java/ix/IxTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.io.IOException; +import java.util.concurrent.Callable; + +import org.junit.*; + +public class IxTest { + + @Test(expected = RuntimeException.class) + public void checkedCallWraps() { + + Ix.checkedCall(new Callable() { + @Override + public Integer call() throws Exception { + throw new IOException(); + } + }); + } + + @Test(expected = InternalError.class) + public void checkedCallNoWrapsError() { + + Ix.checkedCall(new Callable() { + @Override + public Integer call() throws Exception { + throw new InternalError(); + } + }); + } + + @Test(expected = IllegalArgumentException.class) + public void checkedCallNoWrapping() { + + Ix.checkedCall(new Callable() { + @Override + public Integer call() throws Exception { + throw new IllegalArgumentException(); + } + }); + } + + @Test + public void nullCheck() { + Ix.nullCheck(1, "Should not fail"); + try { + Ix.nullCheck(null, "Failure"); + Assert.fail("Failed to throw NPE"); + } catch (NullPointerException ex) { + Assert.assertEquals("Failure", ex.getMessage()); + } + } + + @Test + public void nonNegativeLong() { + Ix.nonNegative(0L, "n"); + Ix.nonNegative(1L, "n"); + + try { + Ix.nonNegative(-99L, "n"); + } catch (IllegalArgumentException ex) { + Assert.assertEquals("n >= 0 required but it was -99", ex.getMessage()); + } + } + + @Test + public void nonNegativeInt() { + Ix.nonNegative(0, "n"); + Ix.nonNegative(1, "n"); + + try { + Ix.nonNegative(-99, "n"); + } catch (IllegalArgumentException ex) { + Assert.assertEquals("n >= 0 required but it was -99", ex.getMessage()); + } + } + + @Test + public void positiveInt() { + Ix.nonNegative(1, "n"); + + try { + Ix.positive(0, "n"); + } catch (IllegalArgumentException ex) { + Assert.assertEquals("n > 0 required but it was 0", ex.getMessage()); + } + + try { + Ix.positive(-99, "n"); + } catch (IllegalArgumentException ex) { + Assert.assertEquals("n > 0 required but it was -99", ex.getMessage()); + } + } + +} diff --git a/src/test/java/ix/IxTestHelper.java b/src/test/java/ix/IxTestHelper.java new file mode 100644 index 0000000..d0fa6f9 --- /dev/null +++ b/src/test/java/ix/IxTestHelper.java @@ -0,0 +1,102 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.Assert; + +public enum IxTestHelper { + ; + + static String classOf(Object o) { + return o != null ? o.getClass().getSimpleName() : "null"; + } + + /** + * Asserts that the iterable produces the specified array of values and + * verifies if it honors the iterator contract. + * @param the value type + * @param source the source sequence to validate + * @param values the values expected + */ + public static void assertValues(Iterable source, T... values) { + Iterator a = source.iterator(); + int i = 0; + + for (;;) { + boolean b1 = a.hasNext(); + boolean b2 = a.hasNext(); + + Assert.assertEquals("Inconsistent hasNext()", b1, b2); + + if (!b1) { + break; + } + + if (i == values.length) { + throw new AssertionError("The source is longer than " + values.length); + } + + T t = a.next(); + + if (t instanceof Object[]) { + Assert.assertArrayEquals((Object[])values[i], (Object[])t); + } else { + Assert.assertEquals("index=" + i + ", expected class=" + + classOf(values[i]) + + ", actual class=" + + classOf(t), values[i], t); + } + i++; + } + + if (i != values.length) { + throw new AssertionError("The source is shorter than " + values.length + ": " + i); + } + + try { + a.next(); + Assert.fail("The next() should have thrown a NoSuchElementException"); + } catch (NoSuchElementException ex) { + // expected + } + } + + /** + * Assert that calling remove() on the source's Iterator throws + * an UnsupportedOperationException. + * @param source the source to validate + */ + public static void assertNoRemove(Iterable source) { + Iterator it = source.iterator(); + + if (it.hasNext()) { + it.next(); + try { + it.remove(); + Assert.fail("Should have thrown UnsupportedOperationException"); + } catch (UnsupportedOperationException ex) { + // expected + } + } + } + + public static List range(int start, int count) { + return Ix.range(start, count).collectToList().first(); + } +} diff --git a/src/test/java/ix/JoinTest.java b/src/test/java/ix/JoinTest.java new file mode 100644 index 0000000..a94a3a7 --- /dev/null +++ b/src/test/java/ix/JoinTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class JoinTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).join(); + + IxTestHelper.assertValues(source, "1, 2, 3, 4, 5"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).join(); + + IxTestHelper.assertValues(source, "1"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().join(); + + IxTestHelper.assertValues(source, ""); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalSeparator() { + Ix source = Ix.range(1, 5).join("|"); + + IxTestHelper.assertValues(source, "1|2|3|4|5"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justSeparator() { + Ix source = Ix.just(1).join("|"); + + IxTestHelper.assertValues(source, "1"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void emptySeparator() { + Ix source = Ix.empty().join("|"); + + IxTestHelper.assertValues(source, ""); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/main/java/ix/internal/operators/package-info.java b/src/test/java/ix/JustTest.java similarity index 71% rename from src/main/java/ix/internal/operators/package-info.java rename to src/test/java/ix/JustTest.java index 083a4f8..d2f5a67 100644 --- a/src/main/java/ix/internal/operators/package-info.java +++ b/src/test/java/ix/JustTest.java @@ -1,19 +1,31 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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. - */ -/** - * Contains operator implementations. - */ -package ix.internal.operators; \ No newline at end of file +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class JustTest { + + @Test + public void normal() { + Ix source = Ix.just(1); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/LastTest.java b/src/test/java/ix/LastTest.java index b8155d8..ee54abd 100644 --- a/src/test/java/ix/LastTest.java +++ b/src/test/java/ix/LastTest.java @@ -23,20 +23,45 @@ public class LastTest { @Test - public void nonEmpty() { - int v = Ix.just(1).last(); - - Assert.assertEquals(1, v); + public void normal() { + Ix source = Ix.range(1, 10); + + Assert.assertEquals(10, source.last().intValue()); + } + + @Test + public void just() { + Ix source = Ix.just(1); + + Assert.assertEquals(1, source.last().intValue()); } @Test(expected = NoSuchElementException.class) public void empty() { - Ix.empty().last(); + Ix source = Ix.empty(); + + Assert.assertEquals(1, source.last().intValue()); + } + + @Test + public void emptyDefault() { + Ix source = Ix.empty(); + + Assert.assertEquals(100, source.last(100).intValue()); + } + + @Test + public void justDefault() { + Ix source = Ix.just(1); + + Assert.assertEquals(1, source.last(100).intValue()); } @Test - public void longerNonEmpty() { - int v = Ix.range(100, 100).lastOrDefault(1); - Assert.assertEquals(199, v); + public void rangeDefault() { + Ix source = Ix.range(1, 10); + + Assert.assertEquals(10, source.last(100).intValue()); } + } diff --git a/src/test/java/ix/LeavingTest.java b/src/test/java/ix/LeavingTest.java new file mode 100644 index 0000000..1a21bc5 --- /dev/null +++ b/src/test/java/ix/LeavingTest.java @@ -0,0 +1,310 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.io.*; +import java.util.*; + +import org.junit.*; + +public class LeavingTest { + + @Test + public void normal() { + List list = new ArrayList(); + + Ix.range(1, 5).into(list); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void print() throws Exception { + PrintStream old = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + try { + Ix.range(1, 30).print(); + + System.out.flush(); + } finally { + System.setOut(old); + } + + String[] s = bout.toString("UTF-8").split(System.getProperty("line.separator")); + + Assert.assertEquals(Ix.range(1, 23).join().first() + ", ", s[0]); + Assert.assertEquals(Ix.range(24, 7).join().first(), s[1]); + } + + @Test + public void print40() throws Exception { + PrintStream old = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + try { + Ix.range(1, 30).print(",", 40); + + System.out.flush(); + } finally { + System.setOut(old); + } + + String[] s = bout.toString("UTF-8").split(System.getProperty("line.separator")); + + Assert.assertEquals(Ix.range(1, 17).join(",").first() + ",", s[0]); + Assert.assertEquals(Ix.range(18, 13).join(",").first(), s[1]); + } + + @Test + public void println() throws Exception { + PrintStream old = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + try { + Ix.range(1, 3).println(); + + System.out.flush(); + } finally { + System.setOut(old); + } + + String[] s = bout.toString("UTF-8").split(System.getProperty("line.separator")); + + Assert.assertEquals("1", s[0]); + Assert.assertEquals("2", s[1]); + Assert.assertEquals("3", s[2]); + } + + @Test + public void printlnPrefix() throws Exception { + PrintStream old = System.out; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + try { + Ix.range(1, 3).println("--"); + + System.out.flush(); + } finally { + System.setOut(old); + } + + String[] s = bout.toString("UTF-8").split(System.getProperty("line.separator")); + + Assert.assertEquals("--1", s[0]); + Assert.assertEquals("--2", s[1]); + Assert.assertEquals("--3", s[2]); + } + + @Test + public void run() { + final List list = new ArrayList(); + + Ix.range(1, 5).doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + list.add(v); + } + }).run(); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void subscribe() { + final List list = new ArrayList(); + + Ix.range(1, 5).doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + list.add(v); + } + }).subscribe(); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void subscribeAction1() { + final List list = new ArrayList(); + + Ix.range(1, 5).subscribe(new IxConsumer() { + @Override + public void accept(Integer v) { + list.add(v); + } + }); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void subscribeAction1Action1() { + final List list = new ArrayList(); + + Ix.range(1, 5).subscribe(new IxConsumer() { + @Override + public void accept(Integer v) { + list.add(v); + } + }, new IxConsumer() { + @Override + public void accept(Throwable t) { + + } + }); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + + @Test + public void subscribeAction1Action1Throws() { + final List list = new ArrayList(); + + final Throwable[] error = { null }; + + Ix.range(1, 5).subscribe(new IxConsumer() { + @Override + public void accept(Integer v) { + if (v == 5) { + throw new IllegalStateException(); + } + list.add(v); + } + }, new IxConsumer() { + @Override + public void accept(Throwable t) { + error[0] = t; + } + }); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4), list); + Assert.assertTrue(String.valueOf(error[0]), error[0] instanceof IllegalStateException); + } + + @Test + public void subscribeAction1Action1Action0() { + final List list = new ArrayList(); + + Ix.range(1, 5).subscribe(new IxConsumer() { + @Override + public void accept(Integer v) { + list.add(v); + } + }, new IxConsumer() { + @Override + public void accept(Throwable t) { + + } + }, new Runnable() { + @Override + public void run() { + list.add(100); + } + }); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5, 100), list); + } + + @Test + public void subscribeAction1Action1Action0Throws() { + final List list = new ArrayList(); + + final Throwable[] error = { null }; + + Ix.range(1, 5).subscribe(new IxConsumer() { + @Override + public void accept(Integer v) { + if (v == 5) { + throw new IllegalStateException(); + } + list.add(v); + } + }, new IxConsumer() { + @Override + public void accept(Throwable t) { + error[0] = t; + } + }, new Runnable() { + @Override + public void run() { + list.add(100); + } + }); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4), list); + Assert.assertTrue(String.valueOf(error[0]), error[0] instanceof IllegalStateException); + } + + @Test + public void retainAll() { + List list = Ix.range(1, 10).collectToList().first(); + + Ix.from(list).retainAll(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) == 0; + } + }); + + Assert.assertEquals(Arrays.asList(2, 4, 6, 8, 10), list); + } + + @Test + public void removeAll() { + List list = Ix.range(1, 10).collectToList().first(); + + Ix.from(list).removeAll(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) == 1; + } + }); + + Assert.assertEquals(Arrays.asList(2, 4, 6, 8, 10), list); + } + + @Test + public void single() { + Assert.assertEquals(1, Ix.just(1).single().intValue()); + } + + @Test + public void singleDefault() { + Assert.assertEquals(1, Ix.just(1).single(2).intValue()); + } + + @Test(expected = NoSuchElementException.class) + public void singleEmpty() { + Assert.assertEquals(1, Ix.empty().single().intValue()); + } + + @Test + public void singleEmptyDefault() { + Assert.assertEquals(2, Ix.empty().single(2).intValue()); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void singleLonger() { + Ix.range(1, 5).single(); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void singleLongerDefault() { + Ix.range(1, 5).single(10); + } +} diff --git a/src/test/java/ix/LiftTest.java b/src/test/java/ix/LiftTest.java new file mode 100644 index 0000000..2fa3413 --- /dev/null +++ b/src/test/java/ix/LiftTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +import org.junit.Test; + +public class LiftTest { + + @Test + public void normal() { + Ix source = Ix.just(1).lift(new IxFunction, Iterator>() { + @Override + public Iterator apply(final Iterator it) { + return new Iterator() { + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Integer next() { + return it.next() + 10; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }); + + IxTestHelper.assertValues(source, 11); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/MapTest.java b/src/test/java/ix/MapTest.java new file mode 100644 index 0000000..189a952 --- /dev/null +++ b/src/test/java/ix/MapTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class MapTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).map(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v + 1; + } + }); + + IxTestHelper.assertValues(source, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + } + + @Test + public void removeComposes() { + List list = Ix.range(1, 10).collectToList().first(); + + Ix.from(list).map(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v + 1; + } + }).removeAll(); + + Assert.assertEquals(Arrays.asList(), list); + } +} diff --git a/src/test/java/ix/MaxTest.java b/src/test/java/ix/MaxTest.java new file mode 100644 index 0000000..22c291e --- /dev/null +++ b/src/test/java/ix/MaxTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MaxTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).maxInt(); + + assertEquals(10L, source.first().intValue()); + } + + @Test + public void just() { + Ix source = Ix.just(1).maxInt(); + + assertEquals(1, source.first().intValue()); + } + + @Test + public void empty() { + Ix source = Ix.empty().maxInt(); + + IxTestHelper.assertValues(source); + } + + @Test + public void normalLong() { + Ix source = Ix.range(1, 10).toLong().maxLong(); + + assertEquals(10L, source.first().longValue()); + } + + @Test + public void justLong() { + Ix source = Ix.just(1L).maxLong(); + + assertEquals(1L, source.first().longValue()); + } + + @Test + public void emptyLong() { + Ix source = Ix.empty().maxLong(); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/MinMaxTest.java b/src/test/java/ix/MinMaxTest.java new file mode 100644 index 0000000..770232e --- /dev/null +++ b/src/test/java/ix/MinMaxTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Comparator; + +import org.junit.Test; + +public class MinMaxTest { + + @Test + public void minComparator() { + Ix source = Ix.range(1, 5).min(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 5); + } + + @Test + public void minComparatorEmpty() { + Ix source = Ix.empty().min(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void minComparatorJust() { + Ix source = Ix.just(1).min(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void maxComparator() { + Ix source = Ix.range(1, 5).max(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void maxComparatorEmpty() { + Ix source = Ix.empty().max(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void maxComparatorJust() { + Ix source = Ix.just(1).max(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void min() { + Ix source = Ix.range(1, 5).min(); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void minEmpty() { + Ix source = Ix.empty().min(); + + IxTestHelper.assertValues(source); + } + + @Test + public void minJust() { + Ix source = Ix.just(1).min(); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void max() { + Ix source = Ix.range(1, 5).max(); + + IxTestHelper.assertValues(source, 5); + } + + @Test + public void maxEmpty() { + Ix source = Ix.empty().max(); + + IxTestHelper.assertValues(source); + } + + @Test + public void maxJust() { + Ix source = Ix.just(1).max(); + + IxTestHelper.assertValues(source, 1); + } +} diff --git a/src/test/java/ix/MinTest.java b/src/test/java/ix/MinTest.java new file mode 100644 index 0000000..79c3e7b --- /dev/null +++ b/src/test/java/ix/MinTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class MinTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).minInt(); + + assertEquals(1, source.first().intValue()); + } + + @Test + public void just() { + Ix source = Ix.just(1).minInt(); + + assertEquals(1, source.first().intValue()); + } + + @Test + public void empty() { + Ix source = Ix.empty().minInt(); + + IxTestHelper.assertValues(source); + } + + @Test + public void normalLong() { + Ix source = Ix.range(1, 10).toLong().minLong(); + + assertEquals(1, source.first().longValue()); + } + + @Test + public void justLong() { + Ix source = Ix.just(1L).minLong(); + + assertEquals(1L, source.first().longValue()); + } + + @Test + public void emptyLong() { + Ix source = Ix.empty().minLong(); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/OrderByTest.java b/src/test/java/ix/OrderByTest.java new file mode 100644 index 0000000..22d4867 --- /dev/null +++ b/src/test/java/ix/OrderByTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Comparator; + +import org.junit.Test; + +public class OrderByTest { + + @Test + public void normal() { + Ix source = Ix.fromArray(5, 4, 3, 2, 1).orderBy(); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalComparator() { + Ix source = Ix.fromArray(1, 2, 3, 4, 5).orderBy(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalKeySelector() { + Ix source = Ix.fromArray(1, 2, 3, 4, 5).orderBy(new IxFunction() { + @Override + public Integer apply(Integer v) { + return 3 - v; + } + }); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().orderBy(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).orderBy(); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalReverse() { + Ix source = Ix.range(1, 5).orderByReverse(); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalComparatorReverse() { + Ix source = Ix.fromArray(1, 2, 3, 4, 5).orderByReverse(new Comparator() { + @Override + public int compare(Integer a, Integer b) { + return b.compareTo(a); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalKeySelectorReverse() { + Ix source = Ix.fromArray(1, 2, 3, 4, 5).orderByReverse(new IxFunction() { + @Override + public Integer apply(Integer v) { + return 3 - v; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/OrderedMergeTest.java b/src/test/java/ix/OrderedMergeTest.java new file mode 100644 index 0000000..4038293 --- /dev/null +++ b/src/test/java/ix/OrderedMergeTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Comparator; + +import org.junit.Test; + +public class OrderedMergeTest { + + @Test + public void normalArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMergeArray(Ix.fromArray(1, 3), Ix.fromArray(2, 4, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalIterable() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMerge(Ix.fromArray(Ix.fromArray(1, 3), Ix.fromArray(2, 4, 5))); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertNoRemove(source); + } + + @Test + @SuppressWarnings("unchecked") + public void firstEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.empty(), Ix.fromArray(2, 4, 5)); + + IxTestHelper.assertValues(source, 2, 4, 5); + } + + @Test + @SuppressWarnings("unchecked") + public void secondEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.fromArray(1, 3), Ix.empty()); + + IxTestHelper.assertValues(source, 1, 3); + } + + @Test + @SuppressWarnings("unchecked") + public void bothEmptyArray() { + Ix source = Ix.orderedMergeArray(Ix.empty(), Ix.empty()); + + IxTestHelper.assertValues(source); + } + + @Test + public void comparatorArray() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMergeArray( + new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o2.compareTo(o1); + } + }, + Ix.fromArray(3, 1), Ix.fromArray(5, 4, 2)); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void comparatorIterable() { + @SuppressWarnings("unchecked") + Ix source = Ix.orderedMerge(Ix.fromArray(Ix.fromArray(3, 1), Ix.fromArray(5, 4, 2)), + new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o2.compareTo(o1); + } + } + ); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + IxTestHelper.assertNoRemove(source); + } + + @Test + public void lotsOfIterables() { + Ix source = Ix.orderedMerge(Ix.repeatValue(Ix.just(1), 30)).sumInt(); + + IxTestHelper.assertValues(source, 30); + } +} diff --git a/src/test/java/ix/PublishTest.java b/src/test/java/ix/PublishTest.java new file mode 100644 index 0000000..c98252d --- /dev/null +++ b/src/test/java/ix/PublishTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +import org.junit.*; + +public class PublishTest { + + @Test + public void normal() { + final int[] counter = { 0 }; + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + counter[0]++; + } + }) + .publish(); + + Iterator it1 = source.iterator(); + Iterator it2 = source.iterator(); + + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(2, it2.next().intValue()); + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertEquals(4, it2.next().intValue()); + Assert.assertEquals(5, it1.next().intValue()); + + Assert.assertFalse(it1.hasNext()); + Assert.assertFalse(it2.hasNext()); + + Iterator it3 = source.iterator(); + Assert.assertFalse(it3.hasNext()); + + Assert.assertEquals(5, counter[0]); + } + + @Test + public void selector() { + Ix source = Ix.range(1, 5).publish(new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix o) { + return Ix.zip(o, o.skip(1), new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + } + }) + ; + source.println(); + + IxTestHelper.assertValues(source, 4, 9); + } + + @Test + public void selector2() { + Ix source = Ix.range(1, 5).publish(new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix o) { + return Ix.zip(o, o, new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + } + }) + ; + + IxTestHelper.assertValues(source, 3, 7); + } + +} diff --git a/src/test/java/ix/RangeTest.java b/src/test/java/ix/RangeTest.java new file mode 100644 index 0000000..afe4168 --- /dev/null +++ b/src/test/java/ix/RangeTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +import org.junit.*; + +public class RangeTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertNoRemove(source); + } + + @Test(expected = UnsupportedOperationException.class) + public void cantRemove() { + Iterator it = Ix.range(1, 10).iterator(); + it.next(); + it.remove(); + } + + @Test + public void empty() { + Ix source = Ix.range(1, 0); + + Assert.assertSame(Ix.empty(), source); + } + + @Test + public void just() { + Ix source = Ix.range(1, 1); + + Assert.assertTrue(source.getClass().toString(), source instanceof IxScalarCallable); + } + + @Test + public void negativeRange() { + try { + Ix.range(1, -99); + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException ex) { + Assert.assertEquals("count >= 0 required but it was -99", ex.getMessage()); + } + } +} diff --git a/src/test/java/ix/ReadOnlyTest.java b/src/test/java/ix/ReadOnlyTest.java new file mode 100644 index 0000000..98384ab --- /dev/null +++ b/src/test/java/ix/ReadOnlyTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class ReadOnlyTest { + + @Test + public void normal() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + + Ix source = Ix.from(list).readOnly(); + + IxTestHelper.assertValues(source, 1, 2, 3); + IxTestHelper.assertNoRemove(source); + + Assert.assertEquals(3, list.size()); + } + + @Test + public void normalSilent() { + List list = new ArrayList(); + list.add(1); + list.add(2); + list.add(3); + + Ix source = Ix.from(list).readOnly(true); + + IxTestHelper.assertValues(source, 1, 2, 3); + + source.removeAll(); + + Assert.assertEquals(3, list.size()); + + IxTestHelper.assertValues(source, 1, 2, 3); + } +} diff --git a/src/test/java/ix/ReduceTest.java b/src/test/java/ix/ReduceTest.java index 250913a..4f6008b 100644 --- a/src/test/java/ix/ReduceTest.java +++ b/src/test/java/ix/ReduceTest.java @@ -16,48 +16,50 @@ package ix; -import org.junit.*; +import static org.junit.Assert.assertEquals; -import rx.functions.Func2; +import org.junit.Test; public class ReduceTest { @Test - public void single() { - - Object[] a = Ix.just(1).reduce(new Func2() { + public void normal() { + Ix source = Ix.range(1, 10).reduce(new IxSupplier() { @Override - public Integer call(Integer a, Integer b) { + public Integer get() { + return 0; + } + }, new IxFunction2() { + @Override + public Integer apply(Integer a, Integer b) { return a + b; } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { 1 }, a); + }); + + assertEquals(55, source.first().intValue()); } @Test - public void range() { - - Object[] a = Ix.range(1, 3).reduce(new Func2() { + public void aggregate() { + Ix source = Ix.range(1, 10).reduce(new IxFunction2() { @Override - public Integer call(Integer a, Integer b) { + public Integer apply(Integer a, Integer b) { return a + b; } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { 6 }, a); + }); + + assertEquals(55, source.first().intValue()); } @Test - public void empty() { - - Object[] a = Ix.empty().reduce(new Func2() { + public void aggregateEmpty() { + Ix source = Ix.empty().reduce(new IxFunction2() { @Override - public Integer call(Integer a, Integer b) { + public Integer apply(Integer a, Integer b) { return a + b; } - }).toArray(); - - Assert.assertArrayEquals(new Object[] { }, a); + }); + + IxTestHelper.assertValues(source); } } diff --git a/src/test/java/ix/RemoveRetainTest.java b/src/test/java/ix/RemoveRetainTest.java new file mode 100644 index 0000000..ad541ca --- /dev/null +++ b/src/test/java/ix/RemoveRetainTest.java @@ -0,0 +1,184 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.List; + +import org.junit.Test; + +public class RemoveRetainTest { + + @Test + public void removeNormal() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }); + + IxTestHelper.assertValues(source, 2, 4, 6, 8, 10); + IxTestHelper.assertValues(list, 2, 4, 6, 8, 10); + } + + @Test + public void removeAll() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } + + @Test + public void removeNone() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + IxTestHelper.assertValues(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void removeEmpty() { + List list = IxTestHelper.range(1, 0); + + Ix source = Ix.from(list).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } + + @Test + public void retainNormal() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }); + + IxTestHelper.assertValues(source, 1, 3, 5, 7, 9); + IxTestHelper.assertValues(list, 1, 3, 5, 7, 9); + } + + @Test + public void retainAll() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + IxTestHelper.assertValues(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void retainNone() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } + + @Test + public void retainEmpty() { + List list = IxTestHelper.range(1, 0); + + Ix source = Ix.from(list).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } + + @Test + public void removeAllDouble() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }).remove(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) == 0; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } + + @Test + public void retainNoneDouble() { + List list = IxTestHelper.range(1, 10); + + Ix source = Ix.from(list).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) != 0; + } + }).retain(new IxPredicate() { + @Override + public boolean test(Integer v) { + return (v & 1) == 0; + } + }); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(list); + } +} diff --git a/src/test/java/ix/RepeatTest.java b/src/test/java/ix/RepeatTest.java new file mode 100644 index 0000000..e3c8ee7 --- /dev/null +++ b/src/test/java/ix/RepeatTest.java @@ -0,0 +1,257 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.concurrent.Callable; + +import org.junit.Test; + +public class RepeatTest { + + @Test + public void normal() { + Ix source = Ix.repeatValue(1).take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalLimited() { + Ix source = Ix.repeatValue(1, 5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void neverRepeat() { + Ix source = Ix.repeatValue(1, 0); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void repeatOnce() { + Ix source = Ix.repeatValue(1, 1); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateLimited() { + Ix source = Ix.repeatValue(1, new IxBooleanSupplier() { + int count = 5; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateNeverRepeat() { + Ix source = Ix.repeatValue(1, new IxBooleanSupplier() { + @Override + public boolean getAsBoolean() { + return true; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateRepeatOnce() { + Ix source = Ix.repeatValue(1, new IxBooleanSupplier() { + int count = 1; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateInfinite() { + Ix source = Ix.repeatValue(1, new IxBooleanSupplier() { + @Override + public boolean getAsBoolean() { + return false; + } + }).take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateCountedLimited() { + Ix source = Ix.repeatValue(1, 3L, new IxBooleanSupplier() { + int count = 5; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalInstance() { + Ix source = Ix.just(1).repeat().take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalInstanceLimited() { + Ix source = Ix.just(1).repeat(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void neverRepeatInstance() { + Ix source = Ix.just(1).repeat(0); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void repeatOnceInstance() { + Ix source = Ix.just(1).repeat(1); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateLimitedInstance() { + Ix source = Ix.just(1).repeat(new IxBooleanSupplier() { + int count = 5; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateNeverRepeatInstance() { + Ix source = Ix.just(1).repeat(new IxBooleanSupplier() { + @Override + public boolean getAsBoolean() { + return true; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateRepeatOnceInstance() { + Ix source = Ix.just(1).repeat(new IxBooleanSupplier() { + int count = 1; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateInfiniteInstance() { + Ix source = Ix.just(1).repeat(new IxBooleanSupplier() { + @Override + public boolean getAsBoolean() { + return false; + } + }).take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void predicateCountedLimitedInstance() { + Ix source = Ix.just(1).repeat(3L, new IxBooleanSupplier() { + int count = 5; + @Override + public boolean getAsBoolean() { + return count-- == 0; + } + }); + + IxTestHelper.assertValues(source, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void repeatCallable() { + Ix source = Ix.repeatCallable(new Callable() { + @Override + public Integer call() throws Exception { + return 1; + } + }) + .take(5); + + IxTestHelper.assertValues(source, 1, 1, 1, 1, 1); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/ReplayTest.java b/src/test/java/ix/ReplayTest.java new file mode 100644 index 0000000..6221375 --- /dev/null +++ b/src/test/java/ix/ReplayTest.java @@ -0,0 +1,199 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +import org.junit.*; + +public class ReplayTest { + + @Test + public void normal() { + final int[] counter = { 0 }; + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + counter[0]++; + } + }) + .replay(); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + Assert.assertEquals(5, counter[0]); + } + + @Test + public void lockstep() { + final int[] counter = { 0 }; + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + counter[0]++; + } + }) + .replay(); + + Iterator it1 = source.iterator(); + Iterator it2 = source.iterator(); + + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(1, it2.next().intValue()); + + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertEquals(2, it2.next().intValue()); + + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertEquals(3, it2.next().intValue()); + + Assert.assertEquals(4, it1.next().intValue()); + Assert.assertEquals(4, it2.next().intValue()); + + Assert.assertEquals(5, it1.next().intValue()); + Assert.assertEquals(5, it2.next().intValue()); + + Assert.assertFalse(it1.hasNext()); + Assert.assertFalse(it1.hasNext()); + + Assert.assertEquals(5, counter[0]); + + } + + @Test + public void empty() { + Ix source = Ix.empty().replay(); + + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(source); + IxTestHelper.assertValues(source); + } + + @Test + public void replaySizeNormal() { + final int[] counter = { 0 }; + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + counter[0]++; + } + }) + .replay(10); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + Assert.assertEquals(5, counter[0]); + } + + @Test + public void replaySizeLimit() { + final int[] counter = { 0 }; + Ix source = Ix.range(1, 5) + .doOnNext(new IxConsumer() { + @Override + public void accept(Integer v) { + counter[0]++; + } + }) + .replay(2); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + IxTestHelper.assertValues(source, 4, 5); + IxTestHelper.assertValues(source, 4, 5); + + Assert.assertEquals(5, counter[0]); + } + + @Test + public void replaySelectorNormal() { + + Ix source = Ix.range(1, 5).replay(new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix o) { + return Ix.zip(o, o.skip(1), new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + } + }); + + IxTestHelper.assertValues(source, 3, 5, 7, 9); + IxTestHelper.assertValues(source, 3, 5, 7, 9); + } + + @Test + public void replaySizeSelectorLarge() { + + Ix source = Ix.range(1, 5).replay(10, new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix o) { + return Ix.zip(o, o.skip(1), new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + } + }); + + IxTestHelper.assertValues(source, 3, 5, 7, 9); + IxTestHelper.assertValues(source, 3, 5, 7, 9); + } + + @Test + public void replaySizeSelectorSmall() { + + Ix source = Ix.range(1, 5).replay(2, new IxFunction, Iterable>() { + @Override + public Iterable apply(Ix o) { + return Ix.zip(o, o.skip(1), new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + } + }); + + IxTestHelper.assertValues(source, 3, 5, 7, 9); + IxTestHelper.assertValues(source, 3, 5, 7, 9); + } + + @Test + public void replaySizeSelectorInnerEffect() { + + Ix source = Ix.range(1, 5).replay(2, new IxFunction, Iterable>() { + @SuppressWarnings("unchecked") + @Override + public Iterable apply(Ix o) { + return Ix.concatArray(o, o); + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 4, 5); + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 4, 5); + } +} diff --git a/src/test/java/ix/ReverseTest.java b/src/test/java/ix/ReverseTest.java new file mode 100644 index 0000000..961d36d --- /dev/null +++ b/src/test/java/ix/ReverseTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ReverseTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).reverse(); + + IxTestHelper.assertValues(source, 5, 4, 3, 2, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().reverse(); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/ScanTest.java b/src/test/java/ix/ScanTest.java new file mode 100644 index 0000000..14d1fc9 --- /dev/null +++ b/src/test/java/ix/ScanTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ScanTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).scan(new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source, 1, 3, 6, 10, 15); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).scan(new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().scan(new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normalSeed() { + Ix source = Ix.range(1, 5).scan(new IxSupplier() { + @Override + public Integer get() { + return 100; + } + },new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source, 100, 101, 103, 106, 110, 115); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void justSeed() { + Ix source = Ix.just(1).scan(new IxSupplier() { + @Override + public Integer get() { + return 100; + } + }, new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source, 100, 101); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void emptySeed() { + Ix source = Ix.empty().scan(new IxSupplier() { + @Override + public Integer get() { + return 100; + } + }, new IxFunction2() { + @Override + public Integer apply(Integer t1, Integer t2) { + return t1 + t2; + } + }); + + IxTestHelper.assertValues(source, 100); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/SelfComparatorTest.java b/src/test/java/ix/SelfComparatorTest.java new file mode 100644 index 0000000..bbf9112 --- /dev/null +++ b/src/test/java/ix/SelfComparatorTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static ix.SelfComparator.INSTANCE; +import static org.junit.Assert.*; + +import org.junit.Test; + +public class SelfComparatorTest { + + @Test + public void normal() { + assertEquals(0, INSTANCE.compare(1, 1)); + assertEquals(0, INSTANCE.compare(1, new Integer(1))); + + assertTrue(INSTANCE.compare(1, 2) < 0); + + assertTrue(INSTANCE.compare(2, 1) > 0); + + assertNotNull(SelfComparator.valueOf("INSTANCE")); + + assertEquals(1, SelfComparator.values().length); + } +} diff --git a/src/test/java/ix/SequenceEqualTest.java b/src/test/java/ix/SequenceEqualTest.java new file mode 100644 index 0000000..efb94df --- /dev/null +++ b/src/test/java/ix/SequenceEqualTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class SequenceEqualTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 5).sequenceEqual(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, true); + } + + @Test + public void firstSorter() { + Ix source = Ix.range(1, 4).sequenceEqual(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, false); + } + + @Test + public void secondSorter() { + Ix source = Ix.range(1, 5).sequenceEqual(Ix.range(1, 4)); + + IxTestHelper.assertValues(source, false); + } + + @Test + public void firstEmpty() { + Ix source = Ix.empty().sequenceEqual(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, false); + } + + @Test + public void secondEmpty() { + Ix source = Ix.range(1, 5).sequenceEqual(Ix.empty()); + + IxTestHelper.assertValues(source, false); + } + @Test + public void empty() { + Ix source = Ix.empty().sequenceEqual(Ix.empty()); + + IxTestHelper.assertValues(source, true); + } + + @Test + public void different() { + Ix source = Ix.fromArray(1, 2, 3, 3, 5).sequenceEqual(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, false); + } +} diff --git a/src/test/java/ix/SkipLastTest.java b/src/test/java/ix/SkipLastTest.java new file mode 100644 index 0000000..732a455 --- /dev/null +++ b/src/test/java/ix/SkipLastTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class SkipLastTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).skipLast(5); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void normalTwo() { + Ix source = Ix.range(1, 2).skipLast(1); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void normalThree() { + Ix source = Ix.range(1, 16).skipLast(1); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + } + + @Test + public void zero() { + Ix source = Ix.range(1, 10).skipLast(0); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void all() { + Ix source = Ix.range(1, 10).skipLast(10); + + IxTestHelper.assertValues(source); + } + + @Test + public void more() { + Ix source = Ix.range(1, 10).skipLast(15); + + IxTestHelper.assertValues(source); + } + + + @Test + public void just() { + Ix source = Ix.just(1).skipLast(1); + + IxTestHelper.assertValues(source); + } + + @Test + public void empty() { + Ix source = Ix.empty().skipLast(1); + + IxTestHelper.assertValues(source); + } + + @Test + public void emptyZero() { + Ix source = Ix.empty().skipLast(0); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/SkipTest.java b/src/test/java/ix/SkipTest.java index cf54ed3..f4a32f1 100644 --- a/src/test/java/ix/SkipTest.java +++ b/src/test/java/ix/SkipTest.java @@ -16,44 +16,43 @@ package ix; -import java.util.*; - -import org.junit.*; +import org.junit.Test; public class SkipTest { + @Test - public void skipNegative() { - List list = Ix.range(1, 5).skip(-5).toList(); - - Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + public void normal() { + Ix source = Ix.range(1, 10).skip(5); + + IxTestHelper.assertValues(source, 6, 7, 8, 9, 10); } @Test - public void skipZero() { - List list = Ix.range(1, 5).skip(0).toList(); - - Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + public void zero() { + Ix source = Ix.range(1, 10).skip(0); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); } @Test - public void skipSome() { - List list = Ix.range(1, 5).skip(2).toList(); - - Assert.assertEquals(Arrays.asList(3, 4, 5), list); + public void all() { + Ix source = Ix.range(1, 10).skip(10); + + IxTestHelper.assertValues(source); } @Test - public void skipAll() { - List list = Ix.range(1, 5).skip(5).toList(); - - Assert.assertEquals(Arrays.asList(), list); + public void empty() { + Ix source = Ix.empty().skip(10); + + IxTestHelper.assertValues(source); } @Test - public void skipMoreThanAll() { - List list = Ix.range(1, 5).skip(10).toList(); - - Assert.assertEquals(Arrays.asList(), list); + public void emptyZero() { + Ix source = Ix.empty().skip(0); + + IxTestHelper.assertValues(source); } } diff --git a/src/test/java/ix/SkipWhileTest.java b/src/test/java/ix/SkipWhileTest.java new file mode 100644 index 0000000..51a616e --- /dev/null +++ b/src/test/java/ix/SkipWhileTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class SkipWhileTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).skipWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v < 6; + } + }); + + IxTestHelper.assertValues(source, 6, 7, 8, 9, 10); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void skipAll() { + Ix source = Ix.range(1, 10).skipWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void skipNone() { + Ix source = Ix.range(1, 10).skipWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void removeUnskipped() { + List list = IxTestHelper.range(1, 10); + Ix.from(list).skipWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v < 6; + } + }).removeAll(); + + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); + } + +} diff --git a/src/test/java/ix/SourceQueuedIteratorTest.java b/src/test/java/ix/SourceQueuedIteratorTest.java new file mode 100644 index 0000000..551a9cc --- /dev/null +++ b/src/test/java/ix/SourceQueuedIteratorTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.*; + +public class SourceQueuedIteratorTest { + + IxSourceQueuedIterator it; + + @Before + public void before() { + it = new IxSourceQueuedIterator(Ix.empty().iterator()) { + + @Override + protected boolean moveNext() { + return false; + } + }; + } + + @Test + public void normal() { + Assert.assertTrue(it.isEmpty()); + Assert.assertEquals(null, it.peek()); + + it.offer(1); + + Assert.assertFalse(it.isEmpty()); + + Assert.assertEquals(1, it.peek()); + Assert.assertEquals(1, it.poll()); + Assert.assertTrue(it.isEmpty()); + Assert.assertEquals(null, it.peek()); + + Assert.assertNull(it.poll()); + Assert.assertTrue(it.isEmpty()); + } + + @Test(expected = NullPointerException.class) + public void nullOffer() { + it.offer(null); + } + + @Test + public void clear() { + Assert.assertTrue(it.isEmpty()); + + it.offer(1); + + Assert.assertFalse(it.isEmpty()); + + it.clear(); + + Assert.assertNull(it.poll()); + Assert.assertTrue(it.isEmpty()); + } + + @Test + public void nullWraps() { + Assert.assertSame(IxSourceQueuedIterator.NULL, it.toObject(null)); + } + + @Test + public void nullUnwraps() { + Assert.assertNull(it.fromObject(IxSourceQueuedIterator.NULL)); + } + + @Test + public void foreach() { + final int[] count = { 0 }; + it.foreach(new IxConsumer2() { + @Override + public void accept(Integer a, Object b) { + count[0]++; + } + }, null); + + Assert.assertEquals(0, count[0]); + } +} diff --git a/src/test/java/ix/SplitTest.java b/src/test/java/ix/SplitTest.java new file mode 100644 index 0000000..2e75bb7 --- /dev/null +++ b/src/test/java/ix/SplitTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class SplitTest { + + @Test + public void normal() { + Ix source = Ix.split("a|b|c|d", "|"); + + IxTestHelper.assertValues(source, "a", "b", "c", "d"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal2() { + Ix source = Ix.split("a|b|c|", "|"); + + IxTestHelper.assertValues(source, "a", "b", "c", ""); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal3() { + Ix source = Ix.split("a1|b2|c3", "|"); + + IxTestHelper.assertValues(source, "a1", "b2", "c3"); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void normal4() { + Ix source = Ix.split("a1| source = Ix.split("", "|"); + + IxTestHelper.assertValues(source, ""); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/SumTest.java b/src/test/java/ix/SumTest.java new file mode 100644 index 0000000..b758f3d --- /dev/null +++ b/src/test/java/ix/SumTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class SumTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).sumInt(); + + assertEquals(55, source.first().intValue()); + } + + @Test + public void just() { + Ix source = Ix.just(1).sumInt(); + + assertEquals(1, source.first().intValue()); + } + + @Test + public void empty() { + Ix source = Ix.empty().sumInt(); + + IxTestHelper.assertValues(source); + } + + @Test + public void normalLong() { + Ix source = Ix.range(1, 10).toLong().sumLong(); + + assertEquals(55L, source.first().longValue()); + } + + @Test + public void justLong() { + Ix source = Ix.just(1L).sumLong(); + + assertEquals(1, source.first().intValue()); + } + + @Test + public void emptyLong() { + Ix source = Ix.empty().sumLong(); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/SwitchIfEmptyTest.java b/src/test/java/ix/SwitchIfEmptyTest.java new file mode 100644 index 0000000..9d30a3c --- /dev/null +++ b/src/test/java/ix/SwitchIfEmptyTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.List; + +import org.junit.Test; + +public class SwitchIfEmptyTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).switchIfEmpty(Ix.range(11, 10)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void empty() { + Ix source = Ix.empty().switchIfEmpty(Ix.range(11, 10)); + + IxTestHelper.assertValues(source, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20); + } + + @Test + public void emptyOther() { + Ix source = Ix.empty().switchIfEmpty(Ix.empty()); + + IxTestHelper.assertValues(source); + } + + @Test + public void defaultNormal() { + Ix source = Ix.range(1, 10).defaultIfEmpty(100); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void defaultEmpty() { + Ix source = Ix.empty().defaultIfEmpty(100); + + IxTestHelper.assertValues(source, 100); + } + + @Test + public void removeNonEmpty() { + List list = IxTestHelper.range(1, 10); + List list2 = IxTestHelper.range(11, 10); + + Ix.from(list).switchIfEmpty(Ix.from(list2)).removeAll(); + + IxTestHelper.assertValues(list); + IxTestHelper.assertValues(list2, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20); + } + + @Test + public void removeEmpty() { + List list2 = IxTestHelper.range(11, 10); + + Ix.empty().switchIfEmpty(Ix.from(list2)).removeAll(); + + IxTestHelper.assertValues(list2); + } +} diff --git a/src/test/java/ix/TakeLastTest.java b/src/test/java/ix/TakeLastTest.java new file mode 100644 index 0000000..8f4a8ee --- /dev/null +++ b/src/test/java/ix/TakeLastTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class TakeLastTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).takeLast(5); + + IxTestHelper.assertValues(source, 6, 7, 8, 9, 10); + } + + @Test + public void normalTwo() { + Ix source = Ix.range(1, 2).takeLast(1); + + IxTestHelper.assertValues(source, 2); + } + + @Test + public void normalThree() { + Ix source = Ix.range(1, 16).takeLast(15); + + IxTestHelper.assertValues(source, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + } + + @Test + public void zero() { + Ix source = Ix.range(1, 10).takeLast(0); + + IxTestHelper.assertValues(source); + } + + @Test + public void all() { + Ix source = Ix.range(1, 10).takeLast(10); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void more() { + Ix source = Ix.range(1, 10).takeLast(15); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + + @Test + public void just() { + Ix source = Ix.just(1).takeLast(1); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void empty() { + Ix source = Ix.empty().takeLast(1); + + IxTestHelper.assertValues(source); + } + + @Test + public void emptyZero() { + Ix source = Ix.empty().takeLast(0); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/TakeTest.java b/src/test/java/ix/TakeTest.java new file mode 100644 index 0000000..ad186bb --- /dev/null +++ b/src/test/java/ix/TakeTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class TakeTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).take(5); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + } + + @Test + public void all() { + Ix source = Ix.range(1, 10).take(10); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void more() { + Ix source = Ix.range(1, 10).take(15); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void none() { + Ix source = Ix.range(1, 10).take(0); + + IxTestHelper.assertValues(source); + } + + @Test + public void just() { + Ix source = Ix.just(1).take(5); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void empty() { + Ix source = Ix.empty().take(5); + + IxTestHelper.assertValues(source); + } + + @Test + public void removeComposes() { + List list = Ix.range(1, 10).collectToList().first(); + + Ix.from(list).take(5).removeAll(); + + Assert.assertEquals(Arrays.asList(6, 7, 8, 9, 10), list); + } + +} diff --git a/src/test/java/ix/TakeUntilTest.java b/src/test/java/ix/TakeUntilTest.java new file mode 100644 index 0000000..1217717 --- /dev/null +++ b/src/test/java/ix/TakeUntilTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class TakeUntilTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).takeUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 5; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void takeOne() { + Ix source = Ix.range(1, 10).takeUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source, 1); + } + + @Test + public void takeAll() { + Ix source = Ix.range(1, 10).takeUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void removeUnskipped() { + List list = IxTestHelper.range(1, 10); + Ix.from(list).takeUntil(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v == 5; + } + }).removeAll(); + + Assert.assertEquals(Arrays.asList(6, 7, 8, 9, 10), list); + } + +} diff --git a/src/test/java/ix/TakeWhileTest.java b/src/test/java/ix/TakeWhileTest.java new file mode 100644 index 0000000..662eb13 --- /dev/null +++ b/src/test/java/ix/TakeWhileTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class TakeWhileTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).takeWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v < 6; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void takeAll() { + Ix source = Ix.range(1, 10).takeWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return true; + } + }); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + } + + @Test + public void takeNone() { + Ix source = Ix.range(1, 10).takeWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return false; + } + }); + + IxTestHelper.assertValues(source); + } + + @Test + public void removeUnskipped() { + List list = IxTestHelper.range(1, 10); + Ix.from(list).takeWhile(new IxPredicate() { + @Override + public boolean test(Integer v) { + return v < 6; + } + }).removeAll(); + + Assert.assertEquals(Arrays.asList(6, 7, 8, 9, 10), list); + } + +} diff --git a/src/test/java/ix/TestInteractiveConcat.java b/src/test/java/ix/TestInteractiveConcat.java deleted file mode 100644 index 08aa468..0000000 --- a/src/test/java/ix/TestInteractiveConcat.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import java.util.*; - -import org.junit.*; - -import ix.internal.operators.Interactive; - -/** - * Test the concat operator. - */ -public class TestInteractiveConcat { - /** - * Test if concat works correctly when one of the input sequences is empty. - */ - @Test - public void testConcat() { - Iterable one = Collections.singleton(1); - Iterable empty = Collections.emptySet(); - - List> iterables = new ArrayList>(); - iterables.add(one); - iterables.add(empty); - iterables.add(one); - - Iterable concat = Interactive.concat(iterables); - - List result = new ArrayList(); - for (Integer i : concat) { - result.add(i); - } - TestUtil.assertEqual(Arrays.asList(1, 1), result); - } - /** - * Test if concat item removal works when one of the input sequences is empty. - */ - @Test - public void testConcatRemove() { - List> iterables = new ArrayList>(); - - List list1 = TestUtil.newList(1); - List list2 = TestUtil.newList(1); - iterables.add(list1); - iterables.add(Collections.emptyList()); - iterables.add(list2); - - Iterable concat = Interactive.concat(iterables); - - Iterator it = concat.iterator(); - while (it.hasNext()) { - it.next(); - it.remove(); - } - - Assert.assertEquals(0, list1.size()); - Assert.assertEquals(0, list2.size()); - } - -} diff --git a/src/test/java/ix/TestUtil.java b/src/test/java/ix/TestUtil.java deleted file mode 100644 index 10c30f1..0000000 --- a/src/test/java/ix/TestUtil.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2011-2016 David Karnok - * - * Licensed 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 ix; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.junit.Assert; - -/** - * Test utility methods. - */ -public final class TestUtil { - /** Utility class. */ - private TestUtil() { } - - /** - * Returns a user-friendly textual representation of the given sequence. - * @param source the source sequence - * @return the output text - */ - public static String makeString( - Iterable source) { - Iterator iterator = Ix.from(source).join(", ").iterator(); - return iterator.hasNext() ? iterator.next() : ""; - } - /** - * Assert the equivalence of two sequences. - * @param the element type - * @param expected the expected sequence - * @param actual the actual sequence - */ - public static void assertEqual( - Iterable expected, - Iterable actual) { - assertCompare(expected, actual, true); - } - /** - * Assert the inequivalence of two sequences. - * @param the element type - * @param expected the expected sequence - * @param actual the actual sequence - */ - public static void assertNotEqual( - Iterable expected, - Iterable actual) { - assertCompare(expected, actual, false); - } - /** - * Creates a new ArrayList from the elements. - * @param the element type - * @param elements the elements - * @return the list - */ - public static List newList(T... elements) { - return new ArrayList(Arrays.asList(elements)); - } - /** - * Compare two sequences and assert their equivalence. - * @param the element type - * @param expected the expected sequence - * @param actual the actual sequence - * @param eq should they equal? - */ - public static void assertCompare( - Iterable expected, - Iterable actual, boolean eq) { - List expectedList = Ix.from(expected).toList(); - List actualList = Ix.from(actual).toList(); - if (eq != expectedList.equals(actualList)) { - fail(expectedList, actualList); - } - } - /** - * Calls the Assert.fail with a message that displays the expected and actual values as strings. - * @param expected the expected sequence - * @param actual the actual sequence - */ - public static void fail( - Iterable expected, - Iterable actual) { - Assert.fail("Sequences mismatch: expected = " + makeString(expected) + ", actual = " + makeString(actual)); - } - /** - * Test if the actual object is assignable to the expected class. - * @param expectedClass the expected class - * @param actual the actual object - */ - public static void assertInstanceof(Class expectedClass, Object actual) { - if (!expectedClass.isInstance(actual)) { - Assert.fail("Not instance, expected = " + expectedClass + ", actual = " + (actual != null ? actual.getClass() : "null")); - } - } - /** - * Test if the actual object is assignable to the expected class. - * @param expectedClass the expected class - * @param actual the actual object - */ - public static void assertNotInstanceof(Class expectedClass, Object actual) { - if (expectedClass.isInstance(actual)) { - Assert.fail("Shouldn't be an instance, expected = " + expectedClass + ", actual = " + (actual != null ? actual.getClass() : "null")); - } - } -} diff --git a/src/test/java/ix/ToArrayTest.java b/src/test/java/ix/ToArrayTest.java new file mode 100644 index 0000000..ac84213 --- /dev/null +++ b/src/test/java/ix/ToArrayTest.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ToArrayTest { + + @Test + public void normal() { + Ix source = Ix.range(1, 10).collectToArray(); + + IxTestHelper.assertValues(source, new Object[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); + } +} diff --git a/src/test/java/ix/ToListTest.java b/src/test/java/ix/ToListTest.java new file mode 100644 index 0000000..be0c346 --- /dev/null +++ b/src/test/java/ix/ToListTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ToListTest { + + @Test + public void normal() { + Ix source = Ix.just(1); + + assertEquals(1, source.iterator().next().intValue()); + + IxTestHelper.assertValues(source, 1); + } +} diff --git a/src/test/java/ix/ToMapTest.java b/src/test/java/ix/ToMapTest.java new file mode 100644 index 0000000..6c64850 --- /dev/null +++ b/src/test/java/ix/ToMapTest.java @@ -0,0 +1,134 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.Test; + +public class ToMapTest { + + @SuppressWarnings("unchecked") + @Test + public void normal() { + Ix> source = Ix.range(1, 5).collectToMap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }); + + Map map = new HashMap(); + map.put(1, 4); + map.put(0, 3); + map.put(2, 5); + + IxTestHelper.assertValues(source, map); + } + + @SuppressWarnings("unchecked") + @Test + public void normalValueSelector() { + Ix> source = Ix.range(1, 5).collectToMap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }, new IxFunction() { + @Override + public Integer apply(Integer v) { + return v * v; + } + }); + + Map map = new HashMap(); + map.put(1, 16); + map.put(0, 9); + map.put(2, 25); + + IxTestHelper.assertValues(source, map); + } + @SuppressWarnings("unchecked") + @Test + public void empty() { + Ix> source = Ix.empty().collectToMap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }); + + Map map = new HashMap(); + + IxTestHelper.assertValues(source, map); + } + + @SuppressWarnings("unchecked") + @Test + public void multimap() { + Ix>> source = Ix.range(1, 5).collectToMultimap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }); + + Map> map = new HashMap>(); + map.put(1, Arrays.asList(1, 4)); + map.put(0, Arrays.asList(3)); + map.put(2, Arrays.asList(2, 5)); + + IxTestHelper.assertValues(source, map); + } + + @SuppressWarnings("unchecked") + @Test + public void multimapValueSelector() { + Ix>> source = Ix.range(1, 5).collectToMultimap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }, new IxFunction() { + @Override + public Integer apply(Integer v) { + return v * v; + } + }); + + Map> map = new HashMap>(); + map.put(1, Arrays.asList(1, 16)); + map.put(0, Arrays.asList(9)); + map.put(2, Arrays.asList(4, 25)); + + IxTestHelper.assertValues(source, map); + } + @SuppressWarnings("unchecked") + @Test + public void multimapEmpty() { + Ix>> source = Ix.empty().collectToMultimap(new IxFunction() { + @Override + public Integer apply(Integer v) { + return v % 3; + } + }); + + Map> map = new HashMap>(); + + IxTestHelper.assertValues(source, map); + } +} diff --git a/src/test/java/ix/ToSetTest.java b/src/test/java/ix/ToSetTest.java new file mode 100644 index 0000000..535f4b2 --- /dev/null +++ b/src/test/java/ix/ToSetTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.Test; + +public class ToSetTest { + + @SuppressWarnings("unchecked") + @Test + public void normal() { + Ix> source = Ix.range(1, 5).collectToSet(); + + IxTestHelper.assertValues(source, new HashSet(Arrays.asList(1, 2, 3, 4, 5))); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void empty() { + Ix> source = Ix.empty().collectToSet(); + + IxTestHelper.assertValues(source, new HashSet()); + + IxTestHelper.assertNoRemove(source); + } + + @SuppressWarnings("unchecked") + @Test + public void duplicates() { + Ix> source = Ix.fromArray(1, 2, 2, 3, 2, 4, 5, 1, 5).collectToSet(); + + IxTestHelper.assertValues(source, new HashSet(Arrays.asList(1, 2, 3, 4, 5))); + + IxTestHelper.assertNoRemove(source); + } + +} diff --git a/src/test/java/ix/ToXTest.java b/src/test/java/ix/ToXTest.java new file mode 100644 index 0000000..aac4576 --- /dev/null +++ b/src/test/java/ix/ToXTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class ToXTest { + + @Test + public void cast() { + Ix source = Ix.just(1).cast(Object.class); + + IxTestHelper.assertValues(source, 1); + + IxTestHelper.assertNoRemove(source); + } + + @Test(expected = ClassCastException.class) + public void castInvalid() { + Ix source = Ix.just(1).cast(String.class); + + String s = source.first(); + + Assert.assertEquals("1", s); + } + + @Test + public void toArray() { + + Assert.assertArrayEquals(new Object[] {1, 2, 3, 4, 5}, Ix.range(1, 5).toArray()); + + } + + @Test + public void toArrayTemplate() { + + Assert.assertArrayEquals(new Integer[] {1, 2, 3, 4, 5}, Ix.range(1, 5).toArray(new Integer[5])); + + } + + @Test + public void toList() { + Assert.assertEquals(Arrays.asList(1, 2, 3, 4, 5), Ix.range(1, 5).toList()); + + } + + @Test + public void toSet() { + Assert.assertEquals(new HashSet(Arrays.asList(1, 2, 3, 4, 5)), Ix.range(1, 5).toSet()); + + } + + @Test + public void toMap() { + Map map = Ix.range(1, 5).toMap(IdentityHelper.instance()); + + Map expected = new HashMap(); + expected.put(1, 1); + expected.put(2, 2); + expected.put(3, 3); + expected.put(4, 4); + expected.put(5, 5); + + Assert.assertEquals(expected, map); + } + + + @Test + public void toMapCustomValues() { + Map map = Ix.range(1, 5).toMap(IdentityHelper.instance(), new IxFunction() { + @Override + public Integer apply(Integer v) { + return v * v; + } + }); + + Map expected = new HashMap(); + expected.put(1, 1); + expected.put(2, 4); + expected.put(3, 9); + expected.put(4, 16); + expected.put(5, 25); + + Assert.assertEquals(expected, map); + } + + @Test + public void toMultimap() { + Map> map = Ix.range(1, 5).toMultimap(IdentityHelper.instance()); + + Map> expected = new HashMap>(); + expected.put(1, Collections.singletonList(1)); + expected.put(2, Collections.singletonList(2)); + expected.put(3, Collections.singletonList(3)); + expected.put(4, Collections.singletonList(4)); + expected.put(5, Collections.singletonList(5)); + + Assert.assertEquals(expected, map); + } + + + @Test + public void toMultimapCustomValues() { + Map> map = Ix.range(1, 5).toMultimap(IdentityHelper.instance(), new IxFunction() { + @Override + public Integer apply(Integer v) { + return v * v; + } + }); + + Map> expected = new HashMap>(); + expected.put(1, Collections.singletonList(1)); + expected.put(2, Collections.singletonList(4)); + expected.put(3, Collections.singletonList(9)); + expected.put(4, Collections.singletonList(16)); + expected.put(5, Collections.singletonList(25)); + + Assert.assertEquals(expected, map); + } +} diff --git a/src/test/java/ix/TransformTest.java b/src/test/java/ix/TransformTest.java new file mode 100644 index 0000000..f260736 --- /dev/null +++ b/src/test/java/ix/TransformTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Iterator; + +import org.junit.*; + +public class TransformTest { + + @Test + public void normal() { + Ix source = Ix.just(1).transform(new IxTransform() { + @Override + public int moveNext(Iterator it, IxConsumer out) { + if (it.hasNext()) { + out.accept(it.next() + 10); + return IxTransform.NEXT; + } + out.accept(12); + return IxTransform.LAST; + } + }); + + IxTestHelper.assertValues(source, 11, 12); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void stop() { + Ix source = Ix.just(1).transform(new IxTransform() { + @Override + public int moveNext(Iterator it, IxConsumer out) { + return IxTransform.STOP; + } + }); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void doubleNext() { + try { + Ix source = Ix.just(1).transform(new IxTransform() { + @Override + public int moveNext(Iterator it, IxConsumer out) { + out.accept(1); + out.accept(2); + return IxTransform.NEXT; + } + }); + + IxTestHelper.assertValues(source); + + Assert.fail("Failed to throw IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("Value already set in this turn!", ex.getMessage()); + } + } + + @Test + public void returnNextWithoutValue() { + try { + Ix source = Ix.just(1).transform(new IxTransform() { + @Override + public int moveNext(Iterator it, IxConsumer out) { + return IxTransform.NEXT; + } + }); + + IxTestHelper.assertValues(source); + + Assert.fail("Failed to throw IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("No value set!", ex.getMessage()); + } + } +} diff --git a/src/test/java/ix/UnionTest.java b/src/test/java/ix/UnionTest.java new file mode 100644 index 0000000..2b94546 --- /dev/null +++ b/src/test/java/ix/UnionTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class UnionTest { + + @Test + public void distinct() { + Ix source = Ix.range(1, 5).union(Ix.range(6, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void overlap() { + Ix source = Ix.range(1, 5).union(Ix.range(3, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5, 6, 7); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void overlapReverse() { + Ix source = Ix.range(3, 5).union(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 3, 4, 5, 6, 7, 1, 2); + + IxTestHelper.assertNoRemove(source); + } + + + @Test + public void same() { + Ix source = Ix.range(1, 5).union(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void firstInSecond() { + Ix source = Ix.range(1, 3).union(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void secondInFirst() { + Ix source = Ix.range(1, 5).union(Ix.range(1, 3)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void firstEmpty() { + Ix source = Ix.empty().union(Ix.range(1, 5)); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void secondEmpty() { + Ix source = Ix.range(1, 5).union(Ix.empty()); + + IxTestHelper.assertValues(source, 1, 2, 3, 4, 5); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void bothEmpty() { + Ix source = Ix.empty().union(Ix.empty()); + + IxTestHelper.assertValues(source); + + IxTestHelper.assertNoRemove(source); + } + + @Test + public void duplicates() { + Ix source = Ix.fromArray(1, 2, 2, 1, 4, 5).union(Ix.fromArray(2, 3, 1, 5, 4)); + + IxTestHelper.assertValues(source, 1, 2, 4, 5, 3); + + IxTestHelper.assertNoRemove(source); + } +} diff --git a/src/test/java/ix/WindowTest.java b/src/test/java/ix/WindowTest.java new file mode 100644 index 0000000..2269ad0 --- /dev/null +++ b/src/test/java/ix/WindowTest.java @@ -0,0 +1,381 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.*; + +import org.junit.*; + +public class WindowTest { + + @Test + public void normal() { + Ix> source = Ix.range(1, 5).window(2); + + List> list = source.collectToList().first(); + + Assert.assertEquals(3, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2); + IxTestHelper.assertValues(list.get(1), 3, 4); + IxTestHelper.assertValues(list.get(2), 5); + } + + @Test + public void normalSizeSkipSame() { + Ix> source = Ix.range(1, 5).window(2, 2); + + List> list = source.collectToList().first(); + + Assert.assertEquals(3, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2); + IxTestHelper.assertValues(list.get(1), 3, 4); + IxTestHelper.assertValues(list.get(2), 5); + } + + @Test + public void normalOne() { + Ix> source = Ix.range(1, 5).window(1); + + List> list = source.collectToList().first(); + + Assert.assertEquals(5, list.size()); + IxTestHelper.assertValues(list.get(0), 1); + IxTestHelper.assertValues(list.get(1), 2); + IxTestHelper.assertValues(list.get(2), 3); + IxTestHelper.assertValues(list.get(3), 4); + IxTestHelper.assertValues(list.get(4), 5); + } + + @Test + public void normalAll() { + Ix> source = Ix.range(1, 5).window(5); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3, 4, 5); + } + + @Test + public void normalMore() { + Ix> source = Ix.range(1, 5).window(10); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3, 4, 5); + } + + @Test + public void innerMovesParent() { + + Ix> source = Ix.range(1, 5).window(3); + + Iterator> it0 = source.iterator(); + + Ix inner = it0.next(); + + Iterator it1 = inner.iterator(); + + try { + inner.iterator(); + Assert.fail("Should have thrown IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("This Window Ix iterable can be consumed only once.", ex.getMessage()); + } + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + } + + @Test + public void normalSkip() { + Ix> source = Ix.range(1, 5).window(2, 3); + + List> list = source.collectToList().first(); + + Assert.assertEquals(2, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2); + IxTestHelper.assertValues(list.get(1), 4, 5); + } + + @Test + public void normalSkip2() { + Ix> source = Ix.range(1, 5).window(1, 2); + + List> list = source.collectToList().first(); + + Assert.assertEquals(3, list.size()); + IxTestHelper.assertValues(list.get(0), 1); + IxTestHelper.assertValues(list.get(1), 3); + IxTestHelper.assertValues(list.get(2), 5); + } + + @Test + public void normalSkip3() { + Ix> source = Ix.range(1, 5).window(1, 6); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1); + } + + @Test + public void normalAllSkip() { + Ix> source = Ix.range(1, 5).window(5, 10); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3, 4, 5); + } + + @Test + public void normalMoreSkip() { + Ix> source = Ix.range(1, 5).window(10, 15); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3, 4, 5); + } + + @Test + public void justSkip() { + Ix> source = Ix.just(1).window(2, 3); + + List> list = source.collectToList().first(); + + Assert.assertEquals(1, list.size()); + IxTestHelper.assertValues(list.get(0), 1); + } + + @Test + public void emptySkip() { + Ix> source = Ix.empty().window(2, 3); + + List> list = source.collectToList().first(); + + Assert.assertEquals(0, list.size()); + } + + @Test + public void skipInnerMovesParent() { + + Ix> source = Ix.range(1, 5).window(2, 3); + + Iterator> it0 = source.iterator(); + + Ix inner = it0.next(); + + Iterator it1 = inner.iterator(); + + try { + inner.iterator(); + Assert.fail("Should have thrown IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("This Window Ix iterable can be consumed only once.", ex.getMessage()); + } + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + inner = it0.next(); + it1 = inner.iterator(); + + Assert.assertEquals(4, it1.next().intValue()); + Assert.assertEquals(5, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + Assert.assertFalse(it0.hasNext()); + } + + @Test + public void normalOverlap() { + Ix> source = Ix.range(1, 5).window(2, 1); + + List> list = source.collectToList().first(); + + Assert.assertEquals(5, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2); + IxTestHelper.assertValues(list.get(1), 2, 3); + IxTestHelper.assertValues(list.get(2), 3, 4); + IxTestHelper.assertValues(list.get(3), 4, 5); + IxTestHelper.assertValues(list.get(4), 5); + } + + @Test + public void normalOverlap2() { + Ix> source = Ix.range(1, 5).window(3, 1); + + List> list = source.collectToList().first(); + + Assert.assertEquals(5, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3); + IxTestHelper.assertValues(list.get(1), 2, 3, 4); + IxTestHelper.assertValues(list.get(2), 3, 4, 5); + IxTestHelper.assertValues(list.get(3), 4, 5); + IxTestHelper.assertValues(list.get(4), 5); + } + + @Test + public void normalOverlap3() { + Ix> source = Ix.range(1, 5).window(3, 2); + + List> list = source.collectToList().first(); + + Assert.assertEquals(3, list.size()); + IxTestHelper.assertValues(list.get(0), 1, 2, 3); + IxTestHelper.assertValues(list.get(1), 3, 4, 5); + IxTestHelper.assertValues(list.get(2), 5); + } + + @Test + public void nullExact() { + Ix> source = Ix.fromArray(null, null, null, null, null).window(2); + + List> list = source.collectToList().first(); + + Assert.assertEquals(3, list.size()); + IxTestHelper.assertValues(list.get(0), null, null); + IxTestHelper.assertValues(list.get(1), null, null); + IxTestHelper.assertValues(list.get(2), (Integer)null); + } + + @Test + public void nullExact2() { + Ix> source = Ix.fromArray(null, null, null, null, null).window(6); + + Iterator list = source.iterator().next().iterator(); + + Assert.assertNull(list.next()); + Assert.assertNull(list.next()); + Assert.assertNull(list.next()); + Assert.assertNull(list.next()); + Assert.assertNull(list.next()); + Assert.assertFalse(list.hasNext()); + } + + @Test + public void nullSkip() { + Ix> source = Ix.fromArray(null, null, null, null, null).window(2, 3); + + List> list = source.collectToList().first(); + + Assert.assertEquals(2, list.size()); + IxTestHelper.assertValues(list.get(0), null, null); + IxTestHelper.assertValues(list.get(1), null, null); + } + + @Test + public void nullOverlap() { + Ix> source = Ix.fromArray(null, null, null, null, null).window(2, 1); + + List> list = source.collectToList().first(); + + Assert.assertEquals(5, list.size()); + IxTestHelper.assertValues(list.get(0), null, null); + IxTestHelper.assertValues(list.get(1), null, null); + IxTestHelper.assertValues(list.get(2), null, null); + IxTestHelper.assertValues(list.get(3), null, null); + IxTestHelper.assertValues(list.get(4), (Integer)null); + } + + @Test + public void overlapInnerMovesParent() { + + Ix> source = Ix.range(1, 5).window(2, 1); + + Iterator> it0 = source.iterator(); + + Ix inner = it0.next(); + + Iterator it1 = inner.iterator(); + + try { + inner.iterator(); + Assert.fail("Should have thrown IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("This Window Ix iterable can be consumed only once.", ex.getMessage()); + } + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + inner = it0.next(); + it1 = inner.iterator(); + + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + Assert.assertTrue(it0.hasNext()); + } + + @Test + public void overlapInnerMovesParent2() { + + Ix> source = Ix.range(1, 5).window(3, 2); + + Iterator> it0 = source.iterator(); + + Ix inner = it0.next(); + + Iterator it1 = inner.iterator(); + + try { + inner.iterator(); + Assert.fail("Should have thrown IllegalStateException"); + } catch (IllegalStateException ex) { + Assert.assertEquals("This Window Ix iterable can be consumed only once.", ex.getMessage()); + } + Assert.assertEquals(1, it1.next().intValue()); + Assert.assertEquals(2, it1.next().intValue()); + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + inner = it0.next(); + it1 = inner.iterator(); + + Assert.assertEquals(3, it1.next().intValue()); + Assert.assertEquals(4, it1.next().intValue()); + Assert.assertEquals(5, it1.next().intValue()); + Assert.assertFalse(it1.hasNext()); + + Assert.assertTrue(it0.hasNext()); + } + + @Test + public void overlapParentMoved() { + + Ix> source = Ix.range(1, 5).window(4, 3); + + Iterator> it0 = source.iterator(); + + Ix inner1 = it0.next(); + Ix inner2 = it0.next(); + + Assert.assertFalse(it0.hasNext()); + + IxTestHelper.assertValues(inner1, 1, 2, 3, 4); + IxTestHelper.assertValues(inner2, 4, 5); + } + +} diff --git a/src/test/java/ix/Zip2Test.java b/src/test/java/ix/Zip2Test.java new file mode 100644 index 0000000..c6c5dd6 --- /dev/null +++ b/src/test/java/ix/Zip2Test.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class Zip2Test { + + IxFunction2 sum = new IxFunction2() { + @Override + public Integer apply(Integer a, Integer b) { + return a + b; + } + }; + + @Test + public void normal() { + + Ix source = Ix.zip( + Ix.range(1, 2), Ix.range(10, 2), sum); + + IxTestHelper.assertValues(source, 11, 13); + } + + @Test + public void firstShorter() { + + Ix source = Ix.zip( + Ix.range(1, 1), Ix.range(10, 2), sum); + + IxTestHelper.assertValues(source, 11); + } + + @Test + public void secondShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 2), sum); + + IxTestHelper.assertValues(source, 11, 13); + } + + @Test + public void bothEmpty() { + + Ix source = Ix.zip( + Ix.empty(), Ix.empty(), sum); + + IxTestHelper.assertValues(source); + } + + @Test + public void normalWith() { + + Ix source = Ix.range(1, 2).zipWith(Ix.range(10, 2), sum); + + IxTestHelper.assertValues(source, 11, 13); + } + +} diff --git a/src/test/java/ix/Zip3Test.java b/src/test/java/ix/Zip3Test.java new file mode 100644 index 0000000..32172f7 --- /dev/null +++ b/src/test/java/ix/Zip3Test.java @@ -0,0 +1,75 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class Zip3Test { + + IxFunction3 sum = new IxFunction3() { + @Override + public Integer apply(Integer a, Integer b, Integer c) { + return a + b + c; + } + }; + + @Test + public void normal() { + + Ix source = Ix.zip( + Ix.range(1, 2), Ix.range(10, 2), Ix.range(100, 2), sum); + + IxTestHelper.assertValues(source, 111, 114); + } + + @Test + public void firstShorter() { + + Ix source = Ix.zip( + Ix.range(1, 1), Ix.range(10, 2), Ix.range(100, 2), sum); + + IxTestHelper.assertValues(source, 111); + } + + @Test + public void secondShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 2), Ix.range(100, 2), sum); + + IxTestHelper.assertValues(source, 111, 114); + } + + @Test + public void thirdShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 3), Ix.range(100, 2), sum); + + IxTestHelper.assertValues(source, 111, 114); + } + + @Test + public void allEmpty() { + + Ix source = Ix.zip( + Ix.empty(), Ix.empty(), Ix.empty(), sum); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/Zip4Test.java b/src/test/java/ix/Zip4Test.java new file mode 100644 index 0000000..e859894 --- /dev/null +++ b/src/test/java/ix/Zip4Test.java @@ -0,0 +1,84 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class Zip4Test { + + IxFunction4 sum = new IxFunction4() { + @Override + public Integer apply(Integer a, Integer b, Integer c, Integer d) { + return a + b + c + d; + } + }; + + @Test + public void normal() { + + Ix source = Ix.zip( + Ix.range(1, 2), Ix.range(10, 2), Ix.range(100, 2), Ix.range(1000, 2), sum); + + IxTestHelper.assertValues(source, 1111, 1115); + } + + @Test + public void firstShorter() { + + Ix source = Ix.zip( + Ix.range(1, 1), Ix.range(10, 2), Ix.range(100, 2), Ix.range(1000, 2), sum); + + IxTestHelper.assertValues(source, 1111); + } + + @Test + public void secondShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 2), Ix.range(100, 3), Ix.range(1000, 3), sum); + + IxTestHelper.assertValues(source, 1111, 1115); + } + + @Test + public void thirdShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 3), Ix.range(100, 2), Ix.range(1000, 3), sum); + + IxTestHelper.assertValues(source, 1111, 1115); + } + + @Test + public void fourthShorter() { + + Ix source = Ix.zip( + Ix.range(1, 3), Ix.range(10, 3), Ix.range(100, 3), Ix.range(1000, 2), sum); + + IxTestHelper.assertValues(source, 1111, 1115); + } + + @Test + public void allEmpty() { + + Ix source = Ix.zip( + Ix.empty(), Ix.empty(), Ix.empty(), Ix.empty(), sum); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/ZipArrayTest.java b/src/test/java/ix/ZipArrayTest.java new file mode 100644 index 0000000..6b7d6fa --- /dev/null +++ b/src/test/java/ix/ZipArrayTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import org.junit.Test; + +public class ZipArrayTest { + + IxFunction zipper = new IxFunction() { + @Override + public Integer apply(Object[] a) { + return (Integer)a[0] + (Integer)a[1]; + } + }; + + @SuppressWarnings("unchecked") + @Test + public void normal() { + + Ix source = Ix.zip(new Iterable[] { + Ix.range(1, 2), Ix.range(10, 2) }, + zipper); + + IxTestHelper.assertValues(source, 11, 13); + } + + @SuppressWarnings("unchecked") + @Test + public void firstShorter() { + + Ix source = Ix.zip(new Iterable[] { + Ix.range(1, 1), Ix.range(10, 2) }, + zipper); + + IxTestHelper.assertValues(source, 11); + } + + @SuppressWarnings("unchecked") + @Test + public void secondShorter() { + + Ix source = Ix.zip(new Iterable[] { + Ix.range(1, 3), Ix.range(10, 2) }, + zipper); + + IxTestHelper.assertValues(source, 11, 13); + } + + @SuppressWarnings("unchecked") + @Test + public void bothEmpty() { + + Ix source = Ix.zip(new Iterable[] { + Ix.empty(), Ix.empty() }, + zipper); + + IxTestHelper.assertValues(source); + } + +} diff --git a/src/test/java/ix/ZipIterableTest.java b/src/test/java/ix/ZipIterableTest.java new file mode 100644 index 0000000..6220a93 --- /dev/null +++ b/src/test/java/ix/ZipIterableTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2011-2016 David Karnok + * + * Licensed 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 ix; + +import java.util.Arrays; + +import org.junit.Test; + +public class ZipIterableTest { + + IxFunction zipper = new IxFunction() { + @Override + public Integer apply(Object[] a) { + int s = 0; + for (Object o : a) { + s += (Integer)o; + } + return s; + } + }; + + @SuppressWarnings("unchecked") + @Test + public void normal() { + + Ix source = Ix.zip(Arrays.asList( + Ix.range(1, 2), Ix.range(10, 2)), + zipper); + + IxTestHelper.assertValues(source, 11, 13); + } + + @SuppressWarnings("unchecked") + @Test + public void normalMany() { + + Ix source = Ix.zip(Arrays.asList( + Ix.range(1, 2), Ix.range(1, 2), + Ix.range(1, 2), Ix.range(1, 2), + Ix.range(1, 2), Ix.range(1, 2), + Ix.range(1, 2), Ix.range(1, 2), + Ix.range(1, 2), Ix.range(1, 2), + Ix.range(1, 2), Ix.range(1, 2) + ), + zipper); + + IxTestHelper.assertValues(source, 12, 24); + } + + @SuppressWarnings("unchecked") + @Test + public void firstShorter() { + + Ix source = Ix.zip(Arrays.asList( + Ix.range(1, 1), Ix.range(10, 2) ), + zipper); + + IxTestHelper.assertValues(source, 11); + } + + @SuppressWarnings("unchecked") + @Test + public void secondShorter() { + + Ix source = Ix.zip(Arrays.asList( + Ix.range(1, 3), Ix.range(10, 2) ), + zipper); + + IxTestHelper.assertValues(source, 11, 13); + } + + @SuppressWarnings("unchecked") + @Test + public void bothEmpty() { + + Ix source = Ix.zip(Arrays.asList( + Ix.empty(), Ix.empty() ), + zipper); + + IxTestHelper.assertValues(source); + } + +}