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

net.codingwell.scalaguice.ScalaModule.scala Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2010-2011 Benjamin Lings
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.codingwell.scalaguice

import com.google.inject._
import binder._
import java.lang.annotation.Annotation

/**
 * Allows binding via type parameters. Mix into AbstractModule
 *  (or subclass) to allow using a type parameter instead of
 * classOf[Foo] or new TypeLiteral[Bar[Foo]] {}.
 *
 * For example, instead of
 * {{{
 * class MyModule extends AbstractModule {
 *   def configure {
 *     bind(classOf[Service]).to(classOf[ServiceImpl]).in(classOf[Singleton])
 *     bind(classOf[CreditCardPaymentService])
 *     bind(new TypeLiteral[Bar[Foo]]{}).to(classOf[FooBarImpl])
 *     bind(classOf[PaymentService]).to(classOf[CreditCardPaymentService])
 *   }
 * }
 * }}}
 * use
 * {{{
 * class MyModule extends AbstractModule with ScalaModule {
 *   def configure {
 *     bind[Service].to[ServiceImpl].in[Singleton]
 *     bind[CreditCardPaymentService]
 *     bind[Bar[Foo]].to[FooBarImpl]
 *     bind[PaymentService].to[CreditCardPaymentService]
 *   }
 * }
 * }}}
 *
 * '''Note''' This syntax allows binding to and from generic types.
 * It doesn't currently allow bindings between wildcard types because the
 * manifests for wildcard types don't provide access to type bounds.
 */

trait InternalModule[B <: Binder] {
  import ScalaModule._

  protected[this] def binderAccess: B

  protected[this] def bind[T: Manifest] = new ScalaAnnotatedBindingBuilder[T] {
    val myBinder = binderAccess
    val self = myBinder.bind(typeLiteral[T])
  }

  protected[this] def bindScope[T <: Annotation : Manifest](scope: Scope) = binderAccess.bindScope(cls[T], scope)
  protected[this] def requestStaticInjection[T: Manifest](): Unit = binderAccess.requestStaticInjection(cls[T])
  protected[this] def getProvider[T: Manifest] = binderAccess.getProvider(cls[T])
  protected[this] def getMembersInjector[T: Manifest] = binderAccess.getMembersInjector(typeLiteral[T])
}

trait ScalaModule extends AbstractModule with InternalModule[Binder] {
  // should be:
  // this: AbstractModule =>
  // see http://lampsvn.epfl.ch/trac/scala/ticket/3564

  //Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
  //So we experimentally figured out how many calls up is the source, so we use that
  //Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
  protected[this] def binderAccess = super.binder.withSource( (new Throwable).getStackTrace()(4) ) // should not need super
}

trait ScalaPrivateModule extends PrivateModule with InternalModule[PrivateBinder] {
  // should be:
  // this: PrivateModule =>
  // see http://lampsvn.epfl.ch/trac/scala/ticket/3564

  import ScalaModule._

  //Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
  //So we experimentally figured out how many calls up is the source, so we use that
  //Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
  protected[this] def binderAccess = super.binder.withSource( (new Throwable).getStackTrace()(5) ) // should not need super

  protected[this] def expose[T: Manifest] = new ScalaAnnotatedElementBuilder[T] {
     val myBinder = binderAccess
     val self = myBinder.expose(typeLiteral[T])
  }
}

object ScalaModule {
  import java.lang.annotation.{Annotation => JAnnotation}

  trait ScalaScopedBindingBuilder extends ScopedBindingBuilderProxy {
    def in[TAnn <: JAnnotation : Manifest]() = self in cls[TAnn]
  }

  trait ScalaLinkedBindingBuilder[T] extends ScalaScopedBindingBuilder
    with LinkedBindingBuilderProxy[T] { outer =>
    def to[TImpl <: T : Manifest] = new ScalaScopedBindingBuilder {
      val self = outer.self to typeLiteral[TImpl]
    }
    def toProvider[TProvider <: Provider[_ <: T] : Manifest] = new ScalaScopedBindingBuilder {
      val self = outer.self toProvider typeLiteral[TProvider]
    }
  }

  trait ScalaAnnotatedBindingBuilder[T] extends ScalaLinkedBindingBuilder[T]
    with AnnotatedBindingBuilderProxy[T] { outer =>
    def annotatedWith[TAnn <: JAnnotation : Manifest] = new ScalaLinkedBindingBuilder[T] {
      val self = outer.self annotatedWith cls[TAnn]
    }
  }

  trait ScalaAnnotatedElementBuilder[T] extends AnnotatedElementBuilderProxy[T] {
    def annotatedWith[TAnn <: JAnnotation : Manifest]() = self annotatedWith cls[TAnn]
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy