Pattern matching on POJOs in Scala? - java

I'm trying to update some of my old Scala code to new APIs.
In one of the libraries I use, a case class has been converted to a simple POJO for compatibility reasons.
I was wondering if it is still possible somehow to use pattern matching for the Java class.
Imagine I have a simple Java class like:
public class A {
private int i;
public A(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
After compilation, I would like to use it in pattern matching somehow like:
class Main extends App {
val a = ...
a match {
case _ # A(i) =>
println(i);
}
}
For the code above, I obviously get an error: Main.scala:7: error: object A is not a case class constructor, nor does it have an unapply/unapplySeq method.
Is there any trick I could use here?
Thanks in advance!

It's a little late in the night here for subtlety, but
object `package` {
val A = AX
}
object AX {
def unapply(a: A): Option[Int] = Some(a.getI)
}
object Test extends App {
Console println {
new A(42) match {
case A(i) => i
}
}
}

Write unapply yourself:
object A {
def unapply(x: A) = Some(x.getI)
}

#som-snytt's answer is correct - but if you are doing this just for e.g. pattern-matching then I prefer the more succinct approach:
import spray.httpx.{UnsuccessfulResponseException => UrUnsuccessfulResponseException}
object UnsuccessfulResponseException {
def unapply(a: UrUnsuccessfulResponseException): Option[HttpResponse]
= Some(a.response)
}
... match {
case Failure(UnsuccessfulResponseException(r)) => r
case ...
}
Ur is a pretentious way of saying "original", but it only takes two letters.

Related

How can I test if a Java object is an enum in scala?

I have a method which converts a string to an int and a Java enum to an int. For other data types, it doesn't do any conversion.
def myConverter[T](attributeValue: T) = {
if (attributeValue.isInstanceOf[String]) {
attributeValue.asInstanceOf[String].toInt
} else if (attributeValue.isInstanceOf[Enumeration$Value]) {
CodeReferenceEx.toInteger(attributeValue.asInstanceOf[Enumeration$Value])
} else {
attributeValue
}
}
The method never enters the elseif block (Enumeration$Value) because the condition is always evaluated to false. I am using a java enumeration object.
Does anyone have any idea? Thanks
Given a Java enum:
public enum C {
ONE, TWO
}
And a Scala enum:
object E extends Enumeration {
val A = Value
}
The following works for both:
def myConverter[T](attributeValue: T) = {
attributeValue match {
case str: String =>
str.toInt
case _: Enumeration =>
println("Scala Enum!")
case _: Enumeration#Value =>
println("Scala Enumeration Value!")
case _ if attributeValue.getClass.isEnum =>
println("Java Enum!")
case _ => println("oops")
}
}
def main(args: Array[String]): Unit = {
myConverter(E)
myConverter(E.A)
myConverter(C.ONE)
}
Yields:
Scala Enum!
Scala Enumeration Value!
Java Enum!
For java enum cast to java.lang.Enum

Scala symbol to java enum

I am using a spray-routing which is pretty elegant with using symbols for parameters. However I am dealing with some legacy code and need to use java enum. Is there some elegant way how to convert scala symbol to java enum?
So the desired code would look as follows:
post {
parameters(('adId.as[String], 'propertyType.as[TypNe])).as(Import) { imp:Import =>
complete {
adImporterService ! imp
StatusCodes.Accepted
}
}
where TypNem is java enum and Import is a scala case class. Instead of
post {
parameters(('adId.as[String], 'propertyType.as[String])) { (aId,pType) =>
complete {
adImporterService ! Import(aId,TypNe.valueOf(pType.toUpperCase()))
StatusCodes.Accepted
}
}
}
For Java Enum PropertyType
public enum PropertyType {
AAA, BBB, CCC
}
You need to provide custom Deserializer
implicit val propertyTypeDeserializer =
new Deserializer[String, PropertyType] {
def apply(s: String): Deserialized[PropertyType] = {
Try(PropertyType.valueOf(s)) match {
case Success(pt) =>
Right(pt)
case Failure(err) =>
Left(MalformedContent("Wrong property type. Accepted values: ${PropertyType.values}", Some(err)))
}
}
}
def receive: Receive = runRoute {
path("test") {
parameter('prop.as[PropertyType]) { case prop =>
get {
complete(s"Result: $prop. Class: ${prop.getClass}")
}
}
}
}
Solution from #Dici also works and much smaller, but with custom Deserializer you are more flexible with error handling
You can use an implicit declaration to improve the readability :
implicit def strToTypeNe = TypNe.valueOf(pType.toUpperCase())

How to check if a scala class is assignable from a java class

I want to be able to check if a certain Scala class is assignable from a certain Java class. As stated here it is not always possible to do D.class.isAssignableFrom(A.class).
Basically what I need is something like this:
def isAssignableFrom(scalaClass: Class[_], javaClass: Class[T]): boolean = {
// magic
}
I have tested:
def m[T: ru.TypeTag, S: ru.TypeTag](x: T, y: S): Boolean = {
val leftTag = ru.typeTag[T]
val rightTag = ru.typeTag[S]
leftTag.tpe <:< rightTag.tpe
}
as stated in the link from above. But it complains about the Java class not having a TypeTag:
error: No TypeTag available for Class[T]
I'm not that familiar with Scala yet so maybe there is a really simple way of doing this?
I managed to solve it like this:
def isAssignableFrom(scalaClass: Class[_], javaClass: Class[T]): Boolean = {
val javaClassType: ru.Type = getType(javaClass)
val scalaClassType: ru.Type = getType(scalaClass)
scalaClassType.<:<(javaClassType)
}
def getType[T](clazz: Class[T]): ru.Type = {
val runtimeMirror = ru.runtimeMirror(clazz.getClassLoader)
runtimeMirror.classSymbol(clazz).toType
}

Collect arguments to apply to curried functions in Java/Scala

I would like to create a class in Java 8 which is able to recursively create an object which has a method that takes a function parameter based on the parameters I added.
For example, I would like to be able to do this:
new X().param(23).param("some String").param(someObject)
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
The apply method would then apply the collected parameters to the given function.
I feel this should be possible without reflection while maintaing type-safety, but I can't quite figure out how. A solution in Scala is also welcome, if I can translate it to Java 8. If it's not possible, I'll also accept an answer that explains why.
What I have so far is essentially this:
class ParamCmd<A,X> {
final A param;
public ParamCmd(A param) {
this.param = param;
}
public<B> ParamCmd<B, Function<A,X>> param(B b) {
return new ParamCmd<>(b);
}
public void apply(Function<A,X> f) {
// this part is unclear to me
}
public static void main(String[] args) {
new ParamCmd<Integer,String>(0).param("oops").param(new Object())
// the constructed function parameters are reversed relative to declaration
.apply((Object c) -> (String b) -> (Integer a) ->
"args were " + a + " " + b + " " + c
);
}
}
As noted in the code comments, my problems are keeping the function parameters in the order of the calls of param(), and actually applying the parameters.
For an unlimited amount of parameters, the only solution I could think of is with Heterogeneous Lists in Scala.
It is probably isn't feasible in Java as there is type level computation going on with path-dependant types.
Using Heterogeneous Lists and Path-Dependant types:
import scala.language.higherKinds
object Main extends App {
val builder1 = HCons(23, HCons("Hello", HNil))
val builder2 = HCons(42L, builder1)
val res1:String = builder1.apply(i => s => i + s)
val res2:String = builder2.apply(l => i => s => (i+l) + s)
println(res1) // 23Hello
println(res2) // 65Hello
}
sealed trait HList {
type F[Res]
def apply[Res]: F[Res] => Res
}
case class HCons[Head, HTail <: HList](head: Head, tail: HTail) extends HList {
type F[Res] = Head => (tail.type)#F[Res]
def apply[Res]: F[Res] => Res = f => tail.apply(f(head))
}
case object HNil extends HList {
type F[Res] = Res
def apply[Res]: F[Res] => Res = identity
}
This code prints:
23Hello
65Hello
The second, more limited way of doing this, but which might work with Java, is to create multiple classes for each function length, which returns the next sized function length class wrapping the value, up to some maximal length - See the Applicative Builder in Scalaz: "Scalaz Applicative Builder"
This doesn't answer your question. However, maybe it helps someone to find a solution, or to explain why it isn't possible in Java and/or Scala.
It can be done in C++, with an arbitrary number of parameters, and without losing type-safety. The call-side look as follows. Unfortunately, the lambda syntax in C++ is quite verbose.
bar{}.param(23).param("some String").param(4.2).apply(
[](int i) {
return [=](std::string s) {
return [=](double d) {
std::cout << i << ' ' << s << ' ' << d << '\n';
};
};
});
Following is the definition of foo and bar. The implementation is straight-forward. However, I doubt that it is possible to build something like this in Java, because the way type parameters work in Java. Generics in Java can only be used to avoid type casts, and that's not enough for this use case.
template <typename Param, typename Tail>
struct foo {
Param _param;
Tail _tail;
template <typename P>
auto param(P p) {
return foo<P, foo>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return _tail.apply(function)(_param);
}
};
struct bar {
template <typename P>
auto param(P p) {
return foo<P, bar>{p, *this};
}
template <typename Function>
auto apply(Function function) {
return function;
}
};
Sorry I just could give some leads in Scala:
Perhaps it would help to have a look at http://www.scala-lang.org/api/2.10.4/index.html#scala.Function$
.apply((Integer a) -> (String b) -> (Object c) -> f(a,b,c))
pretty much looks like Function.uncurried
param(23).param("some String").param(someObject)
could be implemented using a list for an accumulator if you don't care for Type safety. If you want to keep the Types you could use the HList out of Shapeless https://github.com/milessabin/shapeless which comes with a handy tuppled method.
Implementation of param():
import shapeless._
import HList._
import syntax.std.traversable._
class Method(val l : HList = HNil) {
def param(p: Any) = new Method( p :: l )
}
Example
scala> val m = new Method().param(1).param("test")
m: Method = Method#1130ad00
scala> m.l
res8: shapeless.HList = test :: 1 :: HNil

How can I see in what [Java/Scala?] code does Scala compiler rewrites original Scala-code

Following Scala mailing lists, different people often say: "compiler rewrites this [scala] code into this [java/scala??] code". For example, from one of the latest threads, if Scala sees
class C(i: Int = 4) { ... }
then the compiler rewrites this as (effectively):
class C(i: Int) { ... }
object C {
def init$default$1: Int = 4
}
How can I find out, what will be the compiler output for my code? Should I decompile the resulting bytecode for that?
You can use "-print" as compiler option, and scalac will remove all Scala-specific features.
For example, here is the original code:
class Main
{
def test (x: Any) = x match {
case "Hello" => println ("Hello World")
case e: String => println ("String")
case i: Int => println ("Int")
case _ => println ("Something else")
}
}
And if you use "scalac -print" to compile it, you will get the following Scala code.
[[syntax trees at end of cleanup]]// Scala source: Test.scala
package <empty> {
class Main extends java.lang.Object with ScalaObject {
def test(x: java.lang.Object): Unit = {
<synthetic> val temp1: java.lang.Object = x;
if (temp1.==("Hello"))
{
scala.this.Predef.println("Hello World")
}
else
if (temp1.$isInstanceOf[java.lang.String]())
{
scala.this.Predef.println("String")
}
else
if (temp1.$isInstanceOf[Int]())
{
scala.this.Predef.println("Int")
}
else
{
scala.this.Predef.println("Something else")
}
};
def this(): Main = {
Main.super.this();
()
}
}
}
One can look at the generated bytecode with
javap -c -private ClassNameWithoutDotClass

Categories