Replace mapToArray with Streams-based code (#739)

and you can now do (1..10).stream()...
This commit is contained in:
Andrzej Cichocki 2017-06-06 11:02:26 +01:00 committed by GitHub
parent db9cc3a460
commit c2ab4cf26f
9 changed files with 90 additions and 28 deletions

View File

@ -0,0 +1,30 @@
package net.corda.core
import java.util.*
import java.util.Spliterator.*
import java.util.stream.IntStream
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.streams.asSequence
private fun IntProgression.spliteratorOfInt(): Spliterator.OfInt {
val kotlinIterator = iterator()
val javaIterator = object : PrimitiveIterator.OfInt {
override fun nextInt() = kotlinIterator.nextInt()
override fun hasNext() = kotlinIterator.hasNext()
override fun remove() = throw UnsupportedOperationException("remove")
}
val spliterator = Spliterators.spliterator(
javaIterator,
(1 + (last - first) / step).toLong(),
SUBSIZED or IMMUTABLE or NONNULL or SIZED or ORDERED or SORTED or DISTINCT
)
return if (step > 0) spliterator else object : Spliterator.OfInt by spliterator {
override fun getComparator() = Comparator.reverseOrder<Int>()
}
}
fun IntProgression.stream(): IntStream = StreamSupport.intStream(spliteratorOfInt(), false)
@Suppress("UNCHECKED_CAST") // When toArray has filled in the array, the component type is no longer T? but T (that may itself be nullable).
inline fun <reified T> Stream<out T>.toTypedArray() = toArray { size -> arrayOfNulls<T>(size) } as Array<T>

View File

@ -24,7 +24,6 @@ import java.nio.file.*
import java.nio.file.attribute.FileAttribute
import java.time.Duration
import java.time.temporal.Temporal
import java.util.HashMap
import java.util.concurrent.*
import java.util.concurrent.locks.ReentrantLock
import java.util.function.BiConsumer
@ -111,16 +110,6 @@ fun <T> ListenableFuture<T>.andForget(log: Logger) = failure(RunOnCallerThread)
infix fun <F, T> ListenableFuture<F>.map(mapper: (F) -> T): ListenableFuture<T> = Futures.transform(this, { (mapper as (F?) -> T)(it) })
infix fun <F, T> ListenableFuture<F>.flatMap(mapper: (F) -> ListenableFuture<T>): ListenableFuture<T> = Futures.transformAsync(this) { mapper(it!!) }
inline fun <T, reified R> Collection<T>.mapToArray(transform: (T) -> R) = mapToArray(transform, iterator(), size)
inline fun <reified R> IntProgression.mapToArray(transform: (Int) -> R) = mapToArray(transform, iterator(), 1 + (last - first) / step)
inline fun <T, reified R> mapToArray(transform: (T) -> R, iterator: Iterator<T>, size: Int) = run {
var expected = 0
Array(size) {
expected++ == it || throw UnsupportedOperationException("Array constructor is non-sequential!")
transform(iterator.next())
}
}
/** Executes the given block and sets the future to either the result, or any exception that was thrown. */
inline fun <T> SettableFuture<T>.catch(block: () -> T) {
try {

View File

@ -1,7 +1,6 @@
package net.corda.core.crypto
import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.mapToArray
import org.bouncycastle.asn1.ASN1Encodable
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.X500NameBuilder

View File

@ -0,0 +1,42 @@
package net.corda.core
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import java.util.stream.IntStream
import java.util.stream.Stream
import kotlin.test.assertEquals
class StreamsTest {
@Test
fun `IntProgression stream works`() {
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1..4).stream().toArray())
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1 until 5).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..4 step 2).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..3 step 2).stream().toArray())
assertArrayEquals(intArrayOf(), (1..0).stream().toArray())
assertArrayEquals(intArrayOf(1, 0), (1 downTo 0).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 0 step 2).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 1 step 2).stream().toArray())
}
@Test
fun `IntProgression spliterator characteristics and comparator`() {
val rangeCharacteristics = IntStream.range(0, 2).spliterator().characteristics()
val forward = (0..9 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, forward.characteristics())
assertEquals(null, forward.comparator)
val reverse = (9 downTo 0 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, reverse.characteristics())
assertEquals(Comparator.reverseOrder(), reverse.comparator)
}
@Test
fun `Stream toTypedArray works`() {
val a: Array<String> = Stream.of("one", "two").toTypedArray()
assertEquals(Array<String>::class.java, a.javaClass)
assertArrayEquals(arrayOf("one", "two"), a)
val b: Array<String?> = Stream.of("one", "two", null).toTypedArray()
assertEquals(Array<String?>::class.java, b.javaClass)
assertArrayEquals(arrayOf("one", "two", null), b)
}
}

View File

@ -1,16 +1,16 @@
package net.corda.core.crypto
import net.corda.core.mapToArray
import net.corda.core.toTypedArray
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.GeneralName
import org.bouncycastle.asn1.x509.GeneralSubtree
import org.bouncycastle.asn1.x509.NameConstraints
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.junit.Test
import java.security.KeyStore
import java.security.cert.*
import java.util.stream.Stream
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
@ -38,7 +38,7 @@ class X509NameConstraintsTest {
val keyStore = KeyStore.getInstance(KeyStoreUtilities.KEYSTORE_TYPE)
keyStore.load(null, keyPass.toCharArray())
keyStore.addOrReplaceKey(X509Utilities.CORDA_CLIENT_TLS, tlsKey.private, keyPass.toCharArray(),
listOf(tlsCert, clientCACert, intermediateCACert, rootCACert).mapToArray<X509CertificateHolder, Certificate>(converter::getCertificate))
Stream.of(tlsCert, clientCACert, intermediateCACert, rootCACert).map(converter::getCertificate).toTypedArray<Certificate>())
return Pair(keyStore, trustStore)
}

View File

@ -5,14 +5,13 @@ import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
import net.corda.core.crypto.X509Utilities.createSelfSignedCACertificate
import net.corda.core.div
import net.corda.core.mapToArray
import net.corda.core.toTypedArray
import net.corda.testing.MEGA_CORP
import net.corda.testing.getTestX509Name
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.BasicConstraints
import org.bouncycastle.asn1.x509.Extension
import org.bouncycastle.asn1.x509.KeyUsage
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder
import org.junit.Rule
@ -21,7 +20,6 @@ import org.junit.rules.TemporaryFolder
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.IOException
import java.math.BigInteger
import java.net.InetAddress
import java.net.InetSocketAddress
import java.nio.file.Path
@ -31,6 +29,7 @@ import java.security.SecureRandom
import java.security.cert.Certificate
import java.security.cert.X509Certificate
import java.util.*
import java.util.stream.Stream
import javax.net.ssl.*
import kotlin.concurrent.thread
import kotlin.test.*
@ -94,7 +93,7 @@ class X509UtilitiesTest {
// Save the EdDSA private key with self sign cert in the keystore.
val keyStore = KeyStoreUtilities.loadOrCreateKeyStore(tmpKeyStore, "keystorepass")
keyStore.setKeyEntry("Key", keyPair.private, "password".toCharArray(),
listOf(selfSignCert).mapToArray(converter::getCertificate))
Stream.of(selfSignCert).map(converter::getCertificate).toTypedArray())
keyStore.save(tmpKeyStore, "keystorepass")
// Load the keystore from file and make sure keys are intact.
@ -120,7 +119,7 @@ class X509UtilitiesTest {
val converter = JcaX509CertificateConverter()
val keyStore = KeyStoreUtilities.loadOrCreateKeyStore(tmpKeyStore, "keystorepass")
keyStore.setKeyEntry("Key", edDSAKeypair.private, "password".toCharArray(),
listOf(ecDSACert, edDSACert).mapToArray(converter::getCertificate))
Stream.of(ecDSACert, edDSACert).map(converter::getCertificate).toTypedArray())
keyStore.save(tmpKeyStore, "keystorepass")
// Load the keystore from file and make sure keys are intact.
@ -360,7 +359,7 @@ class X509UtilitiesTest {
keyStore.addOrReplaceKey(X509Utilities.CORDA_INTERMEDIATE_CA,
intermediateCAKeyPair.private,
keyPass,
listOf(intermediateCACert, rootCACert).mapToArray<X509CertificateHolder, Certificate>(converter::getCertificate))
Stream.of(intermediateCACert, rootCACert).map(converter::getCertificate).toTypedArray<Certificate>())
keyStore.save(keyStoreFilePath, storePassword)

View File

@ -5,7 +5,7 @@ import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.crypto.*
import net.corda.core.exists
import net.corda.core.mapToArray
import net.corda.core.toTypedArray
import net.corda.core.utilities.ALICE
import net.corda.testing.TestNodeConfiguration
import net.corda.testing.getTestX509Name
@ -32,8 +32,8 @@ class NetworkRegistrationHelperTest {
"CORDA_ROOT_CA")
.map { getTestX509Name(it) }
val converter = JcaX509CertificateConverter()
val certs = identities.map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
.mapToArray(converter::getCertificate)
val certs = identities.stream().map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
.map(converter::getCertificate).toTypedArray()
val certService: NetworkRegistrationService = mock {
on { submitRequest(any()) }.then { id }

View File

@ -13,13 +13,14 @@ import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformNode
import net.corda.core.mapToArray
import net.corda.core.stream
import net.corda.core.toTypedArray
import net.corda.node.services.transactions.minCorrectReplicas
import org.bouncycastle.asn1.x500.X500Name
fun main(args: Array<String>) = BFTNotaryCordform.runNodes()
private val clusterSize = 4 // Minimum size thats tolerates a faulty replica.
private val clusterSize = 4 // Minimum size that tolerates a faulty replica.
private val notaryNames = createNotaryNames(clusterSize)
object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0]) {
@ -38,7 +39,7 @@ object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", not
p2pPort(10005)
rpcPort(10006)
}
val clusterAddresses = (0 until clusterSize).mapToArray { HostAndPort.fromParts("localhost", 11000 + it * 10) }
val clusterAddresses = (0 until clusterSize).stream().mapToObj { HostAndPort.fromParts("localhost", 11000 + it * 10) }.toTypedArray()
fun notaryNode(replicaId: Int, configure: CordformNode.() -> Unit) = node {
name(notaryNames[replicaId])
advertisedServices(advertisedService)

View File

@ -14,6 +14,7 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.BOB
import net.corda.notarydemo.flows.DummyIssueAndMove
import net.corda.notarydemo.flows.RPCStartableNotaryFlowClient
import kotlin.streams.asSequence
fun main(args: Array<String>) {
val address = HostAndPort.fromParts("localhost", 10003)
@ -28,7 +29,8 @@ private class NotaryDemoClientApi(val rpc: CordaRPCOps) {
private val notary by lazy {
val (parties, partyUpdates) = rpc.networkMapUpdates()
partyUpdates.notUsed()
parties.filter { it.advertisedServices.any { it.info.type.isNotary() } }.map { it.notaryIdentity }.distinct().single()
val id = parties.stream().filter { it.advertisedServices.any { it.info.type.isNotary() } }.map { it.notaryIdentity }.distinct().asSequence().singleOrNull()
checkNotNull(id) { "No unique notary identity, try cleaning the node directories." }
}
private val counterpartyNode by lazy {