A next-generation MOF (Meta-Object Facility) combined with modern model data management capabilities. HMF is a metamodel-agnostic framework: any metamodel can be built on top of it.
"Metadata that feels like JSON."
This repository is a multi-module Gradle build:
hmf/
├── hmf-schema/ # Metamodel schema layer — MetaClass, MetaProperty,
│ # MetaAssociation, MetaConstraint, MetaOperation,
│ # ModelElement, ModelEngine. No runtime deps.
└── hmf-runtime/ # Runtime engine — HMFEngine, MountableEngine, HMFObject,
# MetamodelRegistry, ConstraintEngine, OCL/GQL query,
# Z3/SMT solver, in-memory graph storage.
Code generation lives in a sibling repo, hmf-codegen, and is
wired in via includeBuild("../hmf-codegen").
Dependency direction:
hmf-schema ← hmf-runtime
hmf-runtime exposes hmf-schema transitively via Gradle api().
Declarative type definitions using Kotlin named parameters or JSON:
MetaClass— types with attributes, operations, constraints, semantic bindings, and ownership bindings.MetaProperty— primitive-typed attributes with multiplicity and derivation support. Non-primitive properties are modeled as association ends, not attributes.MetaAssociation/MetaAssociationEnd— directional relationships with navigability, aggregation, ordering, and bounds.MetaConstraint— OCL or native Kotlin constraint bodies, typed by purpose:DERIVATION,VERIFICATION,NON_NAVIGABLE_END,REDEFINES_DERIVATION,SUBSETS_DERIVATION,IMPLICIT_REDEFINITION,IMPLICIT_TYPE_FEATURING,IMPLICIT_BINDING_CONNECTOR.MetaOperation— callable operations with OCL, GQL, property-reference, or native Kotlin bodies.SemanticBinding— declarative implied relationships (specializes, subsets, redefines, type-features) with a rich conditional DSL.OwnershipBinding— declare that a metaclass acts as an ownership intermediate (e.g. Membership, FeatureMembership).MetamodelLoader— Jackson-based JSON serialization.
HMFEngine— the runtime container and single source of truth:- Element (node) storage by ID and by class with an O(1) class index.
- Association (edge) graph with a two-level name index.
- Stored, derived, and association-based property access.
- Operation invocation with language dispatch (OCL, GQL, property-ref, native).
LifecycleHandlerevents on element/link create/update/delete.
MountableEngine— extends HMFEngine with read-only mounts so library content can be shared across sessions without copying. Resolution order: local → explicit mounts → implicit mounts.MetamodelRegistry— class/association lookup, inheritance queries, transitive subsetting/redefinition closure, and validation.ConstraintEngine/ConstraintRegistry— derived property evaluation, invariant validation, non-navigable end computation, and implicit relationship creation.- OCL (
query/ocl/) — full parser (ANTLR 4.13), AST, visitor, and executor. Supports iterators (select, reject, collect, forAll, exists, closure, sortedBy, iterate, …), navigation, type operations, let/if, and collection ops. Includes a parse cache and recursion-safeclosure. - GQL (
query/gql/) — graph query language: parser, AST, executor. - Constraint solver — Z3/SMT via
tools.aqua:z3-turnkey:4.13.0:OclToZ3Translator— translates a subset of OCL AST to Z3 expressions.ConstraintSolverService—solve,isSatisfiable,optimize,findConflicts(usingassertAndTrack+unsatCore).
GraphStorage— interface for graph-native node/edge storage, with anInMemoryGraphStorageimplementation for dev and testing.
import org.openmbee.hmf.framework.meta.*
import org.openmbee.hmf.framework.runtime.*
// 1. Define a metamodel
val element = MetaClass(
name = "Element",
isAbstract = true,
attributes = listOf(
MetaProperty(name = "declaredName", type = "String", multiplicity = "0..1"),
MetaProperty(
name = "name",
type = "String",
isDerived = true,
derivationConstraint = "deriveElementName"
)
),
constraints = listOf(
MetaConstraint(
name = "deriveElementName",
type = ConstraintType.DERIVATION,
expression = "self.effectiveName()",
description = "Derivation for Element::name"
)
)
)
// 2. Register and instantiate
val registry = MetamodelRegistry()
registry.register(element)
val engine = HMFEngine(registry)
val obj = engine.createElement("Element")
engine.setProperty(obj.id!!, "declaredName", "MyElement")
// Derived property is computed on access
val name = engine.getProperty(obj.id!!, "name")- JDK 21
- Gradle 9.x (or use the wrapper)
./gradlew build --no-configuration-cache
./gradlew test --no-configuration-cache
./gradlew compileKotlin --no-configuration-cache| Dependency | Version | Purpose |
|---|---|---|
| Kotlin | 2.1.10 | Language |
| JDK | 21 | Runtime |
| Gradle | 9.2.1 | Build |
| Jackson | 2.16.1 | JSON serialization |
| ANTLR | 4.13.1 | OCL / GQL grammars |
| z3-turnkey | 4.13.0 | SMT solver (bundled binaries) |
| kotlin-logging | 6.0.3 | Logging facade |
| Logback | 1.4.14 | Logging implementation |
| Kotest | 5.8.0 | Testing framework |
| JUnit Jupiter | 5.10.1 | Test runner |
| MockK | 1.13.9 | Mocking |
- hmf-codegen — Kotlin and TypeScript code generators that produce typed APIs from an HMF metamodel.