@startuml

skinparam monochrome true
hide empty members
hide circle

class JmeterDsl {
  ..
}

package core {

  interface DslTestElement {
    HashTree buildTreeUnder(HashTree parent, BuildTreeContext context)
    void showInGui()
  }

  class BuildTreeContext {
    HashTree root
    Map<String, Object> entries
    Map<DslVisualizer, Supplier<Component>> visualizers
  }

  abstract class BaseTestElement implements DslTestElement {
    String name
    Class guiClass
    TestElement buildTestElement()
    BeanInfoSupport getBeanInfo()
  }

  abstract class TestElementContainer extends BaseTestElement {
    void addChildren(DslTestElement[] children)
  }

  abstract class TestPlanSingletonChildElement extends BaseTestElement implements TestPlanChild {
    boolean enabled
  }

  class DslTestPlan extends TestElementContainer {
    TestPlanStats run()
    TestPlanStats runIn(DslJmeterEngine engine)
    void saveAsJmx(String filePath)
    {static} DslTestPlan fromJmx(String filePath)
  }

  interface TestPlanChild extends DslTestElement

  interface DslJmeterEngine {
    TestPlanStats run(DslTestPlan testPlan)
  }

  class EmbeddedJmeterEngine implements DslJmeterEngine

  class JMeterEnvironment {
    File homeDir
  }

  EmbeddedJmeterEngine ..> JMeterEnvironment

  class DslThreadGroup extends TestElementContainer implements TestPlanChild {
    List<Stage> stages
  }

  class Stage {
      int threads
      int iterations
      Duration duration
  }

  interface ThreadGroupChild extends DslTestElement

  abstract class DslSampler extends TestElementContainer implements ThreadGroupChild

  interface SamplerChild extends DslTestElement

  interface MultiLevelTestElement extends TestPlanChild, ThreadGroupChild, SamplerChild

  abstract class DslJsr223TestElement extends BaseTestElement {
    String language
    abstract DslJsr223TestElement buildJsr223TestElement()
  }

  class DslScriptBuilder {
    int scriptId
    DslScript script
    Class varsClass
    Map<String, String> varsNameMapping
    String scriptString
    String build()
    String buildAsProperty()
  }

  interface DslScript {
    Object run(DslScriptVars vars)
  }

  abstract class DslScriptVars {
    SampleResult prev
    JMeterContext ctx
    JMeterVariables vars
    Properties props
    Sampler sampler
    Logger log
  }

  class PropertyScriptBuilder extends DslScriptBuilder

  interface PropertyScript extends DslScript

  class PropertyScriptVars extends DslScriptVars

  interface Jsr223Script extends DslScript {
    void run(Jsr223ScriptVars vars)
  }

  abstract class Jsr223ScriptVars extends DslScriptVars {
    String Label
  }

  package threadgroups {

    class RpsThreadGroup extends TestElementContainer implements TestPlanChild {
      List<TimerSchedule> schedules
      EventType counting
      int initThreads
      int maxThreads
      double spareThreads
    }

    class TimerSchedule {
      double fromRps
      double toRps
      Duration duration
    }

    enum EventType {
      REQUESTS
      ITERATIONS
    }

  }

  package configs {

    class DslCsvDataSet extends BaseTestElement implements MultiLevelTestElement {
      String file
      String delimiter
      String encoding
      String[] variableNames
      boolean ignoreFirstLine
      boolean stopThread
      Sharing shareMode
    }

    enum Sharing {
      ALL_THREADS
      THREAD_GROUP
      THREAD
    }

    DslCsvDataSet ..> Sharing

  }

  package controllers {

    abstract class DslController extends TestElementContainer implements ThreadGroupChild

    class DslTransactionController extends DslController

    class PercentController extends DslController {
      float percent
    }

    class DslIfController extends DslController

    class DslWhileController extends DslController

    DslIfController --> PropertyScriptBuilder
    DslWhileController --> PropertyScriptBuilder

  }

  package preprocessors {

    class DslJsr223PreProcessor extends DslJsr223TestElement implements MultiLevelTestElement

    interface PreProcessorScript extends Jsr223Script

    class PreProcessorVars extends Jsr223ScriptVars

  }

  package postprocessors {

    class DslJsr223PostProcessor extends DslJsr223TestElement implements MultiLevelTestElement

    interface PostProcessorScript extends Jsr223Script

    class PostProcessorVars extends Jsr223ScriptVars

    class DslRegexExtractor extends BaseTestElement implements MultiLevelTestElement {
      String variableName
      String regex
      int matchNumber
      String template
      String defaultValue
      TargetField fieldToCheck
      Scope scope
      String scopeVariable
    }

    enum TargetField {
      RESPONSE_BODY
      RESPONSE_BODY_UNESCAPED
      RESPONSE_BODY_AS_DOCUMENT
      RESPONSE_HEADERS
      REQUEST_HEADERS
      REQUEST_URL
      RESPONSE_CODE
      RESPONSE_MESSAGE
    }

    enum Scope {
      ALL
      MAIN_SAMPLE
      SUB_SAMPLES
    }

    DslRegexExtractor ..> TargetField
    DslRegexExtractor ..> Scope

  }

  package assertions {
    class DslResponseAssertion extends BaseTestElement  implements MultiLevelTestElement {
      TargetField fieldToTest
      boolean ignoreStatus
      String[] testStrings
      TestStringStrategy testStrategy
      boolean invertCheck
      boolean anyMatch
    }

    enum TargetField {
      RESPONSE_BODY
      RESPONSE_BODY_AS_DOCUMENT
      RESPONSE_CODE
      RESPONSE_MESSAGE
      RESPONSE_HEADERS
      REQUEST_HEADERS
      REQUEST_URL
      REQUEST_BODY
    }

    enum TestStringStrategy {
      SUBSTRING
      EQUALS
      CONTAINS_REGEX
      MATCHES_REGEX
    }

    DslResponseAssertion ..> TargetField
    DslResponseAssertion ..> TestStringStrategy

  }
  
  package timers {

    class DslUniformRandomTimer extends BaseTestElement implements MultiLevelTestElement {
      long minimumMillis
      long maximumMillis
    }

  }

  package listeners {

    class JtlWriter extends BaseTestElement implements MultiLevelTestElement {
      String jtlFilePath
    }

    class ResponseFileSaver extends BaseTestElement implements MultiLevelTestElement {
      String fileNamePrefix
    }

    class HtmlReporter extends BaseTestElement implements MultiLevelTestElement {
      File reportDirectory
    }

    abstract class DslBackendListener extends BaseTestElement implements MultiLevelTestElement {
      String url
      Class listenerClass
      int queueSize
      Arguments buildListenerArguments()
    }

    class InfluxDbBackendListener extends DslBackendListener {
      String token
      String title
    }

    class DslViewResultsTree extends DslVisualizer {
      int resultsLimit
    }

    abstract class DslVisualizer extends BaseTestElement implements MultiLevelTestElement

  }

}

package http {

  class DslHttpSampler extends DslSampler {
    String url
    HttpMethod method
    String body
  }

  class HttpHeaders extends BaseTestElement implements MultiLevelTestElement {
    Map<String, String> headers
  }

  class DslCacheManager extends TestPlanSingletonChildElement

  class DslCookieManager extends TestPlanSingletonChildElement

}

package java {
  class DslJsr223Sampler extends DslJsr223TestElement implements ThreadGroupChild
}

JmeterDsl -[hidden]- core
TestElementContainer -up-> "*" DslTestElement
DslTestPlan ..> TestPlanChild
DslThreadGroup ..> ThreadGroupChild
DslTestPlan ..> EmbeddedJmeterEngine
DslJsr223TestElement --> DslScriptBuilder
DslSampler ..> SamplerChild
DslJsr223Sampler ..> SamplerChild
DslHttpSampler --> HttpHeaders

@enduml