Skip to content

Commit 6cd40d0

Browse files
committed
expose grouping strat as param
1 parent 9ca1523 commit 6cd40d0

File tree

5 files changed

+34
-32
lines changed

5 files changed

+34
-32
lines changed

core/src/main/kotlin/com/fractalwrench/json2kotlin/ClassTypeHolder.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import com.squareup.kotlinpoet.*
44
import java.util.*
55

66

7-
internal class ClassTypeHolder(val delegate: SourceBuildDelegate) { // TODO rename, bad ontology
7+
internal class ClassTypeHolder(val delegate: SourceBuildDelegate, groupingStrategy: GroupingStrategy) { // TODO rename, bad ontology
88

99
internal val stack = Stack<TypeSpec>()
1010
private val jsonProcessor = JsonProcessor()
11-
private val jsonFieldGrouper = JsonFieldGrouper()
11+
private val jsonFieldGrouper = JsonFieldGrouper(groupingStrategy)
1212

1313

1414
/**
@@ -23,22 +23,22 @@ internal class ClassTypeHolder(val delegate: SourceBuildDelegate) { // TODO rena
2323
val pop = bfsStack.pop()
2424

2525
if (level != -1 && pop.level != level) {
26-
handleLevel(level, levelQueue)
26+
handleLevel(levelQueue)
2727
}
2828
levelQueue.add(pop)
2929
level = pop.level
3030
}
31-
handleLevel(level, levelQueue)
31+
handleLevel(levelQueue)
3232
}
33-
private fun handleLevel(level: Int, levelQueue: LinkedList<TypedJsonElement>) {
33+
private fun handleLevel(levelQueue: LinkedList<TypedJsonElement>) {
3434
processTreeLevel(levelQueue)
3535
}
3636

3737

3838
/**
3939
* Processes a single level in the tree
4040
*/
41-
fun processTreeLevel(levelQueue: LinkedList<TypedJsonElement>) { // FIXME not ll, generify?
41+
fun processTreeLevel(levelQueue: LinkedList<TypedJsonElement>) {
4242
val fieldValues = levelQueue.filter { it.isJsonObject }.toMutableList()
4343

4444
jsonFieldGrouper.groupCommonFieldValues(fieldValues)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.fractalwrench.json2kotlin
2+
3+
4+
internal typealias GroupingStrategy = (lhs: TypedJsonElement, rhs: TypedJsonElement) -> Boolean
5+
6+
/**
7+
* Determines whether two JSON Objects on the same level of a JSON tree share the same class type.
8+
*
9+
* The grouping strategy used here is fairly simple. If either of the JSON objects contain 1/5 of the same
10+
* keys as one of the others, then each object is of the same type.
11+
*
12+
* The only exception to this rule is the case of an empty object, which is considered to have 1 common key
13+
* with the other class, as this allows grouping with smaller objects, but discourages it with larger ones.
14+
*/
15+
internal fun defaultGroupingStrategy(lhs: TypedJsonElement, rhs: TypedJsonElement): Boolean {
16+
val lhsKeys = lhs.asJsonObject.keySet()
17+
val rhsKeys = rhs.asJsonObject.keySet()
18+
val emptyClasses = (lhsKeys.isEmpty() || rhsKeys.isEmpty())
19+
20+
val keySize = if (lhsKeys.size > rhsKeys.size) lhsKeys.size else rhsKeys.size
21+
val commonKeyCount = if (emptyClasses) 1 else lhsKeys.intersect(rhsKeys).size
22+
return (commonKeyCount * 5) >= keySize // at least a fifth of keys must match
23+
} // FIXME should also consider relative size of objects (if lhs has 99 keys, and rhs has 1 key, then they shouldn't match)
24+
Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.fractalwrench.json2kotlin
22

3-
internal class JsonFieldGrouper {
3+
internal class JsonFieldGrouper(val groupingStrategy: GroupingStrategy) {
44

55
fun groupCommonFieldValues(allObjects: MutableList<TypedJsonElement>): List<List<TypedJsonElement>> {
66
val allTypes: MutableList<MutableList<TypedJsonElement>> = mutableListOf()
@@ -25,7 +25,7 @@ internal class JsonFieldGrouper {
2525
allObjects: MutableList<TypedJsonElement>,
2626
commonTypeList: MutableList<TypedJsonElement>) {
2727
val sameTypes = allObjects
28-
.filter { hasSameClassType(element, it) }
28+
.filter { groupingStrategy(element, it) }
2929

3030
commonTypeList.addAll(sameTypes)
3131
allObjects.removeAll(sameTypes)
@@ -35,24 +35,4 @@ internal class JsonFieldGrouper {
3535
}
3636
}
3737

38-
// TODO this should be exposed as a constructor parameter, will allow greater extensibility
39-
40-
/**
41-
* Determines whether two JSON Objects on the same level of a JSON tree share the same class type.
42-
*
43-
* The grouping strategy used here is fairly simple. If either of the JSON objects contain 1/5 of the same
44-
* keys as one of the others, then each object is of the same type.
45-
*
46-
* The only exception to this rule is the case of an empty object, which is considered to have 1 common key
47-
* with the other class, as this allows grouping with smaller objects, but discourages it with larger ones.
48-
*/
49-
private fun hasSameClassType(lhs: TypedJsonElement, rhs: TypedJsonElement): Boolean {
50-
val lhsKeys = lhs.asJsonObject.keySet()
51-
val rhsKeys = rhs.asJsonObject.keySet()
52-
val emptyClasses = (lhsKeys.isEmpty() || rhsKeys.isEmpty())
53-
54-
val keySize = if (lhsKeys.size > rhsKeys.size) lhsKeys.size else rhsKeys.size
55-
val commonKeyCount = if (emptyClasses) 1 else lhsKeys.intersect(rhsKeys).size
56-
return (commonKeyCount * 5) >= keySize // at least a fifth of keys must match
57-
} // FIXME should also consider relative size of objects (if lhs has 99 keys, and rhs has 1 key, then they shouldn't match)
5838
}

core/src/main/kotlin/com/fractalwrench/json2kotlin/Kotlin2JsonConverter.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ class Kotlin2JsonConverter(val buildDelegate: SourceBuildDelegate = GsonBuildDel
1010

1111
// TODO (general: update KDocs!)
1212

13-
// TODO expose grouping class as a parameter
14-
1513
private val jsonReader = JsonReader(JsonParser())
1614
private val sourceFileWriter = SourceFileWriter()
1715
private val traverser = ReverseJsonTreeTraverser()
@@ -27,7 +25,7 @@ class Kotlin2JsonConverter(val buildDelegate: SourceBuildDelegate = GsonBuildDel
2725

2826
val jsonRoot = jsonReader.readJsonTree(input, args)
2927
val stack = traverser.traverse(jsonRoot, args.rootClassName)
30-
val typeHolder = ClassTypeHolder(buildDelegate)
28+
val typeHolder = ClassTypeHolder(buildDelegate, ::defaultGroupingStrategy)
3129
typeHolder.processQueue(stack)
3230

3331
sourceFileWriter.writeSourceFile(typeHolder.stack, args, output)

core/src/main/kotlin/com/fractalwrench/json2kotlin/TypedJsonElement.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import com.google.gson.*
44
import java.math.BigDecimal
55
import java.math.BigInteger
66

7-
class TypedJsonElement : JsonElement { // TODO check visibility
7+
internal class TypedJsonElement : JsonElement {
88

99
val jsonElement: JsonElement
1010
val jsonKey: String

0 commit comments

Comments
 (0)