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.stats
10 
11 import org.geotools.api.feature.simple.{SimpleFeature, SimpleFeatureType}
12 
13 import scala.collection.immutable.ListMap
14 import scala.reflect.ClassTag
15 
16 /**
17   * An enumeration is merely a HashMap mapping values to number of occurrences
18   *
19   * @param sft simple feature type
20   * @param property property name the enumeration is being made for
21   * @tparam T some type T (which is restricted by the stat parser upstream of Histogram instantiation)
22   */
23 class EnumerationStat[T](val sft: SimpleFeatureType, val property: String)(implicit val ct: ClassTag[T]) extends Stat {
24 
25   override type S = EnumerationStat[T]
26 
27   private val i = sft.indexOf(property)
28   private [stats] val enumeration = scala.collection.mutable.HashMap.empty[T, Long].withDefaultValue(0)
29 
30   def size: Int = enumeration.size
31   def values: Iterable[T] = enumeration.keys
32   def frequency(value: T): Long = enumeration(value)
33   def frequencies: Iterable[(T, Long)] = enumeration
34 
35   override def observe(sf: SimpleFeature): Unit = {
36     val value = sf.getAttribute(i).asInstanceOf[T]
37     if (value != null) {
38       enumeration(value) += 1
39     }
40   }
41 
42   override def unobserve(sf: SimpleFeature): Unit = {
43     val value = sf.getAttribute(i).asInstanceOf[T]
44     if (value != null) {
45       val current = enumeration(value)
46       if (current == 1) {
47         enumeration.remove(value)
48       } else {
49         enumeration(value) = current - 1
50       }
51     }
52   }
53 
54   override def +(other: EnumerationStat[T]): EnumerationStat[T] = {
55     val plus = new EnumerationStat[T](sft, property)
56     plus += this
57     plus += other
58     plus
59   }
60 
61   override def +=(other: EnumerationStat[T]): Unit =
62     other.enumeration.foreach { case (key, count) => enumeration(key) += count }
63 
64   override def toJsonObject: Map[T, Long] =
65     if (enumeration.isEmpty) { Map.empty } else { ListMap(enumeration.toSeq.sortBy(_.toString):_*) }
66 
67   override def isEmpty: Boolean = enumeration.isEmpty
68 
69   override def clear(): Unit = enumeration.clear()
70 
71   override def isEquivalent(other: Stat): Boolean = other match {
72     case that: EnumerationStat[_] => property == that.property && enumeration == that.enumeration
73     case _ => false
74   }
75 }
Line Stmt Id Pos Tree Symbol Tests Code
27 13042 1148 - 1156 Select org.locationtech.geomesa.utils.stats.EnumerationStat.property EnumerationStat.this.property
27 13043 1136 - 1157 Apply org.geotools.api.feature.simple.SimpleFeatureType.indexOf EnumerationStat.this.sft.indexOf(EnumerationStat.this.property)
28 13044 1194 - 1261 Apply scala.collection.mutable.Map.withDefaultValue scala.collection.mutable.HashMap.empty[T, Long].withDefaultValue(0L)
30 13045 1281 - 1297 Select scala.collection.TraversableOnce.size EnumerationStat.this.enumeration.size
31 13046 1326 - 1342 Select scala.collection.MapLike.keys EnumerationStat.this.enumeration.keys
32 13047 1377 - 1395 Apply scala.collection.MapLike.apply EnumerationStat.this.enumeration.apply(value)
33 13048 1437 - 1448 Select org.locationtech.geomesa.utils.stats.EnumerationStat.enumeration EnumerationStat.this.enumeration
36 13049 1534 - 1535 Select org.locationtech.geomesa.utils.stats.EnumerationStat.i EnumerationStat.this.i
36 13050 1518 - 1552 TypeApply scala.Any.asInstanceOf sf.getAttribute(EnumerationStat.this.i).asInstanceOf[T]
37 13051 1561 - 1574 Apply scala.Any.!= value.!=(null)
37 13055 1557 - 1557 Literal <nosymbol> ()
37 13056 1557 - 1557 Block <nosymbol> ()
38 13052 1584 - 1607 Apply scala.Long.+ EnumerationStat.this.enumeration.apply(value).+(1)
38 13053 1584 - 1607 Apply scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(value, EnumerationStat.this.enumeration.apply(value).+(1))
38 13054 1584 - 1607 Block scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(value, EnumerationStat.this.enumeration.apply(value).+(1))
43 13057 1705 - 1706 Select org.locationtech.geomesa.utils.stats.EnumerationStat.i EnumerationStat.this.i
43 13058 1689 - 1723 TypeApply scala.Any.asInstanceOf sf.getAttribute(EnumerationStat.this.i).asInstanceOf[T]
44 13059 1732 - 1745 Apply scala.Any.!= value.!=(null)
44 13068 1747 - 1917 Block <nosymbol> { val current: Long = EnumerationStat.this.enumeration.apply(value); if (current.==(1)) { EnumerationStat.this.enumeration.remove(value); () } else EnumerationStat.this.enumeration.update(value, current.-(1)) }
44 13069 1728 - 1728 Literal <nosymbol> ()
44 13070 1728 - 1728 Block <nosymbol> ()
45 13060 1769 - 1787 Apply scala.collection.MapLike.apply EnumerationStat.this.enumeration.apply(value)
46 13061 1798 - 1810 Apply scala.Long.== current.==(1)
47 13062 1822 - 1847 Apply scala.collection.mutable.MapLike.remove EnumerationStat.this.enumeration.remove(value)
47 13063 1840 - 1840 Literal <nosymbol> ()
47 13064 1822 - 1847 Block <nosymbol> { EnumerationStat.this.enumeration.remove(value); () }
49 13065 1892 - 1903 Apply scala.Long.- current.-(1)
49 13066 1871 - 1903 Apply scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(value, current.-(1))
49 13067 1871 - 1903 Block scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(value, current.-(1))
55 13071 2029 - 2032 Select org.locationtech.geomesa.utils.stats.EnumerationStat.sft EnumerationStat.this.sft
55 13072 2034 - 2042 Select org.locationtech.geomesa.utils.stats.EnumerationStat.property EnumerationStat.this.property
55 13073 2006 - 2006 Select org.locationtech.geomesa.utils.stats.EnumerationStat.ct EnumerationStat.this.ct
55 13074 2006 - 2043 ApplyToImplicitArgs org.locationtech.geomesa.utils.stats.EnumerationStat.<init> new org.locationtech.geomesa.utils.stats.EnumerationStat[T](EnumerationStat.this.sft, EnumerationStat.this.property)(EnumerationStat.this.ct)
56 13075 2048 - 2060 Apply org.locationtech.geomesa.utils.stats.EnumerationStat.+= plus.+=(this)
57 13076 2065 - 2078 Apply org.locationtech.geomesa.utils.stats.EnumerationStat.+= plus.+=(other)
62 13077 2199 - 2224 Apply scala.Long.+ EnumerationStat.this.enumeration.apply(key).+(count)
62 13078 2199 - 2224 Apply scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(key, EnumerationStat.this.enumeration.apply(key).+(count))
62 13079 2199 - 2224 Block scala.collection.mutable.MapLike.update EnumerationStat.this.enumeration.update(key, EnumerationStat.this.enumeration.apply(key).+(count))
62 13080 2150 - 2226 Apply scala.collection.IterableLike.foreach other.enumeration.foreach[Unit](((x0$1: (T, Long)) => x0$1 match { case (_1: T, _2: Long)(T, Long)((key @ _), (count @ _)) => EnumerationStat.this.enumeration.update(key, EnumerationStat.this.enumeration.apply(key).+(count)) }))
65 13081 2280 - 2299 Select scala.collection.MapLike.isEmpty EnumerationStat.this.enumeration.isEmpty
65 13082 2303 - 2312 TypeApply scala.collection.immutable.Map.empty scala.Predef.Map.empty[T, Nothing]
65 13083 2303 - 2312 Block scala.collection.immutable.Map.empty scala.Predef.Map.empty[T, Nothing]
65 13084 2355 - 2365 Apply scala.Tuple2.toString x$1.toString()
65 13085 2354 - 2354 Select scala.math.Ordering.String math.this.Ordering.String
65 13086 2330 - 2366 ApplyToImplicitArgs scala.collection.SeqLike.sortBy EnumerationStat.this.enumeration.toSeq.sortBy[String](((x$1: (T, Long)) => x$1.toString()))(math.this.Ordering.String)
65 13087 2322 - 2370 Apply scala.collection.generic.GenMapFactory.apply scala.collection.immutable.ListMap.apply[T, Long]((EnumerationStat.this.enumeration.toSeq.sortBy[String](((x$1: (T, Long)) => x$1.toString()))(math.this.Ordering.String): _*))
65 13088 2322 - 2370 Block scala.collection.generic.GenMapFactory.apply scala.collection.immutable.ListMap.apply[T, Long]((EnumerationStat.this.enumeration.toSeq.sortBy[String](((x$1: (T, Long)) => x$1.toString()))(math.this.Ordering.String): _*))
67 13089 2408 - 2427 Select scala.collection.MapLike.isEmpty EnumerationStat.this.enumeration.isEmpty
69 13090 2460 - 2479 Apply scala.collection.mutable.MapLike.clear EnumerationStat.this.enumeration.clear()
72 13091 2596 - 2609 Select org.locationtech.geomesa.utils.stats.EnumerationStat.property that.property
72 13092 2628 - 2644 Select org.locationtech.geomesa.utils.stats.EnumerationStat.enumeration that.enumeration
72 13093 2613 - 2644 Apply java.lang.Object.== EnumerationStat.this.enumeration.==(that.enumeration)
72 13094 2584 - 2644 Apply scala.Boolean.&& EnumerationStat.this.property.==(that.property).&&(EnumerationStat.this.enumeration.==(that.enumeration))
72 13095 2584 - 2644 Block scala.Boolean.&& EnumerationStat.this.property.==(that.property).&&(EnumerationStat.this.enumeration.==(that.enumeration))
73 13096 2659 - 2664 Literal <nosymbol> false
73 13097 2659 - 2664 Block <nosymbol> false