All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightbend.lagom.javadsl.api.ScalaServiceSupport.scala Maven / Gradle / Ivy

There is a newer version: 1.5.5
Show newest version
/*
 * Copyright (C) 2016 Lightbend Inc. 
 */
package com.lightbend.lagom.javadsl.api

import java.lang.reflect.Method

import com.lightbend.lagom.javadsl.api.Descriptor.Call

import scala.language.experimental.macros
import scala.language.implicitConversions
import scala.reflect.ClassTag
import scala.reflect.macros.blackbox.Context

/**
 * Support for implementing javadsl service calls with Scala.
 */
object ScalaService {

  import ScalaServiceSupport.ScalaMethodCall

  def call[Request, Response](method: ScalaMethodCall[ServiceCall[Request, Response]]): Call[Request, Response] =
    Service.call[Request, Response](method.method)
  def namedCall[Request, Response](name: String, method: ScalaMethodCall[ServiceCall[Request, Response]]): Call[Request, Response] =
    Service.namedCall[Request, Response](name, method.method)
  def pathCall[Request, Response](path: String, method: ScalaMethodCall[ServiceCall[Request, Response]]): Call[Request, Response] =
    Service.pathCall[Request, Response](path, method.method)
  def restCall[Request, Response](restMethod: transport.Method, path: String, method: ScalaMethodCall[ServiceCall[Request, Response]]): Call[Request, Response] =
    Service.restCall[Request, Response](restMethod, path, method.method)

  def named(name: String): Descriptor = Service.named(name)
}

object ScalaServiceSupport {

  final class ScalaMethodCall[T](val method: Method)
  object ScalaMethodCall {
    implicit def methodFor[T](f: () => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: _ => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
    implicit def methodFor[T](f: (_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) => T): ScalaMethodCall[T] = macro methodForImpl[T]
  }

  def getMethodWithName[T](clazz: Class[_], name: String): ScalaMethodCall[T] = {
    new ScalaMethodCall[T](clazz.getMethods.find(_.getName == name).getOrElse(throw new NoSuchMethodException(name)))
  }

  def methodForImpl[T](c: Context)(f: c.Expr[Any])(implicit tType: c.WeakTypeTag[T]): c.Expr[ScalaMethodCall[T]] = {
    import c.universe._

    f match {
      case Expr(Block((_, Function(_, Apply(Select(This(thisType), TermName(methodName)), _))))) =>
        val methodNameString = Literal(Constant(methodName))
        c.Expr[ScalaMethodCall[T]](q"_root_.com.lightbend.lagom.javadsl.api.ScalaServiceSupport.getMethodWithName[${tType.tpe}](classOf[$thisType], $methodNameString)")
      case other =>
        c.abort(c.enclosingPosition, "methodFor must only be invoked with a reference to a function on this, for example, methodFor(this.someFunction)")
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy