Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
ext {
kotlinVersion="1.8.10"
kotlinVersion="1.8.20"
coroutineVersion="1.6.4"
ktxVersion="1.11.0-rc1"
jacksonVersion="2.14.2"
junitVersion="5.9.2"
slf4jVersion="2.0.6"
slf4jVersion="2.0.7"
semver4jVersion="3.1.0"
log4jVersion="2.20.0"
gdxVersion="1.11.0"
mavenResolverVersion="1.9.5"
mavenResolverVersion="1.9.7"
mockitoKotlinVersion="4.1.0"
eclipseCollectionsVersion="11.1.0"
fledUtilsVersion="0.1.9-SNAPSHOT"
fledUtilsVersion="0.1.10-SNAPSHOT"
fledEcsVersion="0.1.9-SNAPSHOT"
fledObjectUpdaterVersion="0.1.9-SNAPSHOT"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package fledware.definitions

import fledware.definitions.builder.mod.ModPackageEntry
import fledware.definitions.exceptions.UnknownDefinitionException
import fledware.utilities.ConcurrentHierarchyMap
import fledware.utilities.HierarchyMap

/**
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package fledware.definitions

import fledware.utilities.ConcurrentHierarchyMap
import fledware.utilities.HierarchyMap
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass


interface DefinitionWithType<T : Any> {
val klass: KClass<out T>
}

data class DefinitionWithTypeHolder(
val indexes: MutableMap<String, HierarchyMap<*>> = ConcurrentHashMap()
)

fun <T : Any> DefinitionRegistry<out DefinitionWithType<T>>.typeIndex(): HierarchyMap<T> {
val holder = (this as DefinitionRegistryManaged).manager.contexts
.getOrPut(DefinitionWithTypeHolder::class) { DefinitionWithTypeHolder() }
@Suppress("UNCHECKED_CAST")
return holder.indexes.computeIfAbsent(this.name) {
val index = ConcurrentHierarchyMap()
this@typeIndex.definitions.values.forEach { index.add(it.klass) }
index
} as HierarchyMap<T>
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ interface DefinitionsManager {
val classLoader: ClassLoader

/**
* all registries indexed by lifecycle name.
*
* If a Lifecycle does not create a registry, then it will not be here.
* all registries indexed by registry name.
*/
val registries: Map<String, DefinitionRegistry<out Any>>

/**
* all instantiator factories instantiator name.
*/
val instantiatorFactories: Map<String, InstantiatorFactory<out Any>>

/**
* user contexts that can be used to share data.
*/
Expand All @@ -29,16 +32,49 @@ interface DefinitionsManager {
*/
val packages: List<ModPackageDetails>

/**
* get a registry for a given definition type.
*
* @param name the name for the registry
* @throws IllegalArgumentException if the registry doesn't exist
*/
fun registry(name: String): DefinitionRegistry<out Any>

/**
*
*/
fun tearDown()
}

/**
* finds the registry with the given name.
*
* @param name the name for the registry
* @throws IllegalArgumentException if the registry doesn't exist
*/
fun DefinitionsManager.findRegistry(name: String): DefinitionRegistry<out Any> {
return registries[name]
?: throw IllegalStateException("unable to find registry: $name")
}

/**
* finds the registry with the given name and casts it to the
* expected registry type.
*
* @param name the name for the registry
* @param T the type to cast the registry to
* @throws IllegalArgumentException if the registry doesn't exist
* @throws ClassCastException if the registry can't be cast
*/
@Suppress("UNCHECKED_CAST")
fun <T : Any> DefinitionsManager.findRegistryOf(name: String): DefinitionRegistry<T> {
return findRegistry(name) as DefinitionRegistry<T>
}

/**
*
*/
fun DefinitionsManager.findInstantiatorFactory(name: String): InstantiatorFactory<out Any> {
return instantiatorFactories[name]
?: throw IllegalStateException("unable to find instantiator factory: $name")
}

/**
*
*/
@Suppress("UNCHECKED_CAST")
fun <I : Any, F : InstantiatorFactory<I>> DefinitionsManager.findInstantiatorFactoryOf(name: String): F {
return findInstantiatorFactory(name) as F
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package fledware.definitions

import kotlin.reflect.KClass

/**
* an instantiator for a specific definition.
*
* This is up to the implementors to define how something
* is actually created. It would be difficult to create a
* common way to create a complex object that would work
* well, be performant, and easy to use by the games that are
* actually defining entities.
*
* This part of the system can be completely left out, but
* there are some nice built-ins that can probably be used
* by things that do need to create instances.
*
* For simple objects that are self-contained, it might be
* better to put the creator right on the definition itself.
* But for object creation that is complex, or need to be cached,
* or depends on other definitions, it is probably better
* to add a little more architecture around the creation.
*
* @param I the type being instantiated
*/
interface Instantiator<I : Any> {
/**
* the name of the [InstantiatorFactory] that created this
*/
val factoryName: String

/**
* the name of this [Instantiator]
*/
val instantiatorName: String

/**
* the type that is instantiated
*/
val instantiating: KClass<I>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package fledware.definitions

interface InstantiatorFactory<I : Any> {
/**
* the name of this factory
*/
val factoryName: String

/**
* All instantiators that have been created.
*/
val instantiators: Map<String, Instantiator<I>>

/**
* gets an instantiator if it is already created. else,
* it will create the cache the instantiator.
*/
fun getOrCreate(name: String): Instantiator<I>
}

/**
*
*/
interface InstantiatorFactoryManaged<I : Any> : InstantiatorFactory<I> {
/**
* The [DefinitionsManager] this registry is managed by
*/
val manager: DefinitionsManager

/**
* Called by the owning manager after all the registries have been created.
*/
fun init(manager: DefinitionsManager)

/**
* Called to signal this registry needs to clean itself of anything
* that needs to be removed from memory.
*/
fun tearDown()
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@ val BuilderState.definitionRegistryBuilders: Map<String, DefinitionRegistryBuild

/**
* finds a specific [DefinitionRegistryBuilder] within the
* [definitionRegistryBuilderGroupName] state.
* [definitionRegistryBuilderGroupName] group.
*/
fun BuilderState.findRegistry(name: String): DefinitionRegistryBuilder<Any, Any> {
return definitionRegistryBuilders[name]
?: throw UnknownHandlerException("unable to find DefinitionRegistryBuilder: $name")
}

/**
* finds a specific [DefinitionRegistryBuilder] within the
* [definitionRegistryBuilderGroupName] group and casts it to the given types.
*/
@Suppress("UNCHECKED_CAST")
fun <R : Any, D : Any> BuilderState.findRegistryOf(name: String): DefinitionRegistryBuilder<R, D> {
return findRegistry(name) as DefinitionRegistryBuilder<R, D>
}

/**
* TODO: the mutators of entries need to be rethought
* apply/mutate doesn't make sense for all registries. The best would be to
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fledware.definitions.builder

import fledware.definitions.InstantiatorFactory
import fledware.definitions.InstantiatorFactoryManaged
import kotlin.collections.Map
import kotlin.collections.MutableMap
import kotlin.collections.mutableMapOf
import kotlin.collections.set

val instantiatorFactoryHolderGroupName = InstantiatorFactoryHolder::class.simpleName!!

class InstantiatorFactoryHolder : AbstractBuilderHandler() {
override val group: String
get() = instantiatorFactoryHolderGroupName
override val name: String
get() = instantiatorFactoryHolderGroupName

val instantiators: Map<String, InstantiatorFactoryManaged<Any>> = mutableMapOf()
}

val BuilderState.instantiatorFactoryHolder: InstantiatorFactoryHolder
get() = this.findHandlerGroupAsSingletonOf(instantiatorFactoryHolderGroupName)

val BuilderState.instantiatorFactories: Map<String, InstantiatorFactoryManaged<Any>>
get() = this.instantiatorFactoryHolder.instantiators

fun BuilderState.putInstantiatorFactory(factory: InstantiatorFactory<out Any>) {
@Suppress("UNCHECKED_CAST")
(instantiatorFactories as MutableMap)[factory.factoryName] =
factory as InstantiatorFactoryManaged<Any>
}

fun BuilderState.removeInstantiatorFactory(factory: InstantiatorFactory<Any>) {
(instantiatorFactories as MutableMap).remove(factory.factoryName)
}

fun BuilderState.removeInstantiatorFactory(factory: String) {
(instantiatorFactories as MutableMap).remove(factory)
}

fun DefinitionsBuilderFactory.withInstantiatorFactory(
factory: InstantiatorFactory<out Any>
) : DefinitionsBuilderFactory {
this.putInstantiatorFactory(factory)
return this
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class AnnotatedClassEntryFactory : AbstractBuilderHandler(),
override val order: Int = 20

override fun attemptRead(modPackage: ModPackage, entry: String): List<ModPackageEntry> {
if (entry.endsWith("Kt.class"))
return emptyList()
if (!entry.endsWith(".class"))
return emptyList()
val klass = modPackage.loadClass(entry).kotlin
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package fledware.definitions.builder.registries

import fledware.definitions.DefinitionRegistryManaged
import fledware.definitions.DefinitionWithType
import fledware.definitions.builder.mod.ModPackageEntry
import fledware.definitions.exceptions.IncompleteDefinitionException
import fledware.definitions.manager.DefaultDefinitionRegistry
import kotlin.reflect.KClass
import kotlin.reflect.full.isSuperclassOf


// TODO: move this to an interface and put in public place?
data class AnnotatedClassDefinition<T : Any>(
val klass: KClass<out T>,
override val klass: KClass<out T>,
val annotation: Annotation
)
): DefinitionWithType<T>

class AnnotatedClassRegistryBuilder<T : Any>(
override val name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fledware.definitions.builder.DefinitionsBuilder
import fledware.definitions.builder.DefinitionsBuilderState
import fledware.definitions.builder.ModProcessingStep
import fledware.definitions.builder.definitionRegistryBuilders
import fledware.definitions.builder.instantiatorFactories
import fledware.definitions.builder.mod.ModPackage
import fledware.definitions.builder.mod.ModPackageContext
import fledware.definitions.builder.mod.ModPackageDetailsRaw
Expand All @@ -17,10 +18,12 @@ import fledware.definitions.builder.mod.std.DefaultModPackageContext
import fledware.definitions.builder.modProcessingSteps
import fledware.definitions.builder.serializers.figureSerializer
import fledware.definitions.builder.serializers.readAsType
import fledware.definitions.exceptions.DefinitionException
import fledware.definitions.exceptions.ModPackageReadException
import fledware.definitions.manager.DefaultDefinitionsManager
import fledware.utilities.ConcurrentTypedMap
import org.slf4j.LoggerFactory
import java.lang.Exception

open class DefaultDefinitionsBuilder(
override val state: DefinitionsBuilderState
Expand All @@ -37,7 +40,8 @@ open class DefaultDefinitionsBuilder(
contexts = ConcurrentTypedMap().also {
state.managerContexts.values.forEach { value -> it.put(value) }
},
initialRegistries = state.definitionRegistryBuilders.values.map { it.build() }
initialRegistries = state.definitionRegistryBuilders.values.map { it.build() },
instantiatorFactories = state.instantiatorFactories
)
}

Expand Down Expand Up @@ -68,7 +72,13 @@ open class DefaultDefinitionsBuilder(
// create all the entry infos that can be processed
val unhandledEntries = modPackage.entries.mapNotNull { entry ->
orderedEntryParsers.firstNotNullOfOrNull {
it.attemptRead(modPackage, entry).ifEmpty { null }
try {
it.attemptRead(modPackage, entry).ifEmpty { null }
}
catch (ex: Exception) {
throw DefinitionException(
"exception in ${modPackage.name} with reading entry $entry", ex)
}
}
}.flatMapTo(linkedSetOf()) { it }
if (logger.isDebugEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fledware.definitions.builder.std

import com.fasterxml.jackson.core.type.TypeReference
import fledware.definitions.builder.DefinitionsBuilderFactory
import fledware.definitions.builder.InstantiatorFactoryHolder
import fledware.definitions.builder.ex.withAddBuilderHandlerHandler
import fledware.definitions.builder.ex.withObjectUpdater
import fledware.definitions.builder.mod.entries.AnnotatedClassEntry
Expand Down Expand Up @@ -41,8 +42,8 @@ fun defaultBuilder() = DefaultDefinitionsBuilderFactory()
.withBuilderHandler(JarModPackageFactory())
.withBuilderHandler(AnnotatedClassEntryFactory())
.withBuilderHandler(AnnotatedFunctionEntryFactory())
.withBuilderHandler(AnnotatedFunctionEntryFactory())
.withBuilderHandler(ResourceEntryFactory())
.withBuilderHandler(InstantiatorFactoryHolder())
.withStandardModEntryProcessors()
.withAddBuilderHandlerHandler()
.withObjectUpdater()
Expand Down
Loading