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
10 
11 import org.geotools.api.feature.`type`.AttributeDescriptor
12 import org.geotools.api.feature.simple.SimpleFeatureType
13 import org.locationtech.geomesa.utils.io.WithClose
14 
15 import java.io.{File, FileWriter, Writer}
16 
17 object GenerateRichFeatureModels {
18 
19   /**
20    * Creates implicit wrappers for any typesafe config format files found under src/main/resources
21    *
22    * @param args (0) - base directory for the maven project
23    *             (1) - package to place the implicit classes
24    */
25   def main(args: Array[String]): Unit = {
26     val basedir = args(0)
27     val packageName = args(1)
28     assert(basedir != null)
29     assert(packageName != null)
30 
31     val sfts = SimpleFeatureTypeLoader.sfts
32 
33     if (sfts.isEmpty) {
34       println("No formats found")
35     } else {
36       sfts.foreach { sft =>
37         val name = s"${safeIdentifier(sft.getTypeName)}Model"
38         val classFilePath = s"$basedir/src/main/scala/${packageName.replaceAll("\\.", "/")}/$name.scala"
39         val classFile = new File(classFilePath)
40         println(s"Writing class file $packageName.$name with feature type ${sft.getTypeName}")
41         WithClose(new FileWriter(classFile)) { fw =>
42           buildSingleClass(sft, name, packageName, fw)
43         }
44       }
45     }
46   }
47 
48   def buildSingleClass(sft: SimpleFeatureType, name: String, pkg: String, out: Writer): Unit = {
49     out.append(s"package $pkg\n\n")
50     out.append("import org.geotools.api.feature.simple.SimpleFeature\n\n")
51     out.append(s"// this class was generated by ${GenerateRichFeatureModels.getClass.getName} for feature type ${sft.getTypeName}\n")
52     out.append(s"object $name {\n\n")
53     out.append(s"  implicit class RichFeature(val sf: SimpleFeature) extends AnyVal {\n")
54     var i = 0
55     while (i < sft.getAttributeCount) {
56       val attr = AttributeMethods(sft, i)
57       out.append("\n")
58       out.append(s"    ${attr.getter}\n")
59       out.append(s"    ${attr.optionGetter}\n")
60       out.append(s"    ${attr.setter}\n")
61       i += 1
62     }
63     out.append(
64       s"""
65          |    def debug(): String = {
66          |      import scala.collection.JavaConverters._
67          |      val sb = new StringBuilder(s"$${sf.getType.getTypeName}:$${sf.getID}")
68          |      sf.getProperties.asScala.foreach(p => sb.append(s"|$${p.getName.getLocalPart}=$${p.getValue}"))
69          |      sb.toString()
70          |    }
71          |""".stripMargin)
72     out.append("  }\n}")
73   }
74 
75   private[geotools] def getAttributeBinding(descriptor: AttributeDescriptor): String = {
76     import org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors._
77 
78     def subtype(c: Class[_]): String = c match {
79       case null => "String"
80       case c => c.getCanonicalName
81     }
82 
83     val binding = descriptor.getType.getBinding.getCanonicalName
84     if (descriptor.isList) {
85       s"$binding[${subtype(descriptor.getListType())}]"
86     } else if (descriptor.isMap) {
87       val (keyType, valueType) = descriptor.getMapTypes()
88       s"$binding[${subtype(keyType)},${subtype(valueType)}]"
89     } else {
90       binding
91     }
92   }
93 
94   private def safeIdentifier(name: String): String = {
95     val safe = new StringBuilder()
96     var i = 0
97     var upper = true // camel case
98     while (i < name.length) {
99       val char = name.charAt(i)
100       if (char == '_'||
101           (i == 0 && !Character.isJavaIdentifierStart(char)) ||
102           (i != 0 && !Character.isJavaIdentifierPart(char))) {
103         upper = true
104       } else if (upper) {
105         safe.append(char.toUpper)
106         upper = false
107       } else {
108         safe.append(char)
109       }
110       i += 1
111     }
112     if (safe.isEmpty) {
113       throw new IllegalArgumentException(s"Can't create valid Java identifier from $name")
114     }
115     safe.toString
116   }
117 
118   private class AttributeMethods(name: String, index: Int, clazz: String) {
119     def getter: String = s"def get$name: $clazz = sf.getAttribute($index).asInstanceOf[$clazz]"
120     def optionGetter: String = s"def opt$name: Option[$clazz] = Option(get$name)"
121     def setter: String = s"def set$name(x: $clazz): Unit = sf.setAttribute($index, x)"
122   }
123 
124   private object AttributeMethods {
125     def apply(sft: SimpleFeatureType, i: Int): AttributeMethods = {
126       val descriptor = sft.getDescriptor(i)
127       val binding = getAttributeBinding(descriptor)
128       new AttributeMethods(safeIdentifier(descriptor.getLocalName), i, binding)
129     }
130   }
131 }
Line Stmt Id Pos Tree Symbol Tests Code
26 6464 1058 - 1065 Apply scala.Array.apply args.apply(0)
27 6465 1088 - 1095 Apply scala.Array.apply args.apply(1)
28 6466 1107 - 1122 Apply java.lang.Object.!= basedir.!=(null)
28 6467 1100 - 1123 Apply scala.Predef.assert scala.Predef.assert(basedir.!=(null))
29 6468 1135 - 1154 Apply java.lang.Object.!= packageName.!=(null)
29 6469 1128 - 1155 Apply scala.Predef.assert scala.Predef.assert(packageName.!=(null))
31 6470 1172 - 1200 Select org.locationtech.geomesa.utils.geotools.SimpleFeatureTypeLoader.sfts SimpleFeatureTypeLoader.sfts
33 6471 1210 - 1222 Select scala.collection.SeqLike.isEmpty sfts.isEmpty
34 6472 1232 - 1259 Apply scala.Predef.println scala.Predef.println("No formats found")
34 6473 1232 - 1259 Block scala.Predef.println scala.Predef.println("No formats found")
36 6497 1279 - 1736 Apply scala.collection.immutable.List.foreach sfts.foreach[Unit](((sft: org.geotools.api.feature.simple.SimpleFeatureType) => { val name: String = scala.StringContext.apply("", "Model").s(GenerateRichFeatureModels.this.safeIdentifier(sft.getTypeName())); val classFilePath: String = scala.StringContext.apply("", "/src/main/scala/", "/", ".scala").s(basedir, packageName.replaceAll("\\.", "/"), name); val classFile: java.io.File = new java.io.File(classFilePath); scala.Predef.println(scala.StringContext.apply("Writing class file ", ".", " with feature type ", "").s(packageName, name, sft.getTypeName())); org.locationtech.geomesa.utils.io.`package`.WithClose.apply[java.io.FileWriter, Unit](new java.io.FileWriter(classFile))(((fw: java.io.FileWriter) => GenerateRichFeatureModels.this.buildSingleClass(sft, name, packageName, fw)))(io.this.IsCloseable.closeableIsCloseable) }))
36 6498 1279 - 1736 Block scala.collection.immutable.List.foreach sfts.foreach[Unit](((sft: org.geotools.api.feature.simple.SimpleFeatureType) => { val name: String = scala.StringContext.apply("", "Model").s(GenerateRichFeatureModels.this.safeIdentifier(sft.getTypeName())); val classFilePath: String = scala.StringContext.apply("", "/src/main/scala/", "/", ".scala").s(basedir, packageName.replaceAll("\\.", "/"), name); val classFile: java.io.File = new java.io.File(classFilePath); scala.Predef.println(scala.StringContext.apply("Writing class file ", ".", " with feature type ", "").s(packageName, name, sft.getTypeName())); org.locationtech.geomesa.utils.io.`package`.WithClose.apply[java.io.FileWriter, Unit](new java.io.FileWriter(classFile))(((fw: java.io.FileWriter) => GenerateRichFeatureModels.this.buildSingleClass(sft, name, packageName, fw)))(io.this.IsCloseable.closeableIsCloseable) }))
37 6474 1322 - 1323 Literal <nosymbol> ""
37 6475 1356 - 1362 Literal <nosymbol> "Model"
37 6476 1339 - 1354 Apply org.geotools.api.feature.simple.SimpleFeatureType.getTypeName sft.getTypeName()
37 6477 1324 - 1355 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.safeIdentifier GenerateRichFeatureModels.this.safeIdentifier(sft.getTypeName())
37 6478 1320 - 1362 Apply scala.StringContext.s scala.StringContext.apply("", "Model").s(GenerateRichFeatureModels.this.safeIdentifier(sft.getTypeName()))
38 6479 1393 - 1394 Literal <nosymbol> ""
38 6480 1401 - 1418 Literal <nosymbol> "/src/main/scala/"
38 6481 1454 - 1456 Literal <nosymbol> "/"
38 6482 1460 - 1467 Literal <nosymbol> ".scala"
38 6483 1419 - 1453 Apply java.lang.String.replaceAll packageName.replaceAll("\\.", "/")
38 6484 1391 - 1467 Apply scala.StringContext.s scala.StringContext.apply("", "/src/main/scala/", "/", ".scala").s(basedir, packageName.replaceAll("\\.", "/"), name)
39 6485 1492 - 1515 Apply java.io.File.<init> new java.io.File(classFilePath)
40 6486 1534 - 1554 Literal <nosymbol> "Writing class file "
40 6487 1565 - 1567 Literal <nosymbol> "."
40 6488 1571 - 1591 Literal <nosymbol> " with feature type "
40 6489 1608 - 1609 Literal <nosymbol> ""
40 6490 1592 - 1607 Apply org.geotools.api.feature.simple.SimpleFeatureType.getTypeName sft.getTypeName()
40 6491 1532 - 1609 Apply scala.StringContext.s scala.StringContext.apply("Writing class file ", ".", " with feature type ", "").s(packageName, name, sft.getTypeName())
40 6492 1524 - 1610 Apply scala.Predef.println scala.Predef.println(scala.StringContext.apply("Writing class file ", ".", " with feature type ", "").s(packageName, name, sft.getTypeName()))
41 6493 1629 - 1654 Apply java.io.FileWriter.<init> new java.io.FileWriter(classFile)
41 6495 1656 - 1656 Select org.locationtech.geomesa.utils.io.IsCloseableImplicits.closeableIsCloseable io.this.IsCloseable.closeableIsCloseable
41 6496 1619 - 1728 ApplyToImplicitArgs org.locationtech.geomesa.utils.io.WithClose.apply org.locationtech.geomesa.utils.io.`package`.WithClose.apply[java.io.FileWriter, Unit](new java.io.FileWriter(classFile))(((fw: java.io.FileWriter) => GenerateRichFeatureModels.this.buildSingleClass(sft, name, packageName, fw)))(io.this.IsCloseable.closeableIsCloseable)
42 6494 1674 - 1718 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.buildSingleClass GenerateRichFeatureModels.this.buildSingleClass(sft, name, packageName, fw)
49 6499 1860 - 1879 Apply scala.StringContext.s scala.StringContext.apply("package ", "\\n\\n").s(pkg)
49 6500 1849 - 1880 Apply java.io.Writer.append out.append(scala.StringContext.apply("package ", "\\n\\n").s(pkg))
50 6501 1885 - 1955 Apply java.io.Writer.append out.append("import org.geotools.api.feature.simple.SimpleFeature\n\n")
51 6502 1973 - 2005 Literal <nosymbol> "// this class was generated by "
51 6503 2049 - 2068 Literal <nosymbol> " for feature type "
51 6504 2085 - 2088 Literal <nosymbol> "\\n"
51 6505 2006 - 2048 Apply java.lang.Class.getName GenerateRichFeatureModels.getClass().getName()
51 6506 2069 - 2084 Apply org.geotools.api.feature.simple.SimpleFeatureType.getTypeName sft.getTypeName()
51 6507 1971 - 2088 Apply scala.StringContext.s scala.StringContext.apply("// this class was generated by ", " for feature type ", "\\n").s(GenerateRichFeatureModels.getClass().getName(), sft.getTypeName())
51 6508 1960 - 2089 Apply java.io.Writer.append out.append(scala.StringContext.apply("// this class was generated by ", " for feature type ", "\\n").s(GenerateRichFeatureModels.getClass().getName(), sft.getTypeName()))
52 6509 2105 - 2126 Apply scala.StringContext.s scala.StringContext.apply("object ", " {\\n\\n").s(name)
52 6510 2094 - 2127 Apply java.io.Writer.append out.append(scala.StringContext.apply("object ", " {\\n\\n").s(name))
53 6511 2143 - 2216 Apply scala.StringContext.s scala.StringContext.apply(" implicit class RichFeature(val sf: SimpleFeature) extends AnyVal {\\n").s()
53 6512 2132 - 2217 Apply java.io.Writer.append out.append(scala.StringContext.apply(" implicit class RichFeature(val sf: SimpleFeature) extends AnyVal {\\n").s())
54 6513 2230 - 2231 Literal <nosymbol> 0
55 6514 2247 - 2268 Apply org.geotools.api.feature.simple.SimpleFeatureType.getAttributeCount sft.getAttributeCount()
55 6515 2243 - 2268 Apply scala.Int.< i.<(sft.getAttributeCount())
55 6534 2270 - 2270 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.while$1 while$1()
55 6535 2270 - 2487 Block <nosymbol> { { val attr: org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods = GenerateRichFeatureModels.this.AttributeMethods.apply(sft, i); out.append("\n"); out.append(scala.StringContext.apply(" ", "\\n").s(attr.getter)); out.append(scala.StringContext.apply(" ", "\\n").s(attr.optionGetter)); out.append(scala.StringContext.apply(" ", "\\n").s(attr.setter)); i = i.+(1) }; while$1() }
55 6536 2236 - 2236 Literal <nosymbol> ()
55 6537 2236 - 2236 Block <nosymbol> ()
56 6516 2289 - 2313 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.apply GenerateRichFeatureModels.this.AttributeMethods.apply(sft, i)
57 6517 2320 - 2336 Apply java.io.Writer.append out.append("\n")
58 6518 2356 - 2361 Literal <nosymbol> " "
58 6519 2374 - 2377 Literal <nosymbol> "\\n"
58 6520 2362 - 2373 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.getter attr.getter
58 6521 2354 - 2377 Apply scala.StringContext.s scala.StringContext.apply(" ", "\\n").s(attr.getter)
58 6522 2343 - 2378 Apply java.io.Writer.append out.append(scala.StringContext.apply(" ", "\\n").s(attr.getter))
59 6523 2398 - 2403 Literal <nosymbol> " "
59 6524 2422 - 2425 Literal <nosymbol> "\\n"
59 6525 2404 - 2421 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.optionGetter attr.optionGetter
59 6526 2396 - 2425 Apply scala.StringContext.s scala.StringContext.apply(" ", "\\n").s(attr.optionGetter)
59 6527 2385 - 2426 Apply java.io.Writer.append out.append(scala.StringContext.apply(" ", "\\n").s(attr.optionGetter))
60 6528 2446 - 2451 Literal <nosymbol> " "
60 6529 2464 - 2467 Literal <nosymbol> "\\n"
60 6530 2452 - 2463 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.setter attr.setter
60 6531 2444 - 2467 Apply scala.StringContext.s scala.StringContext.apply(" ", "\\n").s(attr.setter)
60 6532 2433 - 2468 Apply java.io.Writer.append out.append(scala.StringContext.apply(" ", "\\n").s(attr.setter))
61 6533 2475 - 2481 Apply scala.Int.+ i.+(1)
63 6540 2492 - 2881 Apply java.io.Writer.append out.append(scala.Predef.augmentString(scala.StringContext.apply("\n | def debug(): String = {\n | import scala.collection.JavaConverters._\n | val sb = new StringBuilder(s\"${sf.getType.getTypeName}:${sf.getID}\")\n | sf.getProperties.asScala.foreach(p => sb.append(s\"|${p.getName.getLocalPart}=${p.getValue}\"))\n | sb.toString()\n | }\n |").s()).stripMargin)
64 6538 2510 - 2868 Apply scala.StringContext.s scala.StringContext.apply("\n | def debug(): String = {\n | import scala.collection.JavaConverters._\n | val sb = new StringBuilder(s\"${sf.getType.getTypeName}:${sf.getID}\")\n | sf.getProperties.asScala.foreach(p => sb.append(s\"|${p.getName.getLocalPart}=${p.getValue}\"))\n | sb.toString()\n | }\n |").s()
71 6539 2510 - 2880 Select scala.collection.immutable.StringLike.stripMargin scala.Predef.augmentString(scala.StringContext.apply("\n | def debug(): String = {\n | import scala.collection.JavaConverters._\n | val sb = new StringBuilder(s\"${sf.getType.getTypeName}:${sf.getID}\")\n | sf.getProperties.asScala.foreach(p => sb.append(s\"|${p.getName.getLocalPart}=${p.getValue}\"))\n | sb.toString()\n | }\n |").s()).stripMargin
72 6541 2886 - 2906 Apply java.io.Writer.append out.append(" }\n}")
72 6542 2896 - 2896 Literal <nosymbol> ()
79 6543 3148 - 3156 Literal <nosymbol> "String"
79 6544 3148 - 3156 Block <nosymbol> "String"
80 6545 3173 - 3191 Apply java.lang.Class.getCanonicalName c.getCanonicalName()
80 6546 3173 - 3191 Block java.lang.Class.getCanonicalName c.getCanonicalName()
83 6547 3217 - 3263 Apply java.lang.Class.getCanonicalName descriptor.getType().getBinding().getCanonicalName()
84 6548 3272 - 3289 Select org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor.isList org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).isList
85 6549 3301 - 3302 Literal <nosymbol> ""
85 6550 3309 - 3311 Literal <nosymbol> "["
85 6551 3346 - 3348 Literal <nosymbol> "]"
85 6552 3320 - 3344 Apply org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor.getListType org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getListType()
85 6553 3312 - 3345 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.subtype subtype(org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getListType())
85 6554 3299 - 3348 Apply scala.StringContext.s scala.StringContext.apply("", "[", "]").s(binding, subtype(org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getListType()))
85 6555 3299 - 3348 Block scala.StringContext.s scala.StringContext.apply("", "[", "]").s(binding, subtype(org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getListType()))
86 6556 3364 - 3380 Select org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor.isMap org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).isMap
86 6566 3382 - 3508 Block <nosymbol> { <synthetic> <artifact> private[this] val x$1: (Class[_$5], Class[_$6]) forSome { type _$5; type _$6 } = (org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getMapTypes(): (Class[_], Class[_]) @unchecked) match { case (_1: Class[_], _2: Class[_])(Class[_], Class[_])((keyType @ _), (valueType @ _)) => scala.Tuple2.apply[Class[_$5], Class[_$6]](keyType, valueType) }; val keyType: Class[_] = x$1._1; val valueType: Class[_] = x$1._2; scala.StringContext.apply("", "[", ",", "]").s(binding, subtype(keyType), subtype(valueType)) }
86 6568 3360 - 3535 If <nosymbol> if (org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).isMap) { <synthetic> <artifact> private[this] val x$1: (Class[_$5], Class[_$6]) forSome { type _$5; type _$6 } = (org.locationtech.geomesa.utils.geotools.RichAttributeDescriptors.RichAttributeDescriptor(descriptor).getMapTypes(): (Class[_], Class[_]) @unchecked) match { case (_1: Class[_], _2: Class[_])(Class[_], Class[_])((keyType @ _), (valueType @ _)) => scala.Tuple2.apply[Class[_$5], Class[_$6]](keyType, valueType) }; val keyType: Class[_] = x$1._1; val valueType: Class[_] = x$1._2; scala.StringContext.apply("", "[", ",", "]").s(binding, subtype(keyType), subtype(valueType)) } else binding
87 6557 3395 - 3395 Select scala.Tuple2._1 x$1._1
87 6558 3404 - 3404 Select scala.Tuple2._2 x$1._2
88 6559 3450 - 3451 Literal <nosymbol> ""
88 6560 3458 - 3460 Literal <nosymbol> "["
88 6561 3478 - 3480 Literal <nosymbol> ","
88 6562 3500 - 3502 Literal <nosymbol> "]"
88 6563 3461 - 3477 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.subtype subtype(keyType)
88 6564 3481 - 3499 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.subtype subtype(valueType)
88 6565 3448 - 3502 Apply scala.StringContext.s scala.StringContext.apply("", "[", ",", "]").s(binding, subtype(keyType), subtype(valueType))
90 6567 3522 - 3529 Ident org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.binding binding
95 6569 3611 - 3630 Apply scala.collection.mutable.StringBuilder.<init> new scala.`package`.StringBuilder()
96 6570 3643 - 3644 Literal <nosymbol> 0
97 6571 3661 - 3665 Literal <nosymbol> true
98 6572 3695 - 3706 Apply java.lang.String.length name.length()
98 6573 3691 - 3706 Apply scala.Int.< i.<(name.length())
98 6593 3708 - 3708 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.while$2 while$2()
98 6594 3708 - 4063 Block <nosymbol> { { val char: Char = name.charAt(i); if (char.==('_').||(i.==(0).&&(java.lang.Character.isJavaIdentifierStart(char).unary_!)).||(i.!=(0).&&(java.lang.Character.isJavaIdentifierPart(char).unary_!))) upper = true else if (upper) { safe.append(scala.Predef.charWrapper(char).toUpper); upper = false } else safe.append(char); i = i.+(1) }; while$2() }
98 6595 3684 - 3684 Literal <nosymbol> ()
98 6596 3684 - 3684 Block <nosymbol> ()
99 6574 3727 - 3741 Apply java.lang.String.charAt name.charAt(i)
100 6575 3760 - 3763 Literal <nosymbol> '_'
101 6576 3782 - 3783 Literal <nosymbol> 0
101 6577 3787 - 3825 Select scala.Boolean.unary_! java.lang.Character.isJavaIdentifierStart(char).unary_!
101 6578 3777 - 3825 Apply scala.Boolean.&& i.==(0).&&(java.lang.Character.isJavaIdentifierStart(char).unary_!)
101 6582 3752 - 3889 Apply scala.Boolean.|| char.==('_').||(i.==(0).&&(java.lang.Character.isJavaIdentifierStart(char).unary_!)).||(i.!=(0).&&(java.lang.Character.isJavaIdentifierPart(char).unary_!))
102 6579 3846 - 3847 Literal <nosymbol> 0
102 6580 3851 - 3888 Select scala.Boolean.unary_! java.lang.Character.isJavaIdentifierPart(char).unary_!
102 6581 3841 - 3888 Apply scala.Boolean.&& i.!=(0).&&(java.lang.Character.isJavaIdentifierPart(char).unary_!)
103 6583 3909 - 3913 Literal <nosymbol> true
103 6584 3901 - 3913 Assign <nosymbol> upper = true
104 6588 3938 - 4003 Block <nosymbol> { safe.append(scala.Predef.charWrapper(char).toUpper); upper = false }
104 6591 3927 - 4044 If <nosymbol> if (upper) { safe.append(scala.Predef.charWrapper(char).toUpper); upper = false } else safe.append(char)
105 6585 3960 - 3972 Select scala.runtime.RichChar.toUpper scala.Predef.charWrapper(char).toUpper
105 6586 3948 - 3973 Apply scala.collection.mutable.StringBuilder.append safe.append(scala.Predef.charWrapper(char).toUpper)
106 6587 3990 - 3995 Literal <nosymbol> false
108 6589 4019 - 4036 Apply scala.collection.mutable.StringBuilder.append safe.append(char)
108 6590 4019 - 4036 Block scala.collection.mutable.StringBuilder.append safe.append(char)
110 6592 4051 - 4057 Apply scala.Int.+ i.+(1)
112 6597 4072 - 4084 Select scala.collection.mutable.StringBuilder.isEmpty safe.isEmpty
112 6600 4068 - 4068 Literal <nosymbol> ()
112 6601 4068 - 4068 Block <nosymbol> ()
113 6598 4094 - 4178 Throw <nosymbol> throw new scala.`package`.IllegalArgumentException(scala.StringContext.apply("Can\'t create valid Java identifier from ", "").s(name))
113 6599 4094 - 4178 Block <nosymbol> throw new scala.`package`.IllegalArgumentException(scala.StringContext.apply("Can\'t create valid Java identifier from ", "").s(name))
115 6602 4189 - 4202 Apply scala.collection.mutable.StringBuilder.toString safe.toString()
119 6603 4311 - 4319 Literal <nosymbol> "def get"
119 6604 4323 - 4326 Literal <nosymbol> ": "
119 6605 4331 - 4351 Literal <nosymbol> " = sf.getAttribute("
119 6606 4356 - 4372 Literal <nosymbol> ").asInstanceOf["
119 6607 4377 - 4379 Literal <nosymbol> "]"
119 6608 4319 - 4323 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.name AttributeMethods.this.name
119 6609 4326 - 4331 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.clazz AttributeMethods.this.clazz
119 6610 4351 - 4356 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.index AttributeMethods.this.index
119 6611 4372 - 4377 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.clazz AttributeMethods.this.clazz
119 6612 4309 - 4379 Apply scala.StringContext.s scala.StringContext.apply("def get", ": ", " = sf.getAttribute(", ").asInstanceOf[", "]").s(AttributeMethods.this.name, AttributeMethods.this.clazz, AttributeMethods.this.index, AttributeMethods.this.clazz)
120 6613 4413 - 4421 Literal <nosymbol> "def opt"
120 6614 4425 - 4435 Literal <nosymbol> ": Option["
120 6615 4440 - 4455 Literal <nosymbol> "] = Option(get"
120 6616 4459 - 4461 Literal <nosymbol> ")"
120 6617 4421 - 4425 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.name AttributeMethods.this.name
120 6618 4435 - 4440 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.clazz AttributeMethods.this.clazz
120 6619 4455 - 4459 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.name AttributeMethods.this.name
120 6620 4411 - 4461 Apply scala.StringContext.s scala.StringContext.apply("def opt", ": Option[", "] = Option(get", ")").s(AttributeMethods.this.name, AttributeMethods.this.clazz, AttributeMethods.this.name)
121 6621 4489 - 4497 Literal <nosymbol> "def set"
121 6622 4501 - 4506 Literal <nosymbol> "(x: "
121 6623 4511 - 4538 Literal <nosymbol> "): Unit = sf.setAttribute("
121 6624 4543 - 4548 Literal <nosymbol> ", x)"
121 6625 4497 - 4501 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.name AttributeMethods.this.name
121 6626 4506 - 4511 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.clazz AttributeMethods.this.clazz
121 6627 4538 - 4543 Select org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.index AttributeMethods.this.index
121 6628 4487 - 4548 Apply scala.StringContext.s scala.StringContext.apply("def set", "(x: ", "): Unit = sf.setAttribute(", ", x)").s(AttributeMethods.this.name, AttributeMethods.this.clazz, AttributeMethods.this.index)
126 6629 4681 - 4701 Apply org.geotools.api.feature.simple.SimpleFeatureType.getDescriptor sft.getDescriptor(i)
127 6630 4722 - 4753 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.getAttributeBinding GenerateRichFeatureModels.this.getAttributeBinding(descriptor)
128 6631 4796 - 4819 Apply org.geotools.api.feature.type.AttributeDescriptor.getLocalName descriptor.getLocalName()
128 6632 4781 - 4820 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.safeIdentifier GenerateRichFeatureModels.this.safeIdentifier(descriptor.getLocalName())
128 6633 4760 - 4833 Apply org.locationtech.geomesa.utils.geotools.GenerateRichFeatureModels.AttributeMethods.<init> new GenerateRichFeatureModels.this.AttributeMethods(GenerateRichFeatureModels.this.safeIdentifier(descriptor.getLocalName()), i, binding)