kinesis4cats.compat.OptionConverters.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kinesis4cats-compat_2.13 Show documentation
Show all versions of kinesis4cats-compat_2.13 Show documentation
Code to maintain compatability across major scala versions
The newest version!
/*
* Copyright 2023-2023 etspaceman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kinesis4cats.compat
import java.util.{Optional, OptionalDouble, OptionalInt, OptionalLong}
/** This class enables bidirectional conversion between `scala.Option` and the
* set of `java.util.Optional` classes.
*
* The Scala `Option` is generic; its generic counterpart in Java is
* `java.util.Optional`. `Option` is enriched with an `asJava` method, while
* `Optional` is enriched with `asScala` to perform conversions.
*
* In addition, both `Option` and `Optional` are enriched with `asPrimitive`
* methods that will convert generically contained primitives to the manually
* specialized Java versions for primitives, `OptionalDouble`, `OptionalInt`,
* and `OptionalLong`. The primitive versions can be converted to the Scala
* generic `Option` with `asScala` and to the Java generic `Optional` with
* `asGeneric`.
*
* When calling from Java, methods are more convenient than extension methods,
* so `toJava` and `toScala` methods are provided that convert to and from
* Scala's `Option`. Note that `toJava(toScala(x))` will result in a generic
* `Optional` even if `x` was one of the primitive versons.
*
* Example usage:
*
* {{{
* import scala.compat.java8.OptionConverters._
* val a = Option("example").asJava // Creates java.util.Optional[String] containing "example"
* val b = (None: Option[String]).asJava // Creates an empty java.util.Optional[String]
* val c = a.asScala // Back to Option("example")
* val d = b.asScala // Back to None typed as Option[String]
* val e = Option(2.7).asJava // java.util.Optional[Double] containing boxed 2.7
* val f = Option(2.7).asPrimitive // java.util.OptionalDouble containing 2.7 (not boxed)
* val g = f.asScala // Back to Option(2.7)
* val h = f.asGeneric // Same as e
* val i = e.asPrimitive // Same as f
* val j = toJava(Option("example")) // Same as a
* val k = toScala(a) // Same as c
* }}}
*/
object OptionConverters {
/** Type class implementing conversion from generic `Option` or `Optional` to
* manually specialized variants.
*/
sealed abstract class SpecializerOfOptions[A, That] {
/** Converts from `Optional` to a manually specialized variant `That` */
def fromJava(o: Optional[A]): That
/** Converts from `Option` to a manually specialized variant `That` */
def fromScala(o: Option[A]): That
}
/** Implementation of creation of `OptionalDouble` from `Option[Double]` or
* `Optional[Double]`
*/
implicit val specializer_OptionalDouble
: SpecializerOfOptions[Double, OptionalDouble] =
new SpecializerOfOptions[Double, OptionalDouble] {
/** Creates an `OptionalDouble` from `Optional[Double]` */
def fromJava(o: Optional[Double]): OptionalDouble =
if (o.isPresent) OptionalDouble.of(o.get) else OptionalDouble.empty
/** Creates an `OptionalDouble` from `Option[Double]` */
def fromScala(o: Option[Double]): OptionalDouble = o match {
case Some(d) => OptionalDouble.of(d); case _ => OptionalDouble.empty
}
}
/** Implementation of creation of `OptionalInt` from `Option[Int]` or
* `Optional[Int]`
*/
implicit val specializer_OptionalInt: SpecializerOfOptions[Int, OptionalInt] =
new SpecializerOfOptions[Int, OptionalInt] {
/** Creates an `OptionalInt` from `Optional[Int]` */
def fromJava(o: Optional[Int]): OptionalInt =
if (o.isPresent) OptionalInt.of(o.get) else OptionalInt.empty
/** Creates an `OptionalInt` from `Option[Int]` */
def fromScala(o: Option[Int]): OptionalInt = o match {
case Some(d) => OptionalInt.of(d); case _ => OptionalInt.empty
}
}
/** Implementation of creation of `OptionalLong` from `Option[Long]` or
* `Optional[Long]`
*/
implicit val specializer_OptionalLong
: SpecializerOfOptions[Long, OptionalLong] =
new SpecializerOfOptions[Long, OptionalLong] {
/** Creates an `OptionalLong` from `Optional[Long]` */
def fromJava(o: Optional[Long]): OptionalLong =
if (o.isPresent) OptionalLong.of(o.get) else OptionalLong.empty
/** Creates an `OptionalLong` from `Option[Long]` */
def fromScala(o: Option[Long]): OptionalLong = o match {
case Some(d) => OptionalLong.of(d); case _ => OptionalLong.empty
}
}
/** Provides conversions from `java.util.Optional` to Scala `Option` or
* primitive `java.util.Optional` types
*/
implicit class RichOptionalGeneric[A](val underlying: java.util.Optional[A])
extends AnyVal {
/** Create a `scala.Option` version of this `Optional` */
def asScala: Option[A] =
if (underlying.isPresent) Some(underlying.get) else None
/** Create a specialized primitive variant of this generic `Optional`, if an
* appropriate one exists
*/
def asPrimitive[That](implicit
specOp: SpecializerOfOptions[A, That]
): That = specOp.fromJava(underlying)
}
/** Provides conversions from `scala.Option` to Java `Optional` types, either
* generic or primitive
*/
implicit class RichOptionForJava8[A](val underlying: Option[A])
extends AnyVal {
/** Create a `java.util.Optional` version of this `Option` (not specialized)
*/
def asJava: Optional[A] = underlying match {
case Some(a) => Optional.ofNullable(a); case _ => Optional.empty[A]
}
/** Create a specialized primitive `java.util.Optional` type, if an
* appropriate one exists
*/
def asPrimitive[That](implicit
specOp: SpecializerOfOptions[A, That]
): That = specOp.fromScala(underlying)
}
/** Provides conversions from `java.util.OptionalDouble` to the generic
* `Optional` and Scala `Option`
*/
implicit class RichOptionalDouble(val underlying: OptionalDouble)
extends AnyVal {
/** Create a `scala.Option` version of this `OptionalDouble` */
def asScala: Option[Double] =
if (underlying.isPresent) Some(underlying.getAsDouble) else None
/** Create a generic `java.util.Optional` version of this `OptionalDouble`
*/
def asGeneric: Optional[Double] = if (underlying.isPresent)
Optional.of(underlying.getAsDouble)
else Optional.empty[Double]
}
/** Provides conversions from `java.util.OptionalInt` to the generic
* `Optional` and Scala `Option`
*/
implicit class RichOptionalInt(val underlying: OptionalInt) extends AnyVal {
/** Create a `scala.Option` version of this `OptionalInt` */
def asScala: Option[Int] =
if (underlying.isPresent) Some(underlying.getAsInt) else None
/** Create a generic `java.util.Optional` version of this `OptionalInt` */
def asGeneric: Optional[Int] = if (underlying.isPresent)
Optional.of(underlying.getAsInt)
else Optional.empty[Int]
}
/** Provides conversions from `java.util.OptionalLong` to the generic
* `Optional` and Scala `Option`
*/
implicit class RichOptionalLong(val underlying: OptionalLong) extends AnyVal {
/** Create a `scala.Option` version of this `OptionalLong` */
def asScala: Option[Long] =
if (underlying.isPresent) Some(underlying.getAsLong) else None
/** Create a generic `java.util.Optional` version of this `OptionalLong` */
def asGeneric: Optional[Long] = if (underlying.isPresent)
Optional.of(underlying.getAsLong)
else Optional.empty[Long]
}
/** Conversion from Scala `Option` to Java `Optional` without using implicits,
* for convenient use from Java.
*/
final def toJava[A](o: Option[A]): Optional[A] = o match {
case Some(a) => Optional.ofNullable(a); case _ => Optional.empty[A]
}
/** Conversion from Java `Optional` to Scala `Option` without using implicits,
* for convenient use from Java
*/
final def toScala[A](o: Optional[A]): Option[A] =
if (o.isPresent) Some(o.get) else None
/** Conversion from Java `OptionalDouble` to Scala `Option` without using
* implicits, for convenient use from Java
*/
final def toScala(o: OptionalDouble): Option[Double] =
if (o.isPresent) Some(o.getAsDouble) else None
/** Conversion from Java `OptionalInt` to Scala `Option` without using
* implicits, for convenient use from Java
*/
final def toScala(o: OptionalInt): Option[Int] =
if (o.isPresent) Some(o.getAsInt) else None
/** Conversion from Java `OptionalLong` to Scala `Option` without using
* implicits, for convenient use from Java
*/
final def toScala(o: OptionalLong): Option[Long] =
if (o.isPresent) Some(o.getAsLong) else None
}