PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/scalate-util/src/main/scala/org/fusesource/scalate/util/Objects.scala

http://github.com/scalate/scalate
Scala | 89 lines | 44 code | 10 blank | 35 comment | 9 complexity | 5d258514aa80fc3797b8153f45f36196 MD5 | raw file
  1. /**
  2. * Copyright (C) 2009-2011 the original author or authors.
  3. * See the notice.md file distributed with this work for additional
  4. * information regarding copyright ownership.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.fusesource.scalate.util
  19. import java.lang.reflect.Constructor
  20. import scala.reflect.ClassTag
  21. /**
  22. * Helper object for working with objects using reflection
  23. */
  24. object Objects {
  25. val log = Log(getClass); import log._
  26. /**
  27. * A helper method to return a non null value or the default value if it is null
  28. */
  29. def getOrElse[T](value: T, defaultValue: => T) = if (value != null) value else defaultValue
  30. /**
  31. * Asserts that the given value is not null with a descriptive message
  32. */
  33. def notNull[T <: AnyRef](value: T, message: => String): T = {
  34. if (value == null) {
  35. throw new IllegalArgumentException(message)
  36. }
  37. value
  38. }
  39. def assertInjected[T <: AnyRef](value: T)(implicit m: ClassTag[T]): T = notNull(value, "Value of type " + m.runtimeClass.getName + " has not been injected!")
  40. /**
  41. * Instantiates the given object class using the possible list of values to be injected.
  42. *
  43. * Implements a really simple IoC mechanism. Ideally we'd improve this to support JSR330 style
  44. * better injection with annotated injection points or such like
  45. */
  46. def instantiate[T](clazz: Class[T], injectionValues: List[AnyRef] = Nil): T =
  47. tryInstantiate[T](clazz, injectionValues) match {
  48. case Some(v) => v
  49. case _ => throw new IllegalArgumentException("No valid constructor could be found for " + clazz.getName +
  50. " and values: " + injectionValues)
  51. }
  52. /**
  53. * Attempts to inject the given class if a constructor can be found
  54. */
  55. def tryInstantiate[T](clazz: Class[T], injectionValues: List[AnyRef] = Nil): Option[T] = {
  56. def argumentValue(paramType: Class[_]): Option[AnyRef] =
  57. injectionValues.find(paramType.isInstance(_))
  58. def create(c: Constructor[_], args: Array[AnyRef]): T = {
  59. val answer = if (args.isEmpty) {
  60. clazz.getConstructor().newInstance()
  61. } else {
  62. debug("About to call constructor: %S on %s with args: %s", c, clazz.getName, args.toList)
  63. c.newInstance(args: _*)
  64. }
  65. answer.asInstanceOf[T]
  66. }
  67. def tryCreate(c: Constructor[_]): Option[T] = {
  68. val options = c.getParameterTypes.map(argumentValue(_))
  69. if (options.forall(_.isDefined)) {
  70. val args = options.map(_.get)
  71. Some(create(c, args))
  72. } else {
  73. None
  74. }
  75. }
  76. val constructors = clazz.getConstructors.sortBy(_.getParameterTypes.size * -1)
  77. constructors.view.map(c => tryCreate(c)).find(_.isDefined).flatten
  78. }
  79. }