Skip to content

Configuration

Configure Metalastic metamodel generation using the type-safe Gradle plugin DSL or manual KSP configuration.

Understanding What Gets Generated

Before configuring Metalastic, it's important to understand what artifacts are generated and how configuration affects them.

Two Types of Generated Artifacts

Metalastic generates two distinct types of files:

1. Individual Metamodel Classes

One class per @Document annotated class:

Source Document                    Generated Metamodel
────────────────────────────────  ─────────────────────────────────
com.example.domain.Product    →   com.example.domain.MetaProduct
com.example.domain.Category   →   com.example.domain.MetaCategory
com.example.domain.Review     →   com.example.domain.MetaReview

Key points:

  • ✅ Stay in the same package as the source document
  • ✅ Named with configurable prefix (default: "Meta")
  • ✅ Controlled by classPrefix configuration

2. Centralized Registry Class

One registry class per source set containing all metamodel references:

Generated Registry
──────────────────────────────────────────
com.example.search.Metamodels
kotlin
object Metamodels {
    fun entries(): Sequence<Document<*>> = sequenceOf(
        product,   // from MetaProduct.Companion
        category,  // from MetaCategory.Companion
        review     // from MetaReview.Companion
    )
}

Key points:

  • ✅ Package controlled by packageName configuration
  • ✅ Class name controlled by registryClassName configuration
  • ✅ One registry per source set (main, test, etc.)

Configuration Properties

Quick Reference Table

PropertyControlsApplies ToDefaultExample
packageNamePackage of registry classMetamodels registry onlyAuto-detected, fallback: "com.ekino.oss.metalastic""com.example.search"
registryClassNameName of registry classMetamodels registry only"Metamodels""MainMetamodels"
classPrefixPrefix for Meta classes*All document metamodels"Meta""Models"

Important

registryClassName only controls the centralized registry class name, not individual document metamodel names. Use classPrefix to control document class prefixes (MetaProduct, MetaCategory, etc.).

Detailed Property Explanations

packageName

Controls: Package of the centralized Metamodels registry class

kotlin
metalastic {
    metamodels {
        packageName = "com.example.search.metamodels"
    }
}

Generates:

kotlin
// File: com/example/search/metamodels/Metamodels.kt
package com.example.search.metamodels

object Metamodels {
    fun entries(): Sequence<Document<*>> = ...
}

Auto-detection behavior:

If not explicitly configured, packageName is determined by:

  1. Single package: If all @Document classes are in one package → use that package
  2. Multiple packages: Find common ancestor package
    • Example: com.example.domain + com.example.modelcom.example
  3. No common ancestor or empty: Fallback to "com.ekino.oss.metalastic"

Individual Meta classes:* Stay in their original document packages (NOT affected by this setting)

registryClassName

Controls: Name of the centralized Metamodels registry class

kotlin
metalastic {
    metamodels {
        registryClassName = "MainMetamodels"
    }
}

Generates:

kotlin
object MainMetamodels {  // ← Name controlled by registryClassName
    fun entries(): Sequence<Document<*>> = ...
}

Individual Meta classes:* NOT affected (use classPrefix instead)

classPrefix

Controls: Prefix added to all generated document metamodel class names

kotlin
metalastic {
    metamodels {
        classPrefix = "Models"
    }
}

Generates:

Product    → ModelsProduct
Category   → ModelsCategory
Review     → ModelsReview

Default is "Meta" (MetaProduct, MetaCategory, etc.)

Basic Configuration

Simple Single Source Set

For projects with just a main source set:

kotlin
plugins {
    id("com.google.devtools.ksp") version "2.3.3"
    id("com.ekino.oss.metalastic") version "1.1.0"
}

metalastic {
    metamodels {
        packageName = "com.example.search"
        registryClassName = "Metamodels"
        classPrefix = "Meta"  // default, can be omitted
    }
}

Generates:

  • Registry: com.example.search.Metamodels
  • Documents: com.example.domain.MetaProduct, etc. (in their original packages)

Multi-Source Set Configuration

For projects with main, test, and custom source sets:

kotlin
metalastic {
    metamodels {
        // Global defaults (apply to all source sets unless overridden)
        classPrefix = "Meta"

        // Main source set specific
        main {
            packageName = "com.example.main.search"
            registryClassName = "MainMetamodels"
        }

        // Test source set specific
        test {
            packageName = "com.example.test.search"
            registryClassName = "TestMetamodels"
        }

        // Custom source set (use sourceSet syntax)
        sourceSet("integration") {
            packageName = "com.example.integration.search"
            registryClassName = "IntegrationMetamodels"
        }
    }
}

Generates:

  • Main registry: com.example.main.search.MainMetamodels
  • Test registry: com.example.test.search.TestMetamodels
  • Integration registry: com.example.integration.search.IntegrationMetamodels
  • All document classes: Use Meta prefix (inherited from global classPrefix)

Source Set Configuration

Pre-defined Source Sets

Metalastic provides convenient accessors for common source sets:

kotlin
metalastic {
    metamodels {
        main {
            // Main application code
        }

        test {
            // Unit tests
        }

        // Integration test variants
        integration {
            // Integration tests
        }

        integrationTest {
            // Alternative naming
        }

        // Functional test variants
        functional {
            // Functional tests
        }

        functionalTest {
            // Alternative naming
        }

        // E2E test variants
        e2e {
            // End-to-end tests
        }

        e2eTest {
            // Alternative naming
        }
    }
}

Custom Source Sets

For custom source sets, use the sourceSet() function:

kotlin
metalastic {
    metamodels {
        sourceSet("contractTest") {
            packageName = "com.example.contract"
            registryClassName = "ContractMetamodels"
        }

        sourceSet("performance") {
            packageName = "com.example.perf"
            registryClassName = "PerformanceMetamodels"
        }
    }
}

Features Configuration

Java Compatibility

Generate @JvmField annotations for seamless Java interoperability:

kotlin
metalastic {
    features {
        generateJavaCompatibility = true  // default: true
    }
}

When enabled:

kotlin
@JvmField
val id: KeywordField<String> = keyword("id")

When disabled:

kotlin
val id: KeywordField<String> = keyword("id")  // No @JvmField

Recommendation: Keep enabled unless you're in a Kotlin-only project and want to reduce annotation clutter.

Private Class Metamodels

Generate metamodels for private @Document classes:

kotlin
metalastic {
    features {
        generatePrivateClassMetamodels = false  // default: false
    }
}

When disabled (default):

kotlin
@Document(indexName = "internal")
private class InternalDoc { }  // No MetaInternalDoc generated

When enabled:

kotlin
@Document(indexName = "internal")
private class InternalDoc { }  // Generates MetaInternalDoc

Recommendation: Keep disabled unless you specifically need metamodels for private classes. Public API is cleaner without them.

Debug Reporting

Enable Processor Reports

Generate detailed markdown reports for debugging and build analysis:

kotlin
metalastic {
    reporting {
        enabled = true  // default: false
        outputPath = "build/reports/metalastic/processor-report.md"
    }
}

Report includes:

  • ⏱️ Performance metrics for each processing phase
  • 📊 Generation statistics (documents discovered, fields processed)
  • 🔍 Detailed processing log with timestamps
  • ❌ Error diagnostics with context
  • 📈 Historical tracking across builds

When to use:

  • 🐛 Debugging generation issues
  • ⚡ Optimizing build performance
  • 📊 Understanding what's being generated
  • 🚀 Monitoring in CI/CD pipelines

Manual Configuration (Without Gradle Plugin)

If not using the Gradle plugin, configure KSP directly:

kotlin
plugins {
    id("com.google.devtools.ksp") version "2.3.3"
}

dependencies {
    implementation("com.ekino.oss:metalastic-core:1.1.0")
    ksp("com.ekino.oss:metalastic-processor:1.1.0")
}

ksp {
    // Global configuration
    arg("metamodels.package", "com.example.search")
    arg("metamodels.registryClassName", "Metamodels")
    arg("metamodels.classPrefix", "Meta")

    // Source set specific (use dot notation)
    arg("metamodels.main.package", "com.example.main")
    arg("metamodels.main.registryClassName", "MainMetamodels")

    arg("metamodels.test.package", "com.example.test")
    arg("metamodels.test.registryClassName", "TestMetamodels")

    // Features
    arg("metalastic.generateJavaCompatibility", "true")
    arg("metalastic.generatePrivateClassMetamodels", "false")

    // Reporting
    arg("metalastic.reportingPath", "build/reports/metalastic/report.md")
}

KSP Argument Keys:

Gradle Plugin DSLKSP Argument Key
metamodels.packageNamemetamodels.package
metamodels.registryClassNamemetamodels.registryClassName
metamodels.classPrefixmetamodels.classPrefix
metamodels.main.packageNamemetamodels.main.package
metamodels.main.registryClassNamemetamodels.main.registryClassName
features.generateJavaCompatibilitymetalastic.generateJavaCompatibility
features.generatePrivateClassMetamodelsmetalastic.generatePrivateClassMetamodels
reporting.enabled + outputPathmetalastic.reportingPath

Complete Configuration Reference

Full Gradle Plugin Configuration

kotlin
metalastic {
    // Metamodel generation configuration
    metamodels {
        // ────────────────────────────────────────────────────────
        // Global defaults (apply to all source sets)
        // ────────────────────────────────────────────────────────
        packageName = "com.example.search"    // Registry package
        registryClassName = "Metamodels"              // Registry class name
        classPrefix = "Meta"                  // Meta* prefix

        // ────────────────────────────────────────────────────────
        // Source set specific overrides
        // ────────────────────────────────────────────────────────
        main {
            packageName = "com.example.main.search"
            registryClassName = "MainMetamodels"
            classPrefix = "Meta"  // Can override per source set
        }

        test {
            packageName = "com.example.test.search"
            registryClassName = "TestMetamodels"
        }

        // Custom source sets
        sourceSet("integration") {
            packageName = "com.example.integration"
            registryClassName = "IntegrationMetamodels"
        }
    }

    // ────────────────────────────────────────────────────────
    // Feature flags
    // ────────────────────────────────────────────────────────
    features {
        generateJavaCompatibility = true       // @JvmField annotations
        generatePrivateClassMetamodels = false // Skip private classes
    }

    // ────────────────────────────────────────────────────────
    // Debug reporting
    // ────────────────────────────────────────────────────────
    reporting {
        enabled = false  // Enable for debugging
        outputPath = "build/reports/metalastic/processor-report.md"
    }
}

Next Steps

Released under the MIT License.