Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9d0465b
add conformance check for the new evaluation example
Apr 22, 2026
5abb3f2
add new evaluation test case (WIP)
Jun 15, 2026
22ae0df
Initial commit
PresiProdanov Jun 16, 2026
c26a34e
Initial commit
PresiProdanov Jun 16, 2026
484bee7
Refactor updater factory and add combined evaluation assertions
PresiProdanov Jun 18, 2026
e5bcdb3
Merge branch 'dev' into PPr/initial
PresiProdanov Jun 22, 2026
4bc5683
Changes to handling of imports, requirements updated, new TODOs
PresiProdanov Jun 23, 2026
b79772b
Fix todos for import handling
PresiProdanov Jun 24, 2026
61c0d25
Add more tests and checks for associations
PresiProdanov Jun 29, 2026
9188a98
Refactor CodeAdapter.java
PresiProdanov Jun 30, 2026
191aaad
Refactor AdaptationConflictDetector and SpoonUpdater with helpers. Ad…
PresiProdanov Jul 1, 2026
3a043ce
CodeUpdaterMill, CodeAdapter refactoring, small changes and possible …
PresiProdanov Jul 10, 2026
55f64f6
Enhance AdaptedCodeMerger to handle relocations and imports for adapt…
PresiProdanov Jul 11, 2026
b901aca
Refactor IncarnationContext and related classes to use StableElementK…
PresiProdanov Jul 11, 2026
30997fd
Refactor BasicUpdateHandler to incorporate stable key selection for i…
PresiProdanov Jul 11, 2026
3eed1ef
Refactor CodeUpdaterMill to simplify updater lifecycle management and…
PresiProdanov Jul 11, 2026
65dd134
Refactor CodeUpdater and related services to streamline method and fi…
PresiProdanov Jul 11, 2026
c747290
Refactor AdaptationConflictDetector and related classes to simplify c…
PresiProdanov Jul 11, 2026
c6b7bda
Refactor Spoon transformation services to integrate executable repair…
PresiProdanov Jul 12, 2026
1b85b17
Refactor adaptation context handling to utilize CDModelIndex as it wa…
PresiProdanov Jul 13, 2026
8856eb7
Refactor constants and update method signatures for clarity; enhance …
PresiProdanov Jul 16, 2026
e0327c2
Refactor AdapterUtils and related classes to utilize AdaptReference f…
PresiProdanov Jul 16, 2026
fbff494
Add a few more examples to explain the functionalities better; more m…
PresiProdanov Jul 16, 2026
e3d7fc3
Missing StaticDelegator for one test case and refining member type im…
PresiProdanov Jul 17, 2026
57baf3b
Update method signatures for clarity; enhance type handling and impor…
PresiProdanov Jul 20, 2026
1699e83
Merge test case from paper; add more javadocs to all files
PresiProdanov Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
224 changes: 224 additions & 0 deletions ref-code-adaptation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
# ref-code-adaptation

`ref-code-adaptation` adapts concrete Java code from reference Java code and class-diagram mappings.
## Inputs

The main entry point is `de.monticore.codeAdaption.CodeAdapter`.

Required inputs:

- reference class diagram
- concrete class diagram
- mapping names, such as `buildPat`, `observer`, or `ref`
- adapter/reference Java source directory
- concrete Java source directory
- output directory

The class diagrams define which reference classes, fields, and methods incarnate as concrete Java elements. Java code is parsed and transformed with MontiCore JavaDSL and Spoon.

## Adaptation Flow

1. Load reference and concrete class diagrams with `JavaLoader.parseCD`.
2. Build mapping-specific incarnation contexts.
3. Validate inputs and detect unresolved or ambiguous mappings before creating
a staging workspace or changing existing output.
4. Copy and filter reference adapter code for the active mapping.
5. Adapt types, fields, methods, parameters, constructor calls, and pattern-derived members.
6. Merge adapted code with existing concrete code.
7. Clean generated Java:
- remove `@Adapt` annotations with Spoon
- remove invalid generated imports through JavaDSL import declarations
- preserve valid existing imports without inventing imports for unresolved
simple names
- keep Spoon as the only whole-file formatter; import cleanup edits only
import declaration source ranges
8. Publish the completed staging directory transactionally, restoring the
previous output if publication fails.
9. Compile and structurally verify generated Java in tests.

The context-building step depends on the `useConcretization` argument of
`CodeAdapter.adapt(...)`.

### `useConcretization=true`

This mode delegates model repair to cdconcretization before code adaptation:

1. `ConcretizationCompleter` completes the concrete CD by adding safe missing
model elements, repairing deterministic inheritance gaps, adapting
multi-incarnation names, and removing redundant inherited attributes.
2. `CDConformanceChecker` validates the completed CD and provides the
mapping-specific incarnation mapping.
3. `JavaTypeUpdateService` projects Java-expressible elements that were added
to the completed concrete CD, such as missing fields, methods, types, enum
constants, inheritance, and interfaces.

Use this mode when the concrete CD may need deterministic model-level repair
before Java adaptation.

### `useConcretization=false`

This mode does not mutate or complete the concrete CD. It builds a manual
incarnation context from:

- explicit stereotypes for the active mapping name,
- deterministic name and adapted-name rules enabled by `CDConfParameter`,
- manual `<<forEach="...">>` mappings derived from already-known
incarnations.

The manual branch does not call `ConcretizationCompleter` or
`CDConformanceChecker`, and it does not clone or create CD elements. Conflicts
are reported together as a `CodeAdaptationException` before
`JavaLoader.removeDirectory(outputPath)` is executed, so existing output is
preserved when adaptation cannot safely start.

Supported manual `forEach` targets:

- Type target: `<<forEach="DataClass">> class DataClassBuilder`
- Attribute target: `<<forEach="DataClass.attribute">> any attribute`
- Owner-implied attribute target: `<<forEach="attribute">> any getAttribute()`

For method `forEach` over attributes, concrete method incarnations are derived
from already-mapped concrete attributes and deterministic method names, for
example `getAttribute()` to `getFirstName()` and `getAge()`. The manual mode
does not invent cdconcretization suffix rules; concrete stereotypes or enabled
name rules must make the target deterministic.

## Association Adaptation

Associations affect Java through navigable role fields. For example,

```cd
association [1] User -> (roles) Role [*];
```

is generated by the CD4Code configuration as a collection-valued
field comparable to `Set<Role> roles` on `User`. `CodeAdapter` and CD4Code have
separate responsibilities:

- `CodeAdapter` adapts handwritten Java that uses an association. It updates
endpoint type references and owner-scoped direct role-field reads or writes,
such as `this.roles`.
- CD4Code creates the role-derived fields with `--fieldfromrole navigable`.
Association fields are not projected as ordinary CD attributes by
`CodeAdapter`.

Given `User -> (roles) Role` and the concrete association
`Student -> (roles) HiwiRole`, code such as
`for (Role role : this.roles)` is adapted to use `HiwiRole` while retaining the
role `roles`. If the concrete role is renamed, direct field accesses are renamed
as well. Bidirectional associations are handled per role: a role written on one
association side produces a field on the opposite endpoint, and reads and
assignments are rewritten only inside that owning Java type.

## Important Implementation Points

- `JavaLoader.parseCD` must use the same symbol-table setup as `loadCD`, including built-in types. CDs must declare imports explicitly for Java library types such as `Object`, `String`, `List`, or `Optional`.
- `BasicUpdateHandler` handles ordinary and multi-incarnation adaptation through one optional,
immutable stable-key selection. An empty selection represents the ordinary case.
- `MappingAdaptationRunner` owns the isolated per-pass updater lifecycle, output filtering, merge,
cleanup, and error wrapping.
- `CDTypeRelations` centralizes direct generated-AST access for interfaces,
superclasses, modifiers, and type-reference printing. Runtime Java reflection
is not used by the adapter.
- `ManualIncarnationContextBuilder` is the non-mutating context builder for `useConcretization=false`.
- `IncarnationContext` owns one immutable stable-key mapping. MontiCore symbols
are retained only as mapped-element payload for AST operations; symbol object
identity is not used for incarnation lookup.
- `AdaptationConflictDetector` validates manual mappings before Java output is written.
- `JavaTypeUpdateService` fills Java-expressible gaps only after
cdconcretization, such as missing fields, methods, types, enum constants,
inheritance, and interfaces.
- `JavaSourcePostProcessor` is the final source cleanup step. It parses JavaDSL
compilation units for import declarations and removes only known invalid or
malformed generated imports. It does not infer missing JDK imports from
unresolved simple names.
- `JavaSourceNames` centralizes Java/CD type naming, generic rendering, arrays,
primitives, `void`, and `any` normalization. `JavaMethodSignatures` validates
method names and parameter lists through the JavaDSL grammar rather than
splitting them manually; invalid signatures remain unmatched. Callers should
use these utilities instead of open-coded name or signature parsing.
- `SpoonUpdater` is the supported code updater. `RegexUpdater` is preserved
unchanged as deprecated legacy source for compatibility and is outside the
supported adaptation path.
- `CodeUpdaterMill` owns updater initialization and isolation. Use `init()` for
Spoon, `init(Supplier)` for an alternative updater, `getUpdater()` for the
current pass, and `reset()` between isolated passes.
- Generated builder bodies are represented as structured `MethodBodySpec`
values, so setter-return and constructor-return methods are built through
Spoon statements instead of parsed string snippets.
- Concretization compatibility tests inspect and compile the adapter's real output; they do not
substitute a synthetic CD-to-Java projection.
- Concrete handwritten Java packages are authoritative when an adapted top-level type has one
unique same-name concrete declaration. The adapted declaration is merged into that package, and
other adapted units receive imports for types that no longer share their original package.
Multiple concrete package candidates or conflicting imports are rejected instead of guessed.
- The concretization compilation oracle may stub a missing type only when it is declared by the
original concrete CD and one concrete Java package is unambiguous. Types introduced only from the
reference CD are not stubbed, so stale reference names and missing adapter output fail compilation.
- Final generated output must not contain adapter metadata.
- Generated Java cleanup intentionally avoids broad source-text regex formatting.
Comments, literals, generics, operators, and method bodies should be left to
Spoon, JavaDSL, or AST-level code.



## Manual Conflict Detection

When `useConcretization=false`, the adapter should detect risks that
cdconcretization would otherwise repair or reject on the model level. Reported
conflict categories include:

- missing used type or `any` type incarnation
- type-kind mismatches that cannot be handled by the selected parent/interface mode
- illegal or ambiguous inheritance situations
- field name/type conflicts and duplicate generated field targets
- duplicate Java method signatures with incompatible return types
- ambiguous overloaded stereotypes without a signature
- enum constant order conflicts
- association-derived Java field conflicts, including cardinality and direction ambiguity
- missing manual `forEach` target incarnations

`CodeAdapterTestCase1` exercises the `stud` and `prof` mappings together and is
expected to adapt successfully. Association-role conflicts that remain
ambiguous are reported before output generation; the testcase itself is no
longer an error-only scenario.

## Verification

The cdconcretization-derived tests use the adapter's generated output as their
oracle input. A correct case means:

- final Java files exist
- no final Java file contains `@Adapt` or the `Adapt` import
- generated Java compiles
- generated Java structure matches the Java-expressible `*Conc.cd` to `*Out.cd`
completion delta for every type materialized in adapter output, except for the
explicitly registered model boundaries described below

Exact Java source text is not the main oracle, but generated Java should still be readable and consistently spaced.

## Current Limitations

No fixture is hidden in a generic disabled-case bucket. Three underspecified
elements without an incarnation are explicit rollback/error tests: one attribute,
one method parameter, and one method return type. They are invalid because the
placeholder type `any` cannot be emitted into a concrete CD.

Three fixtures exercise completion semantics that upstream `cdconcretization`
explicitly does not implement. They remain executable rejection/rollback tests:

- attribute `forEach` across inherited declaring owners
- attribute `forEach` without a target incarnation (requires optional-member or
`matchStructure` semantics)
- method-target `forEach`

Five fixtures still compile and run, but do not use their complete model as a
structural oracle. Each is registered by path and reason in
`CDConcretizationTestCases`: four mirror tests explicitly disabled upstream
because of unresolved association, binding, cross-incarnation, or bidirectional
`forEach` semantics; the fifth is an inherited attribute-type mismatch that the
current concretizer incorrectly accepts. These cases are not skipped locally;
metadata cleanup and strict Java compilation remain mandatory.

Fixtures for which upstream provides no separate `*Out.cd` use their reference
CD as the structural oracle, matching the assertions in the upstream tests.
Loading
Loading