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

Commit c09f3bd

Browse files
committed
WIP on hints. Compiles but tests fail
1 parent 3fc1718 commit c09f3bd

7 files changed

+118
-97
lines changed

src/main/scala/com/ckkloverdos/convert/ConverterBase.scala

+34-34
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,29 @@ import com.ckkloverdos.maybe.MaybeEither
2727
trait ConverterBase {
2828
protected val logger = LoggerFactory.getLogger(getClass)
2929

30-
def canConvertValueToType[S: Type, T: Type](sourceValue: S): Boolean =
31-
canConvertType[S, T]
30+
def canConvertValueToType[S: Type, T: Type](sourceValue: S, hint: AnyRef = EmptyHint): Boolean =
31+
canConvertType[S, T](hint)
3232

33-
def canConvertValueToValue[S: Type, T: Type](sourceValue: S, targetValue: T): Boolean =
34-
canConvertType[S, T]
33+
def canConvertValueToValue[S: Type, T: Type](sourceValue: S, targetValue: T, hint: AnyRef = EmptyHint): Boolean =
34+
canConvertType[S, T](hint)
3535

36-
def canConvertType[S: Type, T: Type]: Boolean
36+
def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean
3737

3838
/**
3939
* Convert or throw an exception.
4040
*
4141
* This is a low-level function.
4242
*/
4343
@throws(classOf[ConverterException])
44-
def convertEx[T: Type](sourceValue: Any): T
44+
def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): T
4545

46-
def convert[T: Type](sourceValue: Any): MaybeEither[T] = MaybeEither {
46+
def convert[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): MaybeEither[T] = MaybeEither {
4747
// logger.debug("ConverterBase::convert(%s: %s): %s".format(sourceValue, sourceValue.getClass, manifest[T]))
48-
convertEx[T](sourceValue)
48+
convertEx[T](sourceValue, hint)
4949
}
5050

51-
def convertOpt[T: Type](sourceValue: Any): Option[T] = {
52-
try Some(convertEx[T](sourceValue))
51+
def convertOpt[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): Option[T] = {
52+
try Some(convertEx[T](sourceValue, hint))
5353
catch {
5454
case e: Error
5555
throw e
@@ -59,51 +59,51 @@ trait ConverterBase {
5959
}
6060
}
6161

62-
def convertToByte[S: Type](sourceValue: S): MaybeEither[Byte] = convert[Byte](sourceValue)
62+
def convertToByte[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Byte] = convert[Byte](sourceValue, hint)
6363

64-
def convertToByteOpt[S: Type](sourceValue: S): Option[Byte] = convertOpt[Byte](sourceValue)
64+
def convertToByteOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Byte] = convertOpt[Byte](sourceValue, hint)
6565

66-
def convertToByteEx[S: Type](sourceValue: S): Byte = convertEx[Byte](sourceValue)
66+
def convertToByteEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Byte = convertEx[Byte](sourceValue, hint)
6767

68-
def convertToBoolean[S: Type](sourceValue: S): MaybeEither[Boolean] = convert[Boolean](sourceValue)
68+
def convertToBoolean[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Boolean] = convert[Boolean](sourceValue, hint)
6969

70-
def convertToBooleanOpt[S: Type](sourceValue: S): Option[Boolean] = convertOpt[Boolean](sourceValue)
70+
def convertToBooleanOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Boolean] = convertOpt[Boolean](sourceValue, hint)
7171

72-
def convertToBooleanEx[S: Type](sourceValue: S): Boolean = convertEx[Boolean](sourceValue)
72+
def convertToBooleanEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Boolean = convertEx[Boolean](sourceValue, hint)
7373

74-
def convertToShort[S: Type](sourceValue: S): MaybeEither[Short] = convert[Short](sourceValue)
74+
def convertToShort[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Short] = convert[Short](sourceValue, hint)
7575

76-
def convertToShortOpt[S: Type](sourceValue: S): Option[Short] = convertOpt[Short](sourceValue)
76+
def convertToShortOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Short] = convertOpt[Short](sourceValue, hint)
7777

78-
def convertToShortEx[S: Type](sourceValue: S): Short = convertEx[Short](sourceValue)
78+
def convertToShortEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Short = convertEx[Short](sourceValue, hint)
7979

80-
def convertToChar[S: Type](sourceValue: S): MaybeEither[Char] = convert[Char](sourceValue)
80+
def convertToChar[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Char] = convert[Char](sourceValue, hint)
8181

82-
def convertToCharOpt[S: Type](sourceValue: S): Option[Char] = convertOpt[Char](sourceValue)
82+
def convertToCharOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Char] = convertOpt[Char](sourceValue, hint)
8383

84-
def convertToCharEx[S: Type](sourceValue: S): Char = convertEx[Char](sourceValue)
84+
def convertToCharEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Char = convertEx[Char](sourceValue, hint)
8585

86-
def convertToInt[S: Type](sourceValue: S): MaybeEither[Int] = convert[Int](sourceValue)
86+
def convertToInt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Int] = convert[Int](sourceValue, hint)
8787

88-
def convertToIntOpt[S: Type](sourceValue: S): Option[Int] = convertOpt[Int](sourceValue)
88+
def convertToIntOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Int] = convertOpt[Int](sourceValue, hint)
8989

90-
def convertToIntEx[S: Type](sourceValue: S): Int = convertEx[Int](sourceValue)
90+
def convertToIntEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Int = convertEx[Int](sourceValue, hint)
9191

92-
def convertToLong[S: Type](sourceValue: S): MaybeEither[Long] = convert[Long](sourceValue)
92+
def convertToLong[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Long] = convert[Long](sourceValue, hint)
9393

94-
def convertToLongOpt[S: Type](sourceValue: S): Option[Long] = convertOpt[Long](sourceValue)
94+
def convertToLongOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Long] = convertOpt[Long](sourceValue, hint)
9595

96-
def convertToLongEx[S: Type](sourceValue: S): Long = convertEx[Long](sourceValue)
96+
def convertToLongEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Long = convertEx[Long](sourceValue, hint)
9797

98-
def convertToFloat[S: Type](sourceValue: S): MaybeEither[Float] = convert[Float](sourceValue)
98+
def convertToFloat[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Float] = convert[Float](sourceValue, hint)
9999

100-
def convertToFloatOpt[S: Type](sourceValue: S): Option[Float] = convertOpt[Float](sourceValue)
100+
def convertToFloatOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Float] = convertOpt[Float](sourceValue, hint)
101101

102-
def convertToFloatEx[S: Type](sourceValue: S): Float = convertEx[Float](sourceValue)
102+
def convertToFloatEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Float = convertEx[Float](sourceValue, hint)
103103

104-
def convertToDouble[S: Type](sourceValue: S): MaybeEither[Double] = convert[Double](sourceValue)
104+
def convertToDouble[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): MaybeEither[Double] = convert[Double](sourceValue, hint)
105105

106-
def convertToDoubleOpt[S: Type](sourceValue: S): Option[Double] = convertOpt[Double](sourceValue)
106+
def convertToDoubleOpt[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Option[Double] = convertOpt[Double](sourceValue, hint)
107107

108-
def convertToDoubleEx[S: Type](sourceValue: S): Double = convertEx[Double](sourceValue)
108+
def convertToDoubleEx[S: Type](sourceValue: S, hint: AnyRef = EmptyHint): Double = convertEx[Double](sourceValue, hint)
109109
}

src/main/scala/com/ckkloverdos/convert/Converters.scala

+10-7
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,34 @@ import com.ckkloverdos.maybe._
2525
* @author Christos KK Loverdos <loverdos@gmail.com>.
2626
*/
2727
class Converters(selector: ConverterSelectionStrategy) extends ConverterBase {
28-
def canConvertType[S: Type, T: Type]: Boolean = selector.canConvertType[S, T]
28+
def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean = selector.canConvertType[S, T](hint)
2929

30-
def findConverter[S : Type, T : Type]: Maybe[Converter] = {
30+
def findConverter[S : Type, T : Type](hint: AnyRef = EmptyHint): Maybe[Converter] = {
3131
val sm = typeOf[S]
3232
val tm = typeOf[T]
3333
// logger.debug("findConverter(%s, %s)".format(sm, tm))
34-
selector.find(sm, tm)
34+
selector.find(sm, tm, hint)
3535
}
3636

3737
/**
3838
* Converts a value or throws an exception if the value cannot be converted.
3939
*/
4040
@throws(classOf[ConverterException])
41-
def convertEx[T: Type](sourceValue: Any): T = {
41+
def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): T = {
4242
val sm = typeOfAny(sourceValue)
4343
val tm = typeOf[T]
4444
// logger.debug("[1] Converters::convertEx(%s: %s)(tm=%s)".format(sourceValue, if(null eq sourceValue.asInstanceOf[AnyRef]) "Null" else sourceValue.getClass, tm))
4545
// logger.debug("[2] Converters::convertEx(%s: %s): %s".format(sourceValue, sm, tm))
46-
findConverter(sm, tm) match {
46+
findConverter(sm, tm, hint) match {
4747
case Just(cv)
4848
try {
4949
// logger.debug("Converters::convertEx:: found %s".format(cv))
50-
cv.convertEx[T](sourceValue)
50+
cv.convertEx[T](sourceValue, hint)
5151
} catch {
52-
case e: Exception =>
52+
case e: Error
53+
throw e
54+
55+
case e: Exception
5356
val errMsg = "Error converting %s -> %s for value %s".format(sm, tm, sourceValue)
5457
// logger.error("Converters::convertEx:: " + errMsg)
5558
ConverterException(e, errMsg)

src/main/scala/com/ckkloverdos/convert/IdentityConverter.scala

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ package com.ckkloverdos.convert
2525
object IdentityConverter extends Converter {
2626
def isStrictSource = false
2727

28-
def canConvertType[S: Type, T: Type]: Boolean = {
28+
/**
29+
* Ignores the `hint`.
30+
*/
31+
def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean = {
2932
typeOf[S] == typeOf[T]
3033
}
3134

3235
@throws(classOf[ConverterException])
33-
def convertEx[T: Type](sourceValue: Any): T = {
36+
def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): T = {
3437
val tm = typeOf[T]
3538
try sourceValue.asInstanceOf[T]
3639
catch {

src/main/scala/com/ckkloverdos/convert/SourceTargetConverter.scala

+45-32
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@ class SourceTargetConverter[SS, TT](
2424
val sourceType: Type[SS],
2525
val targetType: Type[TT],
2626
val isStrictSource: Boolean,
27-
val function: SS => TT)
28-
extends Converter {
27+
val function: SS => TT,
28+
val theHint: AnyRef = EmptyHint
29+
) extends Converter {
2930

30-
def canConvertType[S: Type, T: Type]: Boolean = {
31-
val sm = typeOf[S]
32-
val tm = typeOf[T]
31+
def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean = {
32+
(theHint == hint) && {
33+
val sm = typeOf[S]
34+
val tm = typeOf[T]
3335

34-
// logger.debug("canConvertType(%s, %s), sourceType=%s, targetType=%s".format(sm, tm, sourceType, targetType))
36+
// logger.debug("canConvertType(%s, %s), sourceType=%s, targetType=%s".format(sm, tm, sourceType, targetType))
3537

36-
if(isStrictSource)
37-
canConvertStrictSource(sm, tm)
38-
else
39-
canConvertNonStrictSource(sm, tm)
38+
if(isStrictSource)
39+
canConvertStrictSource(sm, tm)
40+
else
41+
canConvertNonStrictSource(sm, tm)
42+
}
4043
}
4144

4245
private[this] def canConvertStrictSource(sm: Type[_], tm: Type[_]) = {
@@ -59,23 +62,31 @@ class SourceTargetConverter[SS, TT](
5962

6063

6164
@throws(classOf[ConverterException])
62-
def convertEx[T: Type](sourceValue: Any): T = {
65+
def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint): T = {
6366
val tm = typeOf[T]
64-
if(targetType != tm) {
65-
ConverterException("Unexpeced target type %s. It should have been %s".format(tm, targetType))
66-
}
67-
try function(sourceType.erasure.cast(sourceValue).asInstanceOf[SS]).asInstanceOf[T]
68-
catch {
69-
case e: ClassCastException
70-
val msg = "tm=%s, targetType=%s, sourceType=%s".format(tm, targetType, sourceType)
71-
ConverterException(e, "[%s] Unexpected failure converting %s -> %s for value %s".format(msg, sourceValue.getClass, tm.erasure, sourceValue))
72-
case e: Exception
73-
ConverterException(e, "Error converting %s -> %s for value %s".format(sourceValue.getClass, tm, sourceValue))
67+
if(theHint == hint) {
68+
if(targetType != tm) {
69+
ConverterException("Unexpeced target type %s. It should have been %s".format(tm, targetType))
70+
}
71+
try function(sourceType.erasure.cast(sourceValue).asInstanceOf[SS]).asInstanceOf[T]
72+
catch {
73+
case e: Error
74+
throw e
75+
76+
case e: ClassCastException
77+
val msg = "tm=%s, targetType=%s, sourceType=%s".format(tm, targetType, sourceType)
78+
ConverterException(e, "[%s] Unexpected failure converting %s -> %s for value %s".format(msg, sourceValue.getClass, tm.erasure, sourceValue))
79+
80+
case e: Exception
81+
ConverterException(e, "Error converting %s -> %s for value %s".format(sourceValue.getClass, tm, sourceValue))
82+
}
83+
} else {
84+
ConverterException("Error converting %s -> %s for value %s. Uknown hint %s".format(sourceValue.getClass, tm, sourceValue, hint))
7485
}
7586
}
7687

7788
override def toString() =
78-
"STConverter(" + List(sourceType, targetType, isStrictSource, function).mkString(",") + ")"
89+
"STConverter(" + List(sourceType, targetType, isStrictSource, function, theHint).mkString(",") + ")"
7990
}
8091

8192
object SourceTargetConverter {
@@ -112,8 +123,9 @@ object SourceTargetConverter {
112123
}
113124
}
114125

115-
abstract class StrictSourceConverterSkeleton[SS: Type, TT: Type] extends Converter {
116-
final def canConvertType[S: Type, T: Type]: Boolean = {
126+
abstract class StrictSourceConverterSkeleton[SS: Type, TT: Type](theHint: AnyRef = EmptyHint) extends Converter {
127+
final def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean = {
128+
(theHint == hint) &&
117129
SourceTargetConverter.canConvertWithStrictSource(typeOf[SS], typeOf[TT], typeOf[S], typeOf[T])
118130
}
119131

@@ -125,16 +137,17 @@ abstract class StrictSourceConverterSkeleton[SS: Type, TT: Type] extends Convert
125137
* This is a low-level function.
126138
*/
127139
@throws(classOf[ConverterException])
128-
final def convertEx[T: Type](sourceValue: Any) = {
129-
convertEx_(sourceValue.asInstanceOf[SS]).asInstanceOf[T]
140+
final def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint) = {
141+
convertEx_(sourceValue.asInstanceOf[SS], hint).asInstanceOf[T]
130142
}
131143

132144
@throws(classOf[ConverterException])
133-
protected def convertEx_(sourceValue: SS): TT
145+
protected def convertEx_(sourceValue: SS, hint: AnyRef = EmptyHint): TT
134146
}
135147

136-
abstract class NonStrictSourceConverterSkeleton[SS: Type, TT: Type] extends Converter {
137-
final def canConvertType[S: Type, T: Type]: Boolean = {
148+
abstract class NonStrictSourceConverterSkeleton[SS: Type, TT: Type](theHint: AnyRef = EmptyHint) extends Converter {
149+
final def canConvertType[S: Type, T: Type](hint: AnyRef = EmptyHint): Boolean = {
150+
(theHint == hint) &&
138151
SourceTargetConverter.canConvertWithNonStrictSource(typeOf[SS], typeOf[TT], typeOf[S], typeOf[T])
139152
}
140153

@@ -145,10 +158,10 @@ abstract class NonStrictSourceConverterSkeleton[SS: Type, TT: Type] extends Conv
145158
*
146159
* This is a low-level function.
147160
*/
148-
final def convertEx[T: Type](sourceValue: Any) = {
149-
convertEx_(sourceValue.asInstanceOf[SS]).asInstanceOf[T]
161+
final def convertEx[T: Type](sourceValue: Any, hint: AnyRef = EmptyHint) = {
162+
convertEx_(sourceValue.asInstanceOf[SS], hint).asInstanceOf[T]
150163
}
151164

152-
protected def convertEx_(sourceValue: SS): TT
165+
protected def convertEx_(sourceValue: SS, hint: AnyRef = EmptyHint): TT
153166

154167
}

src/main/scala/com/ckkloverdos/convert/package.scala

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ package com.ckkloverdos
1818

1919

2020
package object convert {
21+
final val EmptyHint: AnyRef = new java.lang.Object
22+
2123
type Type[A] = Manifest[A]
2224

2325
@inline

src/main/scala/com/ckkloverdos/convert/select/CachedMostSpecificTypeFirstSelection.scala

+11-11
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ import com.ckkloverdos.maybe.{NoVal, Maybe, Just}
2828
final class CachedMostSpecificTypeFirstSelection(converters: Traversable[Converter]) extends ConverterSelectionStrategy {
2929
private[this] val _lock = new ReentrantLock()
3030
private[this] val (_strictSourceConverters, _nonStrictSourceConverters) = converters.map(Just(_)).partition(_.get.isStrictSource)
31-
private[this] var _cache: Map[(Manifest[_], Manifest[_]), Just[Converter]] = Map()
31+
private[this] var _cache: Map[(Manifest[_], Manifest[_], AnyRef), Just[Converter]] = Map()
3232

3333
def isCaching = true
3434

35-
def addToCache(sm: Type[_], tm: Type[_], cv: Converter) = {
35+
def addToCache(sm: Type[_], tm: Type[_], hint: AnyRef, cv: Converter) = {
3636
lock(_lock) {
37-
_cache += ((sm, tm) -> Just(cv))
37+
_cache += ((sm, tm, hint) -> Just(cv))
3838
}
3939
}
4040

41-
override def findCached[S, T](sm: Type[S], tm: Type[T]) = {
42-
_cache.get((sm, tm)) match {
41+
override def findCached[S, T](sm: Type[S], tm: Type[T], hint: AnyRef) = {
42+
_cache.get((sm, tm, hint)) match {
4343
case Some(jcv) =>
4444
logger.debug("findCached(%s, %s) => %s".format(sm, tm, jcv))
4545
jcv.asInstanceOf[Maybe[Converter]]
@@ -49,21 +49,21 @@ final class CachedMostSpecificTypeFirstSelection(converters: Traversable[Convert
4949
}
5050
}
5151

52-
def findNonCached[S, T](sm: Type[S], tm: Type[T]): Maybe[Converter] = {
53-
_strictSourceConverters.find(_.get.canConvertType(sm, tm)) match {
52+
def findNonCached[S, T](sm: Type[S], tm: Type[T], hint: AnyRef): Maybe[Converter] = {
53+
_strictSourceConverters.find(_.get.canConvertType(sm, tm, hint)) match {
5454
case Some(jcv) =>
55-
logger.debug("findNonCached(%s, %s) => STRICT: %s".format(sm, tm, jcv))
55+
logger.debug("findNonCached(%s, %s, %s) => STRICT: %s".format(sm, tm, hint, jcv))
5656
jcv.asInstanceOf[Maybe[Converter]]
5757
case None =>
5858
_nonStrictSourceConverters foreach { case convJ =>
5959
val conv = convJ.get
6060
}
61-
_nonStrictSourceConverters.find(_.get.canConvertType(sm, tm)) match {
61+
_nonStrictSourceConverters.find(_.get.canConvertType(sm, tm, hint)) match {
6262
case Some(jcv) =>
63-
logger.debug("findNonCached(%s, %s) => NON-STRICT: %s".format(sm, tm, jcv))
63+
logger.debug("findNonCached(%s, %s, %s) => NON-STRICT: %s".format(sm, tm, hint, jcv))
6464
jcv.asInstanceOf[Maybe[Converter]]
6565
case None =>
66-
logger.debug("findNonCached(%s, %s) => %s".format(sm, tm, None))
66+
logger.debug("findNonCached(%s, %s, %s) => %s".format(sm, tm, hint, None))
6767
NoVal
6868
}
6969
}

0 commit comments

Comments
 (0)