Statistics
| Branch: | Tag: | Revision:

root / src / main / scala / gr / grnet / aquarium / util / package.scala @ 16e25d79

History | View | Annotate | Download (6.8 kB)

1
/*
2
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
12
 *   2. Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *      disclaimer in the documentation and/or other materials
15
 *      provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * The views and conclusions contained in the software and
31
 * documentation are those of the authors and should not be
32
 * interpreted as representing official policies, either expressed
33
 * or implied, of GRNET S.A.
34
 */
35

    
36
package gr.grnet.aquarium
37

    
38
import com.ckkloverdos.maybe.{Failed, MaybeOption, Just, NoVal, Maybe}
39
import java.nio.charset.Charset
40
import java.io.{PrintWriter, StringWriter}
41
import annotation.tailrec
42

    
43

    
44
/**
45
 * Utility functions.
46
 *
47
 * @author Christos KK Loverdos <loverdos@gmail.com>.
48
 */
49
package object util {
50
  final val UTF_8_Charset = Charset.forName("UTF-8")
51

    
52
  def tryOption[A](f: => A): Option[A] = {
53
    try Some(f)
54
    catch {
55
      case _: Exception => None
56
    }
57
  }
58

    
59
  def withCloseable[C <: { def close(): Unit}, A](c: C)(f: C => A): A = {
60
    try {
61
      f(c)
62
    } finally {
63
      c.close()
64
    }
65
  }
66

    
67
  def afterLastIndexOf(separator: String, input: String) = {
68
    input.substring(input.lastIndexOf(separator) + 1)
69
  }
70
  /**
71
   * Compute the class name excluding any leading packages.
72
   *
73
   * This is basically the name after the last dot.
74
   */
75
  def shortNameOfClass(theClass: Class[_]): String = {
76
    afterLastIndexOf(".", theClass.getName)
77
  }
78

    
79
  /**
80
   * Compute the class name excluding any leading packages and any `$` prefixes.
81
   *
82
   * This is basically the name after the last dot and after any dollar sign.
83
   */
84
  def simpleNameOfClass(theClass: Class[_]): String = {
85
    afterLastIndexOf("$", simpleNameOfClass(theClass))
86
  }
87

    
88
  /**
89
   * For the class of the provided object, compute the class name excluding any leading packages.
90
   *
91
   * This is basically the name after the last dot.
92
   *
93
   * The `null` value is mapped to string `"null"`.
94
   */
95
  def shortClassNameOf(anyRef: AnyRef): String = {
96
    anyRef match {
97
      case null =>
98
        "<null>"
99
      case clz: Class[_] =>
100
        shortNameOfClass(clz)
101
      case obj =>
102
        shortNameOfClass(obj.getClass)
103
    }
104
  }
105

    
106
  /**
107
   * Compute the class name excluding any leading packages and any `$` prefixes.
108
   *
109
   * This is basically the name after the last dot and after any dollar sign.
110
   */
111
  def simpleClassNameOf(anyRef: AnyRef) = {
112
    afterLastIndexOf("$", shortClassNameOf(anyRef))
113
  }
114

    
115
  def safeToStringOrNull(obj: AnyRef): String = obj match {
116
    case null => null
117
    case _ => obj.toString
118
  }
119

    
120
  def displayableObjectInfo(obj: AnyRef): String = {
121
    "[%s] %s".format(obj.getClass, obj)
122
  }
123

    
124
  /**
125
   * This basically turns an [[scala.Option]] into a [[com.ckkloverdos.maybe.Maybe]] when asking a
126
   * [[scala.collection.Map]] for a key.
127
   *
128
   * @param map The input map.
129
   * @param key The key we are interested in.
130
   * @tparam A The type of keys.
131
   * @tparam B The type of values.
132
   *
133
   * @return A [[com.ckkloverdos.maybe.Just]] if a value was found, a
134
   *           [[com.ckkloverdos.maybe.NoVal]] if nothing was found and a
135
   *           [[com.ckkloverdos.maybe.Failed]] if some error happened.
136
   */
137
  @inline
138
  def findFromMapAsMaybe[A, B <: AnyRef](map: scala.collection.Map[A, B], key: A): Maybe[B] = Maybe {
139
    map.get(key) match {
140
      case Some(value) ⇒
141
        value
142
      case None ⇒
143
        null.asInstanceOf[B]
144
    }
145
  }
146

    
147
  @inline
148
  def findAndRemoveFromMap[A, B <: AnyRef](map: scala.collection.mutable.Map[A, B], key: A): Maybe[B] = Maybe {
149
    map.get(key) match {
150
      case Some(value) ⇒
151
        map -= key
152
        value
153
      case None ⇒
154
        null.asInstanceOf[B]
155
    }
156
  }
157

    
158
  // Dear scalac. Optimize this.
159
  def nspaces(n: Int): String = {
160
    ("" /: (1 to n)) ((string, _) => string + " ")
161
  }
162

    
163
  def rpad(s: String, size: Int) = {
164
    s + nspaces((size - s.length()) max 0)
165
  }
166
  
167
  def maxStringSize[A](trav: Traversable[A]): Int = {
168
    (0 /: trav)(_ max _.toString.length)
169
  }
170

    
171
  /**
172
   * Given a [[com.ckkloverdos.maybe.Maybe]] that is actually a [[com.ckkloverdos.maybe.Failed]], return the latter.
173
   *
174
   * Use this only when you are sure what the `maybe` contains, since the methods can break type safety.
175
   *
176
   * @param maybe
177
   * @tparam A
178
   * @return
179
   */
180
  def failedForSure[A](maybe: Maybe[A]): Failed = {
181
    maybe.asInstanceOf[Failed]
182
  }
183

    
184
  /**
185
   * Given a [[com.ckkloverdos.maybe.Maybe]] that is actually a [[com.ckkloverdos.maybe.Just]], return the latter.
186
   *
187
   * Use this only when you are sure what the `maybe` contains, since the methods can break type safety.
188
   *
189
   * @param maybe
190
   * @tparam A
191
   * @return
192
   */
193
  def justForSure[A](maybe: Maybe[A]): Just[A] = {
194
    maybe.asInstanceOf[Just[A]]
195
  }
196

    
197
  /**
198
   * Transform an array of bytes to a string, assuming UTF-8 encoding.
199
   */
200
  def makeString(bytes: Array[Byte]): String = {
201
    new String(bytes, UTF_8_Charset)
202
  }
203

    
204
  /**
205
   * Transform a string to an array of bytes, following a UTF-8 decoding scheme.
206
   */
207
  def makeBytes(string: String): Array[Byte] = {
208
    string.getBytes(UTF_8_Charset)
209
  }
210

    
211
  /**
212
   * Return the stack trace of the given [[java.lang.Throwable]] in the form of [[java.lang.String]].
213
   *
214
   * @param t
215
   * @return
216
   */
217
  def stringOfStackTrace(t: Throwable): String = {
218
    val sw = new StringWriter()
219
    val pw = new PrintWriter(sw)
220

    
221
    t.printStackTrace(pw)
222
    pw.flush()
223
    pw.close()
224

    
225
    sw.toString
226
  }
227

    
228

    
229
  def chainOfCauses(t: Throwable): List[String] = {
230
    import scala.collection.mutable.ListBuffer
231
    @tailrec
232
    def loop(t: Throwable, buffer: ListBuffer[String]): List[String] = {
233
      t match {
234
        case null ⇒
235
          buffer.toList
236

    
237
        case _ ⇒
238
          buffer.append("%s(%s)".format(shortClassNameOf(t), t.getMessage))
239
          loop(t.getCause, buffer)
240
      }
241
    }
242

    
243
    loop(t, new ListBuffer[String])
244
  }
245
}