From bpmn-to-code
Replaces hardcoded BPMN string literals in Java/Kotlin code with references to generated Process API constants. Use when migrating to process API or refactoring BPMN strings to type-safe references.
npx claudepluginhub emaarco/bpmn-to-code --plugin bpmn-to-codeThis skill is limited to using the following tools:
Replace hardcoded BPMN string literals in user code with references to the generated Process API.
Sets up bpmn-to-code Maven plugin in existing projects by configuring pom.xml for BPMN code generation in Java or Kotlin.
Guides writing OpenRewrite recipes: declarative YAML, Refaster templates, imperative Java LST visitors for code refactoring, AST manipulation, custom rules, and migrations.
You are a code migration expert specializing in transitioning codebases between frameworks, languages, versions, and platforms. Generate comprehensive migration plans, automated migration scripts, and
Share bugs, ideas, or general feedback.
Replace hardcoded BPMN string literals in user code with references to the generated Process API.
// Generated by bpmn-to-code)..bpmn) — these are source-of-truth inputs, not generated code../gradlew generateBpmnModelApi or mvn io.github.emaarco:bpmn-to-code-maven:generate-bpmn-api).**/*ProcessApi*.kt and **/*ProcessApi*.java.// Generated by bpmn-to-code on the first line).$ARGUMENTS specifies a class name, filter to only that API. Otherwise, collect all generated API files.For each generated API file, extract a lookup table of string values mapped to their fully qualified API references:
object: Parse const val NAME: String = "value" lines within the top-level object and each nested object (Elements, Messages, TaskTypes, Timers, Errors, Signals, Variables, CallActivities).final class: Parse public static final String NAME = "value"; lines within the top-level class and each nested static final class.PROCESS_ID with value "newsletterSubscription" in NewsletterSubscriptionProcessApiV1 becomes:
NewsletterSubscriptionProcessApiV1.PROCESS_IDNewsletterSubscriptionProcessApiV1.Variables.SUBSCRIPTION_IDSkip non-string constants (e.g. BpmnTimer and BpmnError object references) — these are composite types and not direct string replacements.
$ARGUMENTS contains a directory path, use that as the scan root.src/main/ in the project root..kt source files exist, scan **/*.kt files..java source files exist, scan **/*.java files.src/test/) unless the user explicitly requests test migration.For each string value in the lookup table from Step 2, use Grep to search for exact occurrences in the scoped files:
"<value>" (escaped appropriately for regex)."id", "name", "type") to avoid false positives.Group the proposed replacements by file and present a summary table:
## Migration Plan
### src/main/kotlin/com/example/MyService.kt
| Line | Current | Replacement |
|------|---------|-------------|
| 24 | "newsletterSubscription" | NewsletterSubscriptionProcessApiV1.PROCESS_ID |
| 31 | "subscriptionId" | NewsletterSubscriptionProcessApiV1.Variables.SUBSCRIPTION_ID |
### src/main/kotlin/com/example/AnotherService.kt
| Line | Current | Replacement |
|------|---------|-------------|
| 12 | "Message_FormSubmitted" | NewsletterSubscriptionProcessApiV1.Messages.MESSAGE_FORM_SUBMITTED |
**Imports to add:**
- `MyService.kt` → `import com.example.api.NewsletterSubscriptionProcessApiV1`
- `AnotherService.kt` → `import com.example.api.NewsletterSubscriptionProcessApiV1`
**Total: 3 replacements across 2 files**
If a string value matches constants from multiple API classes and the context does not make it clear which process is intended, flag it and ask the user which reference to use.
If no matches are found, report that no hardcoded strings were found that match the generated API.
Ask: "Apply these replacements? (yes / skip [file-or-line] / cancel)"
For each file in the approved plan:
import <package>.<ApiClassName> after the last existing import line.import <package>.<ApiClassName>; after the last existing import line../gradlew compileKotlin or ./gradlew compileJavamvn compile