1 /***********************************************************************
2  * Copyright (c) 2013-2024 Commonwealth Computer Research, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Apache License, Version 2.0
5  * which accompanies this distribution and is available at
6  * http://www.opensource.org/licenses/apache2.0.php.
7  ***********************************************************************/
8 
9 package org.locationtech.geomesa.utils.geotools.converters
10 
11 import com.typesafe.scalalogging.StrictLogging
12 import org.geotools.api.filter.expression.Expression
13 import org.geotools.data.util.InterpolationConverterFactory
14 import org.geotools.util.factory.GeoTools
15 import org.geotools.util.{Converter, Converters}
16 
17 import java.util.concurrent.ConcurrentHashMap
18 import scala.reflect.ClassTag
19 import scala.util.control.NonFatal
20 
21 /**
22   * Replacement for geotools `Converters`, which caches the converters for each pair of (from -> to) instead of
23   * re-creating them each time.
24   */
25 object FastConverter extends StrictLogging {
26 
27   import scala.collection.JavaConverters._
28 
29   private val factories = Converters.getConverterFactories(GeoTools.getDefaultHints).asScala.toArray.filter {
30     // exclude jai-related factories as it's not usually on the classpath
31     case _: InterpolationConverterFactory => false
32     case _ => true
33   }
34 
35   private val cache = new ConcurrentHashMap[(Class[_], Class[_]), Array[Converter]]
36 
37   /**
38     * Convert the value into the given type
39     *
40     * @param value value to convert
41     * @param binding type to convert to
42     * @tparam T type binding
43     * @return converted value, or null if it could not be converted
44     */
45   def convert[T](value: Any, binding: Class[T]): T = {
46     if (value == null) {
47       return null.asInstanceOf[T]
48     }
49 
50     val clas = value.getClass
51     if (clas == binding) {
52       return value.asInstanceOf[T]
53     }
54 
55     val converters = getConverters(clas, binding)
56 
57     var i = 0
58     while (i < converters.length) {
59       try {
60         val result = converters(i).convert(value, binding)
61         if (result != null) {
62           return result
63         }
64       } catch {
65         case NonFatal(e) =>
66           logger.trace(s"Error converting $value (of type ${value.getClass.getName}) " +
67               s"to ${binding.getName} using converter ${converters(i).getClass.getName}:", e)
68       }
69       i += 1
70     }
71 
72     val msg = s"Could not convert '$value' (of type ${value.getClass.getName}) to ${binding.getName}"
73     logger.warn(msg)
74     logger.debug(msg, new Exception())
75 
76     null.asInstanceOf[T]
77   }
78 
79 
80   /**
81    * Convert the value into one of the given type
82    *
83    * @param value value to convert
84    * @param bindings type to convert to, in order of preference
85    * @tparam T type binding
86    * @return converted value, or null if it could not be converted
87    */
88   def convertFirst[T](value: Any, bindings: Iterator[Class[_ <: T]]): T = {
89     if (value == null) {
90       return null.asInstanceOf[T]
91     }
92 
93     val clas = value.getClass
94 
95     while (bindings.hasNext) {
96       val binding = bindings.next
97       if (clas == binding) {
98         return value.asInstanceOf[T]
99       }
100 
101       val converters = getConverters(clas, binding)
102 
103       var i = 0
104       while (i < converters.length) {
105         try {
106           val result = converters(i).convert(value, binding)
107           if (result != null) {
108             return result
109           }
110         } catch {
111           case NonFatal(e) =>
112             logger.trace(s"Error converting $value (of type ${value.getClass.getName}) " +
113                 s"to ${binding.getName} using converter ${converters(i).getClass.getName}:", e)
114         }
115         i += 1
116       }
117     }
118 
119     logger.warn(
120       s"Could not convert '$value' (of type ${value.getClass.getName}) " +
121           s"to any of ${bindings.map(_.getName).mkString(", ")}")
122 
123     null.asInstanceOf[T]
124   }
125 
126   /**
127     * Convert the value into the given type, returning the default if it could not be converted or is null
128     *
129     * @param value value to convert
130     * @param default value to return if convert results in null
131     * @param ct class tag
132     * @tparam T type to convert to
133     * @return
134     */
135   def convertOrElse[T <: AnyRef](value: Any, default: => T)(implicit ct: ClassTag[T]): T = {
136     val attempt = convert(value, ct.runtimeClass.asInstanceOf[Class[T]])
137     if (attempt == null) { default } else { attempt }
138   }
139 
140   /**
141     * Evaluate and convert an expression
142     *
143     * @param expression expression to evaluate
144     * @param binding type to convert to
145     * @tparam T type binding
146     * @return converted value, or null if it could not be converted
147     */
148   def evaluate[T](expression: Expression, binding: Class[T]): T = convert(expression.evaluate(null), binding)
149 
150   /**
151    * Gets a cached converter, loading it if necessary
152    *
153    * @param from from
154    * @param to to
155    * @return
156    */
157   private def getConverters(from: Class[_], to: Class[_]): Array[Converter] = {
158     var converters = cache.get((from, to))
159 
160     if (converters == null) {
161       if (from.eq(to) || from == to || to.isAssignableFrom(from)) {
162         converters = Array(IdentityConverter)
163       } else {
164         converters = factories.flatMap(factory => Option(factory.createConverter(from, to, null)))
165         if (to == classOf[String]) {
166           converters = converters :+ ToStringConverter // add toString as a final fallback
167         }
168       }
169       cache.put((from, to), converters)
170     }
171 
172     converters
173   }
174 
175   private object IdentityConverter extends Converter {
176     override def convert[T](source: Any, target: Class[T]): T = source.asInstanceOf[T]
177   }
178 
179   private object ToStringConverter extends Converter {
180     override def convert[T](source: Any, target: Class[T]): T = source.toString.asInstanceOf[T]
181   }
182 }
Line Stmt Id Pos Tree Symbol Tests Code
29 6546 1191 - 1215 Apply org.geotools.util.factory.GeoTools.getDefaultHints org.geotools.util.factory.GeoTools.getDefaultHints()
29 6547 1158 - 1216 Apply org.geotools.util.Converters.getConverterFactories org.geotools.util.Converters.getConverterFactories(org.geotools.util.factory.GeoTools.getDefaultHints())
29 6548 1158 - 1232 ApplyToImplicitArgs scala.collection.TraversableOnce.toArray scala.collection.JavaConverters.asScalaSetConverter[org.geotools.util.ConverterFactory](org.geotools.util.Converters.getConverterFactories(org.geotools.util.factory.GeoTools.getDefaultHints())).asScala.toArray[org.geotools.util.ConverterFactory]((ClassTag.apply[org.geotools.util.ConverterFactory](classOf[org.geotools.util.ConverterFactory]): scala.reflect.ClassTag[org.geotools.util.ConverterFactory]))
29 6553 1158 - 1389 Apply scala.collection.TraversableLike.filter scala.Predef.refArrayOps[org.geotools.util.ConverterFactory](scala.collection.JavaConverters.asScalaSetConverter[org.geotools.util.ConverterFactory](org.geotools.util.Converters.getConverterFactories(org.geotools.util.factory.GeoTools.getDefaultHints())).asScala.toArray[org.geotools.util.ConverterFactory]((ClassTag.apply[org.geotools.util.ConverterFactory](classOf[org.geotools.util.ConverterFactory]): scala.reflect.ClassTag[org.geotools.util.ConverterFactory]))).filter(((x0$1: org.geotools.util.ConverterFactory) => x0$1 match { case (_: org.geotools.data.util.InterpolationConverterFactory) => false case _ => true }))
31 6549 1361 - 1366 Literal <nosymbol> false
31 6550 1361 - 1366 Block <nosymbol> false
32 6551 1381 - 1385 Literal <nosymbol> true
32 6552 1381 - 1385 Block <nosymbol> true
35 6554 1413 - 1474 Apply java.util.concurrent.ConcurrentHashMap.<init> new java.util.concurrent.ConcurrentHashMap[(Class[_], Class[_]),Array[org.geotools.util.Converter]]()
46 6555 1775 - 1788 Apply scala.Any.== value.==(null)
46 6559 1771 - 1771 Literal <nosymbol> ()
46 6560 1771 - 1771 Block <nosymbol> ()
47 6556 1805 - 1809 Literal <nosymbol> null
47 6557 1805 - 1825 TypeApply scala.Any.asInstanceOf null.asInstanceOf[T]
47 6558 1798 - 1825 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convert return null.asInstanceOf[T]
50 6561 1848 - 1862 Apply scala.Any.getClass value.getClass()
51 6562 1871 - 1886 Apply java.lang.Object.== clas.==(binding)
51 6565 1867 - 1867 Literal <nosymbol> ()
51 6566 1867 - 1867 Block <nosymbol> ()
52 6563 1903 - 1924 TypeApply scala.Any.asInstanceOf value.asInstanceOf[T]
52 6564 1896 - 1924 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convert return value.asInstanceOf[T]
55 6567 1953 - 1981 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.getConverters FastConverter.this.getConverters(clas, binding)
57 6568 1995 - 1996 Literal <nosymbol> 0
58 6569 2012 - 2029 Select scala.Array.length converters.length
58 6570 2008 - 2029 Apply scala.Int.< i.<(converters.length)
58 6579 2031 - 2031 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.while$1 while$1()
58 6580 2031 - 2421 Block <nosymbol> { { try { val result: T = converters.apply(i).convert[T](value, binding); if (result.!=(null)) return result else () } catch { case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => (if (FastConverter.this.logger.underlying.isTraceEnabled()) FastConverter.this.logger.underlying.trace(scala.StringContext.apply("Error converting ", " (of type ", ") ").s(value, value.getClass().getName()).+(scala.StringContext.apply("to ", " using converter ", ":").s(binding.getName(), converters.apply(i).getClass().getName())), e) else (): Unit) }; i = i.+(1) }; while$1() }
58 6581 2001 - 2001 Literal <nosymbol> ()
58 6582 2001 - 2001 Block <nosymbol> ()
59 6576 2053 - 2167 Block <nosymbol> { val result: T = converters.apply(i).convert[T](value, binding); if (result.!=(null)) return result else () }
60 6571 2066 - 2103 Apply org.geotools.util.Converter.convert converters.apply(i).convert[T](value, binding)
61 6572 2116 - 2130 Apply scala.Any.!= result.!=(null)
61 6574 2112 - 2112 Literal <nosymbol> ()
61 6575 2112 - 2112 Block <nosymbol> ()
62 6573 2144 - 2157 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convert return result
66 6577 2222 - 2394 Typed <nosymbol> (if (FastConverter.this.logger.underlying.isTraceEnabled()) FastConverter.this.logger.underlying.trace(scala.StringContext.apply("Error converting ", " (of type ", ") ").s(value, value.getClass().getName()).+(scala.StringContext.apply("to ", " using converter ", ":").s(binding.getName(), converters.apply(i).getClass().getName())), e) else (): Unit)
69 6578 2409 - 2415 Apply scala.Int.+ i.+(1)
72 6583 2439 - 2459 Literal <nosymbol> "Could not convert \'"
72 6584 2464 - 2476 Literal <nosymbol> "\' (of type "
72 6585 2500 - 2506 Literal <nosymbol> ") to "
72 6586 2523 - 2524 Literal <nosymbol> ""
72 6587 2477 - 2499 Apply java.lang.Class.getName value.getClass().getName()
72 6588 2507 - 2522 Apply java.lang.Class.getName binding.getName()
72 6589 2437 - 2524 Apply scala.StringContext.s scala.StringContext.apply("Could not convert \'", "\' (of type ", ") to ", "").s(value, value.getClass().getName(), binding.getName())
76 6590 2590 - 2594 Literal <nosymbol> null
76 6591 2590 - 2610 TypeApply scala.Any.asInstanceOf null.asInstanceOf[T]
89 6592 2962 - 2975 Apply scala.Any.== value.==(null)
89 6596 2958 - 2958 Literal <nosymbol> ()
89 6597 2958 - 2958 Block <nosymbol> ()
90 6593 2992 - 2996 Literal <nosymbol> null
90 6594 2992 - 3012 TypeApply scala.Any.asInstanceOf null.asInstanceOf[T]
90 6595 2985 - 3012 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convertFirst return null.asInstanceOf[T]
93 6598 3035 - 3049 Apply scala.Any.getClass value.getClass()
95 6599 3062 - 3078 Select scala.collection.Iterator.hasNext bindings.hasNext
95 6622 3080 - 3080 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.while$3 while$3()
95 6623 3080 - 3716 Block <nosymbol> { { val binding: Class[_ <: T] = bindings.next(); if (clas.==(binding)) return value.asInstanceOf[T] else (); val converters: Array[org.geotools.util.Converter] = FastConverter.this.getConverters(clas, binding); var i: Int = 0; while$2(){ if (i.<(converters.length)) { { try { val result: T = converters.apply(i).convert[_$3](value, binding); if (result.!=(null)) return result else () } catch { case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => (if (FastConverter.this.logger.underlying.isTraceEnabled()) FastConverter.this.logger.underlying.trace(scala.StringContext.apply("Error converting ", " (of type ", ") ").s(value, value.getClass().getName()).+(scala.StringContext.apply("to ", " using converter ", ":").s(binding.getName(), converters.apply(i).getClass().getName())), e) else (): Unit) }; i = i.+(1) }; while$2() } else () } }; while$3() }
95 6624 3055 - 3055 Literal <nosymbol> ()
95 6625 3055 - 3055 Block <nosymbol> ()
96 6600 3102 - 3115 Apply scala.collection.Iterator.next bindings.next()
97 6601 3126 - 3141 Apply java.lang.Object.== clas.==(binding)
97 6604 3122 - 3122 Literal <nosymbol> ()
97 6605 3122 - 3122 Block <nosymbol> ()
98 6602 3160 - 3181 TypeApply scala.Any.asInstanceOf value.asInstanceOf[T]
98 6603 3153 - 3181 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convertFirst return value.asInstanceOf[T]
101 6606 3214 - 3242 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.getConverters FastConverter.this.getConverters(clas, binding)
103 6607 3258 - 3259 Literal <nosymbol> 0
104 6608 3277 - 3294 Select scala.Array.length converters.length
104 6609 3273 - 3294 Apply scala.Int.< i.<(converters.length)
104 6618 3296 - 3296 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.while$2 while$2()
104 6619 3296 - 3710 Block <nosymbol> { { try { val result: T = converters.apply(i).convert[_$3](value, binding); if (result.!=(null)) return result else () } catch { case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => (if (FastConverter.this.logger.underlying.isTraceEnabled()) FastConverter.this.logger.underlying.trace(scala.StringContext.apply("Error converting ", " (of type ", ") ").s(value, value.getClass().getName()).+(scala.StringContext.apply("to ", " using converter ", ":").s(binding.getName(), converters.apply(i).getClass().getName())), e) else (): Unit) }; i = i.+(1) }; while$2() }
104 6620 3266 - 3266 Literal <nosymbol> ()
104 6621 3266 - 3266 Block <nosymbol> ()
105 6615 3322 - 3442 Block <nosymbol> { val result: T = converters.apply(i).convert[_$3](value, binding); if (result.!=(null)) return result else () }
106 6610 3335 - 3372 Apply org.geotools.util.Converter.convert converters.apply(i).convert[_$3](value, binding)
107 6611 3387 - 3401 Apply scala.Any.!= result.!=(null)
107 6613 3383 - 3383 Literal <nosymbol> ()
107 6614 3383 - 3383 Block <nosymbol> ()
108 6612 3417 - 3430 Return org.locationtech.geomesa.utils.geotools.converters.FastConverter.convertFirst return result
112 6616 3503 - 3677 Typed <nosymbol> (if (FastConverter.this.logger.underlying.isTraceEnabled()) FastConverter.this.logger.underlying.trace(scala.StringContext.apply("Error converting ", " (of type ", ") ").s(value, value.getClass().getName()).+(scala.StringContext.apply("to ", " using converter ", ":").s(binding.getName(), converters.apply(i).getClass().getName())), e) else (): Unit)
115 6617 3696 - 3702 Apply scala.Int.+ i.+(1)
123 6626 3881 - 3885 Literal <nosymbol> null
123 6627 3881 - 3901 TypeApply scala.Any.asInstanceOf null.asInstanceOf[T]
136 6628 4334 - 4372 TypeApply scala.Any.asInstanceOf ct.runtimeClass.asInstanceOf[Class[T]]
136 6629 4319 - 4373 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.convert FastConverter.this.convert[T](value, ct.runtimeClass.asInstanceOf[Class[T]])
137 6630 4382 - 4397 Apply java.lang.Object.== attempt.==(null)
137 6631 4401 - 4408 Ident org.locationtech.geomesa.utils.geotools.converters.FastConverter.default default
137 6632 4418 - 4425 Ident org.locationtech.geomesa.utils.geotools.converters.FastConverter.attempt attempt
148 6633 4751 - 4776 Apply org.geotools.api.filter.expression.Expression.evaluate expression.evaluate(null)
148 6634 4743 - 4786 Apply org.locationtech.geomesa.utils.geotools.converters.FastConverter.convert FastConverter.this.convert[T](expression.evaluate(null), binding)
158 6635 5023 - 5033 Apply scala.Tuple2.apply scala.Tuple2.apply[Class[_$4], Class[_$5]](from, to)
158 6636 5013 - 5034 Apply java.util.concurrent.ConcurrentHashMap.get FastConverter.this.cache.get(scala.Tuple2.apply[Class[_$4], Class[_$5]](from, to))
160 6637 5044 - 5062 Apply java.lang.Object.== converters.==(null)
160 6659 5064 - 5485 Block <nosymbol> { if (from.eq(to).||(from.==(to)).||(to.isAssignableFrom(from))) converters = scala.Array.apply[org.geotools.util.Converter](FastConverter.this.IdentityConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter])) else { converters = scala.Predef.refArrayOps[org.geotools.util.ConverterFactory](FastConverter.this.factories).flatMap[org.geotools.util.Converter, Array[org.geotools.util.Converter]](((factory: org.geotools.util.ConverterFactory) => scala.this.Option.option2Iterable[org.geotools.util.Converter](scala.Option.apply[org.geotools.util.Converter](factory.createConverter(from, to, null)))))(scala.this.Array.canBuildFrom[org.geotools.util.Converter]((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))); if (to.==(classOf[java.lang.String])) converters = scala.Predef.refArrayOps[org.geotools.util.Converter](converters).:+[org.geotools.util.Converter](FastConverter.this.ToStringConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter])) else () }; FastConverter.this.cache.put(scala.Tuple2.apply[Class[_$4], Class[_$5]](from, to), converters) }
160 6660 5040 - 5040 Literal <nosymbol> ()
160 6661 5040 - 5040 Block <nosymbol> ()
161 6638 5091 - 5101 Apply java.lang.Object.== from.==(to)
161 6639 5105 - 5130 Apply java.lang.Class.isAssignableFrom to.isAssignableFrom(from)
161 6640 5076 - 5130 Apply scala.Boolean.|| from.eq(to).||(from.==(to)).||(to.isAssignableFrom(from))
162 6641 5161 - 5178 Select org.locationtech.geomesa.utils.geotools.converters.FastConverter.IdentityConverter FastConverter.this.IdentityConverter
162 6642 5155 - 5179 ApplyToImplicitArgs scala.Array.apply scala.Array.apply[org.geotools.util.Converter](FastConverter.this.IdentityConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))
162 6643 5142 - 5179 Assign <nosymbol> converters = scala.Array.apply[org.geotools.util.Converter](FastConverter.this.IdentityConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))
163 6656 5193 - 5439 Block <nosymbol> { converters = scala.Predef.refArrayOps[org.geotools.util.ConverterFactory](FastConverter.this.factories).flatMap[org.geotools.util.Converter, Array[org.geotools.util.Converter]](((factory: org.geotools.util.ConverterFactory) => scala.this.Option.option2Iterable[org.geotools.util.Converter](scala.Option.apply[org.geotools.util.Converter](factory.createConverter(from, to, null)))))(scala.this.Array.canBuildFrom[org.geotools.util.Converter]((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))); if (to.==(classOf[java.lang.String])) converters = scala.Predef.refArrayOps[org.geotools.util.Converter](converters).:+[org.geotools.util.Converter](FastConverter.this.ToStringConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter])) else () }
164 6644 5216 - 5225 Select org.locationtech.geomesa.utils.geotools.converters.FastConverter.factories FastConverter.this.factories
164 6645 5252 - 5291 Apply org.geotools.util.ConverterFactory.createConverter factory.createConverter(from, to, null)
164 6646 5245 - 5292 Apply scala.Option.apply scala.Option.apply[org.geotools.util.Converter](factory.createConverter(from, to, null))
164 6647 5245 - 5292 ApplyImplicitView scala.Option.option2Iterable scala.this.Option.option2Iterable[org.geotools.util.Converter](scala.Option.apply[org.geotools.util.Converter](factory.createConverter(from, to, null)))
164 6648 5233 - 5233 ApplyToImplicitArgs scala.Array.canBuildFrom scala.this.Array.canBuildFrom[org.geotools.util.Converter]((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))
164 6649 5216 - 5293 ApplyToImplicitArgs scala.collection.TraversableLike.flatMap scala.Predef.refArrayOps[org.geotools.util.ConverterFactory](FastConverter.this.factories).flatMap[org.geotools.util.Converter, Array[org.geotools.util.Converter]](((factory: org.geotools.util.ConverterFactory) => scala.this.Option.option2Iterable[org.geotools.util.Converter](scala.Option.apply[org.geotools.util.Converter](factory.createConverter(from, to, null)))))(scala.this.Array.canBuildFrom[org.geotools.util.Converter]((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter])))
165 6650 5306 - 5327 Apply java.lang.Object.== to.==(classOf[java.lang.String])
165 6654 5302 - 5302 Literal <nosymbol> ()
165 6655 5302 - 5302 Block <nosymbol> ()
166 6651 5368 - 5385 Select org.locationtech.geomesa.utils.geotools.converters.FastConverter.ToStringConverter FastConverter.this.ToStringConverter
166 6652 5354 - 5385 ApplyToImplicitArgs scala.collection.mutable.ArrayOps.:+ scala.Predef.refArrayOps[org.geotools.util.Converter](converters).:+[org.geotools.util.Converter](FastConverter.this.ToStringConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))
166 6653 5341 - 5385 Assign <nosymbol> converters = scala.Predef.refArrayOps[org.geotools.util.Converter](converters).:+[org.geotools.util.Converter](FastConverter.this.ToStringConverter)((ClassTag.apply[org.geotools.util.Converter](classOf[org.geotools.util.Converter]): scala.reflect.ClassTag[org.geotools.util.Converter]))
169 6657 5456 - 5466 Apply scala.Tuple2.apply scala.Tuple2.apply[Class[_$4], Class[_$5]](from, to)
169 6658 5446 - 5479 Apply java.util.concurrent.ConcurrentHashMap.put FastConverter.this.cache.put(scala.Tuple2.apply[Class[_$4], Class[_$5]](from, to), converters)
176 6662 5626 - 5648 TypeApply scala.Any.asInstanceOf source.asInstanceOf[T]
180 6663 5773 - 5804 TypeApply scala.Any.asInstanceOf source.toString().asInstanceOf[T]