Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "QVTd In-place and Copy Transformations"

(Mechanisms)
Line 8: Line 8:
 
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=512735
 
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=512735
  
=The Primary Use Case (Copy)=
+
==The Primary Use Case (Copy)==
  
 
Support an EcoreUtil.Copier-like capability:
 
Support an EcoreUtil.Copier-like capability:
Line 16: Line 16:
 
* references to external class instances reference the unchanged external class instance
 
* references to external class instances reference the unchanged external class instance
  
==QVTr solution==
+
===QVTr solution===
  
 
Impossible, since there is no ability to create a dynamically determined type.
 
Impossible, since there is no ability to create a dynamically determined type.
Line 25: Line 25:
 
at the end of the RelToCore example.
 
at the end of the RelToCore example.
  
==QVTc solution==
+
===QVTc solution===
  
 
Impossible, since there is no ability to create a dynamically determined type.
 
Impossible, since there is no ability to create a dynamically determined type.
  
=The Secondary Use Case (Endogeneous)=
+
==The Secondary Use Case (Endogeneous)==
  
 
An endogeneous (out-of-place) transformation may create a slightly modified copy of its input.
 
An endogeneous (out-of-place) transformation may create a slightly modified copy of its input.

Revision as of 17:09, 20 March 2017

The QVT specification has vague indications that QVTr / QVTc supports in-place transformations but provides no real details.

Copy transformations in which the output is very similar to the input are not considered at all.

This working document considers how copy and in-place might be supported. It takes over from

The Primary Use Case (Copy)

Support an EcoreUtil.Copier-like capability:

  • deep copy of an input model
  • arbitrary input classes, some of which may use an extension metamodel not known until run-time
  • references to copied class instances are redirected to the copies
  • references to external class instances reference the unchanged external class instance

QVTr solution

Impossible, since there is no ability to create a dynamically determined type.

Even if all classes are known at programming time, it is necessary to enumerate an explicit copy of each class. See the

-- copy an ocl expression
-- For space reasons this relation is not expanded out here

at the end of the RelToCore example.

QVTc solution

Impossible, since there is no ability to create a dynamically determined type.

The Secondary Use Case (Endogeneous)

An endogeneous (out-of-place) transformation may create a slightly modified copy of its input.

This is rather similar although there is much more adjustment of a pure copy, types are usually known. There may be many copy invocations.

Copy versus In-Place transformation

These could be treated as separate challenges, but from a programmer perspective they are identical; a potentially late run-time option can specify whether the output overlays or replicates the input. We therefore treat copy and in-place as the same problem when considering UMLX, QVTr, QVTc. THe distinction may perhaps occurs as alternate qvts2qvti synthesizes generate different code, or perhaps just in the qvti run-time.

Copy versus non-copy transformation

A non-copy transformation specifies all created types explicitly. Output slots are populated explicitly.

A copy transformation can re-use the source type/object as the target type/object. Output slots may be populated implicitly (by copy/re-use).

Using a non-copy language semantics for a copy requires all slots to be enumerated to participate in the copy. This is verbose and error prone.

An alternative copy language semantics need only specify deviations from a perfect deep copy. cf. Henshin's create/delete markups.

Mechanisms

Operations and Relations provide type-dependent functionality. Just about anyting can be done with an OPeration, but it isn'y bidirectional. Therefore try to solve problem using Relations/Mappings.

Copy invocation

In QVTr, a when { DoCopy(a,b}; } could invoke a copy between a and b.

In QVTc, the conventional QVTr2QVTc conversion of the QVTr invocation should work.

=> regular

Base Copy Type definition

A normal invocation implies a normal definition that happens to deep copy. The 'create' action needs to be annotated as a copy.

For an individual copied type within a pattern of not-copies, the node in a QVTr pattern perhaps needs a 'copy' prefix.

For an endogeneous transformation we would like to avoid duplicate programming. Perhaps a form of differential relation in the source syntax can be syntax sugar for numerous 'copy' prefixes.

This is circular a when annotates an assign as a copyCall, which has a body that copies. Which is more primitive? annotation of an assignment or annotation of a domain. In QVTc, we annotate a 'realize'. QVTr hides the ralize, so it is not annotateable, ? annotating a domain makes sense?

=> irregularity: created type is defined by source object rather than program declaration

Property Copy definition

A custom copy may provide variant property assignments. Ideally the defaults property copies would magically not happen. This is very hard if the copy is distributed over many collaborating relations. Therefore a practical restriction performs all local property assignments then all implicit assignments. Users cannot distribute copy functionality.

=> irregularity: explicit property assignments followed by residual implicit copied property assignments => restriction: copy assignments must be local to a copy relation

Derived Copy definition

If a copy is a relation, a derived relation supports a derived copy. Regular.

=> restriction: trace class inheritance must persist the relation derivations.

Trace Class

If a copy is a relation, it has a trace class. Regular.

Details

QVTc / QVTr copy semantics

QVTr is realized by a QVTr2QVTc transformation, so it is really the QVTc copy semantics that we must resolve.

Derived types

QVTc cannot create/re-use a derived type. A variant realize, a typeof operator or a template type could re-use the dynamic type, but we must also deep copy all the slots that are not assigned explicitly. Is a copy except a list of properties needed? Is it possible to perform a global transformation analysis to identify the except properties automatically? Is it necessary to defer to a run-time capability that automatically deep copies what isn't explicitly assigned? How would a run-time capability know to perform the late deep copies if multiple mappings collaborate in the assignments?

A copy-except-list-of-properties makes the problem a programmer responsibility, so it can be right. A WFR can detect some conflicts between the except-list and the actual assignments. This is similar to a WFR that can detect missing assignments.

The copy-except can be defined more positively as a CopySignature, rather like a QVTr Key; the name of a copied base-type and the names of the properties that are to be assigned explicitly, rather than copied automatically. realize xInstance:XClass using XCopySignature.

Copy Trace Classes

A copy needs a simple 'trace' comprising XCopySignature{in:X; out:X} allowing navigation such as 'myIn.XCopySignature.out'.

How does the copy trace relate to the mapping trace?

For a simple mapping that creates a copy the mapping trace could inherit/aggregate the copy trace.

For a more complex mapping that create more than one copy, the corresponding multiple inheritance is only an option under normal OO semantics with careful renaming, unfortunately EMF always imposes diamond inheritance. Multiple aggregation is possible. Without inheritance, does a copied object have separate navigations using the mapping trace class and the copy trace class?

Derived copy-trace classes

One CopyTrace declaration may extend another CopyTrace declaration to extend the number of not-deep-copied properties. It has no effect on the copied class which is always the same as the source.

Incremental Copy

If an obscure property in a derived copied class is changed, then an incremental copy must re-copy. How does a trace that is unaware of this property handle it? Possibly any mutation of the source triggers a full copy. Possibly the trace has an 'anything-else' so that known properties are handled efficiently, only unknown properties get the anything-else treatment.

Multiple Copy Signatures

What if a class has two distinct refined copy mappings?

Each should have a distinct copy-signature and so there should be two possible navigations.

What if a multiply inherited class inherits multiple copy mappings?

Each should have a distinct copy-signature and so there should be multiple possible navigations. The base copy traces may navigate to distinct objects. The more derived copy traces may (redundantly) navigate to the same object.

Normal multiple inheritance and casting could allow shared references, but EMF won't support it so we will need the bloat of all possibilities.

Internal/External references

A direct implementation of a reference copy must make a two-way decision as to whether the mapping navigates through the trace object of the copied internal source object, or just re-uses the external source object. Provided the trace object navigation support a Boolean test capability for existence this test is possible but messy.

We cannot eliminate the trace of the internal, but we can add a copy-trace for the external thereby ensuring that all references always use a copy-trace, even if the external trace is degenerate with identical source/target objects; just as an in-place might also have. This makes the QVTc much more regular and so simplifies the QVTr2QVTc synthesis.

QVTr copy syntax

ModelMorf

ModelMorf introduces a replace keyword that may qualify a relation to support in-place. Unfortunately I do not understand the description in the Readme.htm of its Beta-4. Perhaps there is some similarity with the domain declaration proposed below.

Transformation declaration

Applying a magic copy keyword to the transformation declaration could change the semantics/syntax but how might a transformation that needs a bit of copy and a bit of non-copy select between semantics. Seems too coarse grained.

Relation declaration

Applying a magic copy keyword to the relation declaration is more flexible but limiting for examples such as the TTC PetriNet2Statechart that need to trans form a pair of domains in-place.

Relation inheritance

Copy semantics could be inherited if default copy relations are auto-generated and available for re-use by derived relations. Unfortunately QVTr overrides is a replace rather than augment capability, so this would need changing. It is not clear how this handles types not known at programming time.

Absolute Domain declaration

Applying a magic copy keyword to the domain declaration creates a problem that there are then pairs of domains with the same name. The intuitive WFR could be relaxed.

Relative Domain declaration

A copies xxxx clause could suffix a domain declaration to indicate that the new domain is based on a copy of the xxxx domain.

Within the copy domain we can exploit the multi-rooted capability to require that all root-variables of the copy domain have names that appear in the copied domain. The copy domain therefore defines one or more Henshin-like overlay patterns; a pattern for creation, an equals null for deletion.

A very similar effect could be achieved by adding a mutation { ... } clause to the copied domain. This is slightly shorter and avoids a duplicated name, but adds to the brace syntax complexity of domains, wheres and collections.

QVTc copy syntax

QVTs implications

Copy

A realized node may be

  • created with the specified type (current functionality)
  • created/re-used with a referenced type with a selective deep copy

The new usage adds a copy-trace middle element in addition to the mapping-trace middle element. The type of the copy-trace corresponds to a copy signature and so a list of not-deep-copied properties.

In-place

We need extra edges to enforce the write-after-read re-use.

We probably don't need extra caching since the middle model caches anyway.

QVTi implications

Use Case Solution

QVTr

copy-key MyTypeKey{isCopy};
copy-key MyDerivedTypeKey extends MyTypeKey{isCopy2}

relation UseACopy {
    domain model1
        c1 : MyContext {
            t1 : MyType {}
        }
    domain model2
        c2 : MyContext {
            t2 : MyType {}
        }
    when {
        MakeABaseCopy{t1, t2);
    }
}   
 
relation MakeABaseCopy {
    domain model1
         t : MyType {};
    domain model2 copies model1 using MyTypeKey
         t { isCopy = true; };
}    
 
relation MakeADerivedCopy overrides MakeABaseCopy {
    domain model1
         t : MyDerivedType {};
    domain model2 copies model1 using MyDerivedTypeKey
         t { isCopy = true; isCopy2 = true; };
}    

QVTc

mapping UseACopy {
    domain model1(t1 : MyType){}
    domain model2(t2 : MyType | t1.TMakeABaseCopy.out = t2){
}   
 
mapping MakeABaseCopy {
    domain model1(t : MyType){};
    domain model2 copies model1
         realize t2 := ;
}    
 
mapping MakeADerivedCopy overrides MakeABaseCopy {
    domain model1(t : MyDerivedType){};
    domain model2 copies model1
         t { name = t.name.toLower(); };
}    

Back to the top