Skip to content
This repository was archived by the owner on Aug 17, 2019. It is now read-only.

Commit 7622a98

Browse files
committed
API changes and tests
1 parent eb36bb8 commit 7622a98

13 files changed

+385
-69
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2011 Christos KK Loverdos
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.ckkloverdos.props
18+
19+
import com.ckkloverdos.convert.Converters
20+
import java.net.URL
21+
import java.io.InputStream
22+
import java.util.Properties
23+
import com.ckkloverdos.resource.{StreamResourceContext, WrappingStreamResource, StreamResource, DefaultResourceContext}
24+
import com.ckkloverdos.maybe.{NoVal, Maybe}
25+
26+
/**
27+
* Properties with conversion methods.
28+
*
29+
* @author Christos KK Loverdos <loverdos@gmail.com>.
30+
*/
31+
class AnyProps(val map: Map[String, Any])(implicit conv: Converters = Converters.DefaultConverters) extends PropsBase[String, Any, AnyProps]{
32+
def newProps(map: AnyProps#MapType) = new AnyProps(map)
33+
34+
val converters = conv
35+
36+
def getBoolean(key: String, falseStrings: Set[String] = AnyProps.DefaultFalseStrings): Maybe[Boolean] = map.get(key) match {
37+
case Some(value) conv.convertToBoolean(value)
38+
case None NoVal
39+
}
40+
41+
def getByte(key: String): Maybe[Byte] = map.get(key) match {
42+
case Some(value) conv.convertToByte(value)
43+
case None NoVal
44+
}
45+
46+
def getShort(key: String): Maybe[Short] = map.get(key) match {
47+
case Some(value) conv.convertToShort(value)
48+
case None NoVal
49+
}
50+
51+
def getInt(key: String): Maybe[Int] = map.get(key) match {
52+
case Some(value) conv.convertToInt(value)
53+
case None NoVal
54+
}
55+
56+
def getLong(key: String): Maybe[Long] = map.get(key) match {
57+
case Some(value) conv.convertToLong(value)
58+
case None NoVal
59+
}
60+
61+
def getDouble(key: String): Maybe[Double] = map.get(key) match {
62+
case Some(value) conv.convertToDouble(value)
63+
case None NoVal
64+
}
65+
66+
def getFloat(key: String): Maybe[Float] = map.get(key) match {
67+
case Some(value) conv.convertToFloat(value)
68+
case None NoVal
69+
}
70+
71+
def getProps(key: String): Maybe[AnyProps] = map.get(key) match {
72+
case Some(value) conv.convert[AnyProps](value)
73+
case None NoVal
74+
}
75+
76+
def getList(key: String, separatorRegex: String = "\\s*,\\s*") = map.get(key) match {
77+
case Some(value) value match {
78+
case value: String
79+
value.split(separatorRegex).toList
80+
case _
81+
Nil
82+
}
83+
case None Nil
84+
}
85+
86+
def getTrimmedList(key: String, separatorRegex: String = "\\s*,\\s*"): List[String] =
87+
getList(key, separatorRegex).map(_.trim).filter(_.length > 0)
88+
89+
override def equals(any: Any) = any match {
90+
case props: AnyProps props.getClass == this.getClass && props.map == this.map
91+
case _ false
92+
}
93+
94+
def equalsAnyProps(other: AnyProps): Boolean = other match {
95+
case null false
96+
case _ equalsMap(other.map)
97+
}
98+
99+
def equalsMap(other: Map[String, Any]): Boolean = other match {
100+
case null false
101+
case _ other == this.map
102+
}
103+
104+
override def hashCode() = map.##
105+
106+
override def toString = "AnyProps(%s)".format(map.mkString(", "))
107+
}
108+
109+
object AnyProps {
110+
lazy val DefaultFalseStrings = Set("false", "off", "0")
111+
112+
lazy val DummyWrappedURL = new URL("streamresource://wrapped")
113+
lazy val DummyWrappedPath = "wrapped"
114+
115+
lazy val empty = new Props(Map())
116+
117+
def apply(rc: StreamResource)(implicit conv: Converters): Maybe[AnyProps] = {
118+
rc.mapInputStream { in
119+
val props = new java.util.Properties
120+
props.load(in)
121+
import collection.JavaConversions._
122+
props.toMap
123+
} map (new AnyProps(_))
124+
}
125+
126+
def apply(in: InputStream)(implicit conv: Converters): Maybe[AnyProps] =
127+
this(new WrappingStreamResource(in, DummyWrappedPath, DummyWrappedURL))
128+
129+
def apply(props: Properties)(implicit conv: Converters): Maybe[AnyProps] = {
130+
import collection.JavaConversions._
131+
Maybe(new AnyProps(props.toMap))
132+
}
133+
134+
def apply(path: String, rc: StreamResourceContext = DefaultResourceContext)(implicit conv: Converters): Maybe[AnyProps] = {
135+
rc.getResource(path).flatMap(this(_))
136+
}
137+
138+
def apply(keyvals: (String, Any)*)(implicit conv: Converters): AnyProps = new AnyProps(Map(keyvals: _*))
139+
}

src/main/scala/com/ckkloverdos/props/Props.scala

+47-54
Original file line numberDiff line numberDiff line change
@@ -20,102 +20,97 @@ import com.ckkloverdos.resource.{StreamResource, WrappingStreamResource, StreamR
2020
import java.io.InputStream
2121
import java.net.URL
2222
import java.util.Properties
23-
import com.ckkloverdos.maybe.{NoVal, Maybe}
2423
import com.ckkloverdos.convert.Converters
24+
import com.ckkloverdos.maybe.{NoVal, Maybe}
25+
import com.ckkloverdos.key.StringKey
26+
import com.ckkloverdos.env.Env
2527

2628
/**
2729
* Properties with conversion methods.
2830
*
2931
* @author Christos KK Loverdos <loverdos@gmail.com>.
3032
*/
31-
class Props(val map: Map[String, String])(implicit conv: Converters = Converters.DefaultConverters) {
32-
33-
private def _toBoolean(value: String, falseStrings: Set[String]): Boolean = {
34-
if(null eq value) {
35-
throw new NullPointerException("Cannot get a Boolean from null")
36-
} else {
37-
!(falseStrings contains value.toLowerCase)
38-
}
39-
}
40-
41-
def converters = conv
42-
43-
def contains(key: String) = map contains key
44-
45-
def filterKeys(f: String => Boolean) = new Props(map filterKeys f)
46-
47-
def filterValues(f: String => Boolean) = new Props(map filter {case (k, v) => f(v)})
33+
class Props(val map: Map[String, String])(implicit conv: Converters = Converters.DefaultConverters) extends PropsBase[String, String, Props]{
34+
def newProps(map: Props#MapType) = new Props(map)
4835

49-
/**
50-
* Get a value or throw an exception if it doesnot exist.
51-
*/
52-
def getEx(key: String): String = map apply key
36+
def toAnyProps: AnyProps = new AnyProps(map)
5337

54-
def get(key: String): Maybe[String] = map.get(key): Maybe[String]
38+
val converters = conv
5539

56-
def getOr(key: String, default: String = null): String = map.getOrElse(key, default)
57-
58-
def getBoolean(key: String, falseStrings: Set[String] = Props.DefaultFalseStrings): Maybe[Boolean] = map.get(key) match {
59-
case Some(value) => Maybe(_toBoolean(value, falseStrings))
60-
case None => NoVal
40+
def getBoolean(key: String): Maybe[Boolean] = map.get(key) match {
41+
case Some(value) conv.convertToBoolean(value)
42+
case None NoVal
6143
}
6244

6345
def getByte(key: String): Maybe[Byte] = map.get(key) match {
64-
case Some(value) => conv.convertValueToByte(value)
65-
case None => NoVal
66-
}
46+
case Some(value) conv.convertToByte(value)
47+
case None NoVal
48+
}
6749

6850
def getShort(key: String): Maybe[Short] = map.get(key) match {
69-
case Some(value) => conv.convertValueToShort(value)
70-
case None => NoVal
51+
case Some(value) conv.convertToShort(value)
52+
case None NoVal
7153
}
7254

7355
def getInt(key: String): Maybe[Int] = map.get(key) match {
74-
case Some(value) => conv.convertValueToInt(conv)
75-
case None => NoVal
56+
case Some(value) conv.convertToInt(value)
57+
case None NoVal
7658
}
7759

7860
def getLong(key: String): Maybe[Long] = map.get(key) match {
79-
case Some(value) => conv.convertValueToLong(value)
80-
case None => NoVal
61+
case Some(value) conv.convertToLong(value)
62+
case None NoVal
8163
}
8264

8365
def getDouble(key: String): Maybe[Double] = map.get(key) match {
84-
case Some(value) => conv.convertValueToDouble(value)
85-
case None => NoVal
66+
case Some(value) conv.convertToDouble(value)
67+
case None NoVal
8668
}
8769

8870
def getFloat(key: String): Maybe[Float] = map.get(key) match {
89-
case Some(value) => conv.convertValueToFloat(value)
90-
case None => NoVal
71+
case Some(value) conv.convertToFloat(value)
72+
case None NoVal
9173
}
9274

9375
def getProps(key: String): Maybe[Props] = map.get(key) match {
94-
case Some(value) => conv.convertValue(value, manifest[Props])
95-
case None => NoVal
76+
case Some(value) conv.convert[Props](value)
77+
case None NoVal
9678
}
9779

9880
def getList(key: String, separatorRegex: String = "\\s*,\\s*") = map.get(key) match {
99-
case Some(value) => value.split(separatorRegex).toList
100-
case None => Nil
81+
case Some(value) value.split(separatorRegex).toList
82+
case None Nil
10183
}
10284

10385
def getTrimmedList(key: String, separatorRegex: String = "\\s*,\\s*"): List[String] =
10486
getList(key, separatorRegex).map(_.trim).filter(_.length > 0)
10587

10688
override def equals(any: Any) = any match {
107-
case props: Props if(props.getClass == this.getClass) => props.map == this.map
108-
case _ => false
89+
case props: Props if(props.getClass == this.getClass) props.map == this.map
90+
case _ false
10991
}
11092

11193
def equalsProps(other: Props): Boolean = other match {
112-
case null => false
113-
case _ => equalsMap(other.map)
94+
case null false
95+
case _ equalsMap(other.map)
11496
}
11597

11698
def equalsMap(other: Map[String, String]): Boolean = other match {
117-
case null => false
118-
case _ => other == this.map
99+
case null false
100+
case _ other == this.map
101+
}
102+
103+
def toEnv: Env = new Env(map map { case (k, v) (StringKey(k), v)})
104+
105+
def group(keyPrefix: String): Props = {
106+
val dottedPrefix = keyPrefix + "."
107+
val newPairs = for {
108+
key <- map.keysIterator if(key.startsWith(dottedPrefix))
109+
} yield {
110+
key.substring(dottedPrefix.length) -> map(key)
111+
}
112+
113+
new Props(Map(newPairs.toSeq: _*))
119114
}
120115

121116
override def hashCode() = map.##
@@ -124,15 +119,13 @@ class Props(val map: Map[String, String])(implicit conv: Converters = Converters
124119
}
125120

126121
object Props {
127-
lazy val DefaultFalseStrings = Set("false", "off", "0")
128-
129122
lazy val DummyWrappedURL = new URL("streamresource://wrapped")
130123
lazy val DummyWrappedPath = "wrapped"
131124

132125
lazy val empty = new Props(Map())
133126

134127
def apply(rc: StreamResource)(implicit conv: Converters): Maybe[Props] = {
135-
rc.mapInputStream { in =>
128+
rc.mapInputStream { in
136129
val props = new java.util.Properties
137130
props.load(in)
138131
import collection.JavaConversions._
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2011 Christos KK Loverdos
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.ckkloverdos.props
18+
19+
import com.ckkloverdos.convert.Converters
20+
import com.ckkloverdos.maybe.{MaybeOption, NoVal, Maybe}
21+
22+
23+
/**
24+
* Base trait for `Props`, `AnyProps`, parameterized by the type of values.
25+
*
26+
* @author Christos KK Loverdos <loverdos@gmail.com>.
27+
*/
28+
trait PropsBase[K, V, P <: PropsBase[K, V, P]] {
29+
type MapType = Map[K, V]
30+
31+
val map: MapType
32+
val converters: Converters
33+
34+
def newProps(map: MapType): P
35+
36+
def contains(key: K) = map contains key
37+
38+
def filterKeys(f: K => Boolean) = newProps(map filterKeys f)
39+
40+
def filterValues(f: V => Boolean) = newProps(map filter {case (k, v) => f(v)})
41+
42+
/**
43+
* Get a value or throw an exception if it doesnot exist.
44+
*/
45+
@throws(classOf[NoSuchElementException])
46+
def getEx(key: K): V = map apply key
47+
48+
def get(key: K): Maybe[V] = map.get(key): Maybe[V]
49+
50+
def getOr(key: K, default: V): Any = map.getOrElse(key, default)
51+
52+
def size: Int = map.size
53+
54+
def keySet: Set[K] = map.keySet
55+
56+
def keysIterator: Iterator[K] = map.keysIterator
57+
}

src/main/scala/com/ckkloverdos/resource/ClassLoaderStreamResourceContext.scala

+11-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.ckkloverdos.resource
1818

1919
import com.ckkloverdos.maybe.{NoVal, Maybe}
20+
import java.net.URLClassLoader
2021

2122
/**
2223
*
@@ -45,5 +46,14 @@ final class ClassLoaderStreamResourceContext private(
4546
}
4647
}
4748

48-
override def toString = "ClassLoaderStreamResourceContext(%s, %s, %s)".format(cl, parent, extraPath)
49+
override def toString = {
50+
val clStr = cl match {
51+
case urlcs: URLClassLoader
52+
val urls = urlcs.getURLs
53+
"%s@%s(URLs = [%s])".format(urlcs.getClass.getName, System.identityHashCode(urlcs), urls.toList.mkString(", "))
54+
case cl
55+
cl.toString
56+
}
57+
"ClassLoaderStreamResourceContext(%s, %s, %s)".format(clStr, parent, extraPath)
58+
}
4959
}

0 commit comments

Comments
 (0)