WIP: ResourceEvent-related refactorings
[aquarium] / src / main / scala / gr / grnet / aquarium / util / package.scala
index 3897d7f..e4e94b0 100644 (file)
 
 package gr.grnet.aquarium
 
-import com.ckkloverdos.maybe.{Failed, MaybeOption, Just, NoVal, Maybe}
+import scala.collection.mutable.ListBuffer
+import com.ckkloverdos.maybe.{Failed, Just, Maybe}
 import java.nio.charset.Charset
 import java.io.{PrintWriter, StringWriter}
+import annotation.tailrec
 
 
 /**
- * Utility definitions.
+ * Utility functions.
  *
  * @author Christos KK Loverdos <loverdos@gmail.com>.
  */
@@ -63,14 +65,25 @@ package object util {
     }
   }
 
+  def afterLastIndexOf(separator: String, input: String) = {
+    input.substring(input.lastIndexOf(separator) + 1)
+  }
   /**
    * Compute the class name excluding any leading packages.
    *
    * This is basically the name after the last dot.
    */
   def shortNameOfClass(theClass: Class[_]): String = {
-    val cname = theClass.getName
-    cname.substring(cname.lastIndexOf(".") + 1)
+    afterLastIndexOf(".", theClass.getName)
+  }
+
+  /**
+   * Compute the class name excluding any leading packages and any `$` prefixes.
+   *
+   * This is basically the name after the last dot and after any dollar sign.
+   */
+  def simpleNameOfClass(theClass: Class[_]): String = {
+    afterLastIndexOf("$", shortNameOfClass(theClass))
   }
 
   /**
@@ -91,6 +104,15 @@ package object util {
     }
   }
 
+  /**
+   * Compute the class name excluding any leading packages and any `$` prefixes.
+   *
+   * This is basically the name after the last dot and after any dollar sign.
+   */
+  def simpleClassNameOf(anyRef: AnyRef) = {
+    afterLastIndexOf("$", shortClassNameOf(anyRef))
+  }
+
   def safeToStringOrNull(obj: AnyRef): String = obj match {
     case null => null
     case _ => obj.toString
@@ -124,14 +146,8 @@ package object util {
   }
 
   @inline
-  def findAndRemoveFromMap[A, B <: AnyRef](map: scala.collection.mutable.Map[A, B], key: A): Maybe[B] = Maybe {
-    map.get(key) match {
-      case Some(value) ⇒
-        map -= key
-        value
-      case None ⇒
-        null.asInstanceOf[B]
-    }
+  def findAndRemoveFromMap[A, B <: AnyRef](map: scala.collection.mutable.Map[A, B], key: A): Option[B] = {
+    map.remove(key)
   }
 
   // Dear scalac. Optimize this.
@@ -203,4 +219,64 @@ package object util {
 
     sw.toString
   }
+
+  private[this]
+  def chainOfCausesBuffer(t: Throwable): ListBuffer[String] = {
+    @tailrec
+    def loop(t: Throwable, buffer: ListBuffer[String]): ListBuffer[String] = {
+      t match {
+        case null ⇒
+          buffer
+
+        case _ ⇒
+          buffer.append("%s: %s".format(shortClassNameOf(t), t.getMessage))
+          loop(t.getCause, buffer)
+      }
+    }
+
+    loop(t, new ListBuffer[String])
+  }
+
+  def chainOfCauses(t: Throwable): List[String] = {
+    chainOfCausesBuffer(t).toList
+  }
+
+  def sourceOfTraceElement(st: StackTraceElement): Option[String] = {
+    tryOption {
+      val path = Class.forName(st.getClassName).getProtectionDomain.getCodeSource.getLocation.getPath
+      val file = new java.io.File(path)
+      file.getName
+    }
+  }
+
+  def formatTraceElement(st: StackTraceElement): String = {
+    val source = sourceOfTraceElement(st)
+    "%s.%s(%s:%s)%s".format(
+      st.getClassName,
+      st.getMethodName,
+      st.getFileName,
+      st.getLineNumber,
+      if(source.isDefined) " [%s]".format(source.get) else ""
+    )
+  }
+
+  def chainOfCausesForLogging(t: Throwable, caughtTraceIndex: Int = 3) = {
+    val buf = chainOfCausesBuffer(t)
+    val happenedTrace = t.getStackTrace()(0)
+    val caughtTrace = new Exception().getStackTrace()(caughtTraceIndex)
+
+    buf.prepend("[Happened @] %s".format(formatTraceElement(happenedTrace)))
+    buf.prepend("[Caught   @] %s".format(formatTraceElement(caughtTrace)))
+
+    val noNL = buf.map { line ⇒
+      "!! " + line.replaceAll("""[\n\r]+""", ", ")
+    }
+
+    noNL mkString "\n"
+  }
+
+  private[this] lazy val _isRunningTests =
+    new Exception().getStackTrace().find(_.getClassName.startsWith("org.junit")).isDefined
+
+  def isRunningTests() = _isRunningTests
 }
\ No newline at end of file