From 635110d78e3580321900a025754c3542907c443b Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Fri, 6 Dec 2024 15:31:13 +0100 Subject: [PATCH 1/6] Add IntelliJ dir to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 078418f5..7a4afb0d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ target/ *.log .mvn/wrapper/*.jar +# Idea +.idea/ + # Eclipse META-INF build.properties From 9614d238f0f365377bb9536b020ded6d9fbe6136 Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Fri, 31 Jan 2025 10:50:29 +0100 Subject: [PATCH 2/6] add support for handling vitruviuschanges --- .../ChangePropagationSpecification.xtend | 35 +++++++- .../propagation/impl/ChangePropagator.xtend | 89 ++++++++++++++++++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend index ed86703d..97c6717f 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend @@ -3,6 +3,7 @@ package tools.vitruv.change.propagation import org.eclipse.emf.ecore.EObject import tools.vitruv.change.atomic.EChange import tools.vitruv.change.composite.MetamodelDescriptor +import tools.vitruv.change.composite.description.VitruviusChange; import tools.vitruv.change.correspondence.Correspondence import tools.vitruv.change.correspondence.view.EditableCorrespondenceModelView import tools.vitruv.change.interaction.UserInteractor @@ -44,6 +45,7 @@ interface ChangePropagationSpecification extends ChangePropagationObservable { /** * Returns whether this ChangePropagationSpecification handles the given change, i.e., * whether {@link #propagateChange} will perform changes when applied to that change. + * TODO ist default-impl false hier ne gute Idee? * * @param change the atomic change for which to check whether this specification reacts * to it. Must not be null. @@ -52,7 +54,7 @@ interface ChangePropagationSpecification extends ChangePropagationObservable { * @return true if {@link #propagateChange} will perform modifications in response to the * given change, false otherwise */ - def boolean doesHandleChange(EChange change, EditableCorrespondenceModelView correspondenceModel) + def boolean doesHandleChange(EChange change, EditableCorrespondenceModelView correspondenceModel) { false } /** * Performs modifications in target models identified by accessing the given CorrespondenceModel @@ -68,4 +70,35 @@ interface ChangePropagationSpecification extends ChangePropagationObservable { * Must not be null. */ def void propagateChange(EChange change, EditableCorrespondenceModelView correspondenceModel, ResourceAccess resourceAccess) + + + /** + * Returns whether this ChangePropagationSpecification handles the given change, i.e., + * whether {@link #propagateChange} will perform changes when applied to that change. + * + * @return true if {@link #propagateNonAtomicChange} will perform modifications in response to the + * given change, false otherwise. + */ + def boolean doesHandleNonAtomicChanges() { false } + + /** + * If this ChangePropagationSpecification handles non-atomic changes (change sequences), + * see {@link #doesHandleNonAtomicChanges }, this + * performs modifications in target models identified by accessing the given CorrespondenceModel + * for the elements changed by the given EChange in order to reflect the changes in the + * target model. + * + * Else, this does nothing. TODO maybe let it delegate to {@link #propagateChange}? + * + * @param change the non-atomic change (i.e. change sequence) which shall be propagated. Should affect only elements in + * an instance of a source metamodel of this specification (see + * {@link #getSourceMetamodelDescriptor}). Must not be null. + * @param correspondenceModel the correspondence model to retrieve information about the target + * model from. Must not be null. + * @param resourceAccess an object for resource access, in particular to create new model files. + * Must not be null. + */ + def void propagateNonAtomicChange(VitruviusChange change, EditableCorrespondenceModelView correspondenceModel, ResourceAccess resourceAccess) { + // noop + } } diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend index 704fb453..41093fb4 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend @@ -87,12 +87,78 @@ class ChangePropagator { val List userInteractions = new ArrayList def private propagateChanges() { - val result = sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] + //TODO dunno if this is good.. + // first, the whole vitruviuschange is propagated to CPSs that can handle it. + // Then, the other CPSs handle the change in their way (the non-atomic-enabled CPSs are called, but perform noops, currently, just like some other CPSs where 'doesHandleChange' returns false, + // which is not checked, here (noop is assumed). TODO see unten + val result = propagateNonAtomicChange() + result += sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] + + //val result = sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] handleObjectsWithoutResource() changedResources.forEach[modified = true] return result } + def private List propagateNonAtomicChange() { + //TODO maybr deactivate?? + val userInteractorChange = installUserInteractorForChange(sourceChange) + changePropagationProvider.forEach[registerObserver(this)] + userInteractor.registerUserInputListener(this) + //TODO implement calling changepropspec respective function + //TODO do the other crap done in propagateSingleChange, too... + // TODO this for testin purposes only, only the weiterleiting part for testing! + val propagationResultChanges = try { + sourceChange.affectedEObjectsMetamodelDescriptors.flatMap [ + // we only want ChangePropSpecs that handle non-atomic changes + changePropagationProvider.getChangePropagationSpecifications(it).filter[it.doesHandleNonAtomicChanges()] => [ + forEach[it.userInteractor = outer.userInteractor] + ] + ].toSet.flatMapFixed [ + //TODO change deez to + propagateNonAtomicChangeForChangePropagationSpecification(sourceChange, it) + //propagateChangeForChangePropagationSpecification(change, it) + ] + } finally { + //TODO maybr deactivate?? + userInteractor.deregisterUserInputListener(this) + changePropagationProvider.forEach[deregisterObserver(this)] + userInteractorChange.close() + } + + //TODO copied: müsste passen so + if (logger.isDebugEnabled) { + logger.debug( + '''Propagated «FOR p : propagationPath SEPARATOR ' -> '»«p»«ENDFOR» -> {«FOR changeInPropagation : propagationResultChanges SEPARATOR ", "»« + changeInPropagation.affectedEObjectsMetamodelDescriptors»«ENDFOR»}''' + ) + } + if (logger.isTraceEnabled) { + logger.trace(''' + Result changes: + «FOR result : propagationResultChanges» + «result.affectedEObjectsMetamodelDescriptors»: «result» + «ENDFOR» + ''') + } + + //TODO if sourcechange instanceof TransactionalChange do the following: + //sourceChange.userInteractions = userInteractions + + val resultingChanges = new ArrayList() + if (!propagationResultChanges.isNullOrEmpty) { + val propagatedChange = new PropagatedChange(sourceChange, + VitruviusChangeFactory.instance.createCompositeChange(propagationResultChanges)) + resultingChanges += propagatedChange + } + + if (changePropagationMode != ChangePropagationMode.SINGLE_STEP) { + resultingChanges += + propagationResultChanges.filter[it.containsConcreteChange].propagateTransitiveChanges + } + return resultingChanges + } + def private List propagateSingleChange(TransactionalChange change) { checkState(!change.affectedEObjects.isNullOrEmpty, "There are no objects affected by this change:%s%s", System.lineSeparator, change) @@ -163,12 +229,33 @@ class ChangePropagator { return nextPropagations.mapFixed[propagateChanges()].flatten } + def private propagateNonAtomicChangeForChangePropagationSpecification( + VitruviusChange change, + ChangePropagationSpecification propagationSpecification + ) { + //TODO check if this passt so + val transitiveChanges = modelRepository.recordChanges [ + propagationSpecification.propagateNonAtomicChange(change, modelRepository.correspondenceModel, + modelRepository) + //for (eChange : change.EChanges) { + // propagationSpecification.propagateChange(eChange, modelRepository.correspondenceModel, + // modelRepository) + //} + ] + + // Store modification information + changedResources += transitiveChanges.flatMap[it.affectedEObjects].map[eResource].filterNull + + return transitiveChanges + } + def private propagateChangeForChangePropagationSpecification( TransactionalChange change, ChangePropagationSpecification propagationSpecification ) { val transitiveChanges = modelRepository.recordChanges [ for (eChange : change.EChanges) { + // TODO wouldn't it be good to call .doesHandleChange(), here? Or do we assume propagateChange to ignore EChanges it 'doesnt handle'? --> should be documented in ChangePropagationSpecification. propagationSpecification.propagateChange(eChange, modelRepository.correspondenceModel, modelRepository) } From 1ed578b77c46fd7e248087e8f8ad45ee0ab0f774 Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Sun, 18 May 2025 15:12:03 +0200 Subject: [PATCH 3/6] clean up --- .../propagation/impl/ChangePropagator.xtend | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend index 41093fb4..7c3ad6e1 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend @@ -87,10 +87,10 @@ class ChangePropagator { val List userInteractions = new ArrayList def private propagateChanges() { - //TODO dunno if this is good.. - // first, the whole vitruviuschange is propagated to CPSs that can handle it. - // Then, the other CPSs handle the change in their way (the non-atomic-enabled CPSs are called, but perform noops, currently, just like some other CPSs where 'doesHandleChange' returns false, - // which is not checked, here (noop is assumed). TODO see unten + /* First, the whole vitruviuschange is propagated to CPSs that can handle it. + * Then, the other CPSs handle the change in their way (the non-atomic-enabled CPSs are called, but perform noops, + * currently, just like some other CPSs where 'doesHandleChange' returns false, which is not checked, here (noop is assumed). TODO see unten + */ val result = propagateNonAtomicChange() result += sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] @@ -101,13 +101,10 @@ class ChangePropagator { } def private List propagateNonAtomicChange() { - //TODO maybr deactivate?? val userInteractorChange = installUserInteractorForChange(sourceChange) changePropagationProvider.forEach[registerObserver(this)] userInteractor.registerUserInputListener(this) - //TODO implement calling changepropspec respective function - //TODO do the other crap done in propagateSingleChange, too... - // TODO this for testin purposes only, only the weiterleiting part for testing! + val propagationResultChanges = try { sourceChange.affectedEObjectsMetamodelDescriptors.flatMap [ // we only want ChangePropSpecs that handle non-atomic changes @@ -115,18 +112,14 @@ class ChangePropagator { forEach[it.userInteractor = outer.userInteractor] ] ].toSet.flatMapFixed [ - //TODO change deez to propagateNonAtomicChangeForChangePropagationSpecification(sourceChange, it) - //propagateChangeForChangePropagationSpecification(change, it) ] } finally { - //TODO maybr deactivate?? userInteractor.deregisterUserInputListener(this) changePropagationProvider.forEach[deregisterObserver(this)] userInteractorChange.close() } - //TODO copied: müsste passen so if (logger.isDebugEnabled) { logger.debug( '''Propagated «FOR p : propagationPath SEPARATOR ' -> '»«p»«ENDFOR» -> {«FOR changeInPropagation : propagationResultChanges SEPARATOR ", "»« @@ -142,9 +135,6 @@ class ChangePropagator { ''') } - //TODO if sourcechange instanceof TransactionalChange do the following: - //sourceChange.userInteractions = userInteractions - val resultingChanges = new ArrayList() if (!propagationResultChanges.isNullOrEmpty) { val propagatedChange = new PropagatedChange(sourceChange, @@ -233,14 +223,9 @@ class ChangePropagator { VitruviusChange change, ChangePropagationSpecification propagationSpecification ) { - //TODO check if this passt so val transitiveChanges = modelRepository.recordChanges [ propagationSpecification.propagateNonAtomicChange(change, modelRepository.correspondenceModel, modelRepository) - //for (eChange : change.EChanges) { - // propagationSpecification.propagateChange(eChange, modelRepository.correspondenceModel, - // modelRepository) - //} ] // Store modification information @@ -255,7 +240,6 @@ class ChangePropagator { ) { val transitiveChanges = modelRepository.recordChanges [ for (eChange : change.EChanges) { - // TODO wouldn't it be good to call .doesHandleChange(), here? Or do we assume propagateChange to ignore EChanges it 'doesnt handle'? --> should be documented in ChangePropagationSpecification. propagationSpecification.propagateChange(eChange, modelRepository.correspondenceModel, modelRepository) } From dbb61868d89c3b998faf17af8cbd4ee4aafd7afc Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Wed, 21 May 2025 10:59:32 +0200 Subject: [PATCH 4/6] remove todo --- .../change/propagation/ChangePropagationSpecification.xtend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend index 97c6717f..151b6e09 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend @@ -88,7 +88,7 @@ interface ChangePropagationSpecification extends ChangePropagationObservable { * for the elements changed by the given EChange in order to reflect the changes in the * target model. * - * Else, this does nothing. TODO maybe let it delegate to {@link #propagateChange}? + * Else, this does nothing. * * @param change the non-atomic change (i.e. change sequence) which shall be propagated. Should affect only elements in * an instance of a source metamodel of this specification (see From 85a2f922c1c2a88e774f6b9ab11c600a9111ce77 Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Wed, 21 May 2025 11:03:14 +0200 Subject: [PATCH 5/6] remove todo --- .../vitruv/change/propagation/impl/ChangePropagator.xtend | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend index 7c3ad6e1..68df4682 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/impl/ChangePropagator.xtend @@ -88,13 +88,12 @@ class ChangePropagator { def private propagateChanges() { /* First, the whole vitruviuschange is propagated to CPSs that can handle it. - * Then, the other CPSs handle the change in their way (the non-atomic-enabled CPSs are called, but perform noops, - * currently, just like some other CPSs where 'doesHandleChange' returns false, which is not checked, here (noop is assumed). TODO see unten + * Then, the other CPSs handle the change in their way. + (the non-atomic-enabled CPSs are called, too, but perform noops) */ val result = propagateNonAtomicChange() result += sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] - //val result = sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)] handleObjectsWithoutResource() changedResources.forEach[modified = true] return result From 43173fa49d84495d3c2287d4b322dbea92f195f9 Mon Sep 17 00:00:00 2001 From: Robin Schulz Date: Wed, 21 May 2025 11:05:47 +0200 Subject: [PATCH 6/6] remove todo --- .../change/propagation/ChangePropagationSpecification.xtend | 1 - 1 file changed, 1 deletion(-) diff --git a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend index 151b6e09..f4effed9 100644 --- a/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend +++ b/propagation/src/main/xtend/tools/vitruv/change/propagation/ChangePropagationSpecification.xtend @@ -45,7 +45,6 @@ interface ChangePropagationSpecification extends ChangePropagationObservable { /** * Returns whether this ChangePropagationSpecification handles the given change, i.e., * whether {@link #propagateChange} will perform changes when applied to that change. - * TODO ist default-impl false hier ne gute Idee? * * @param change the atomic change for which to check whether this specification reacts * to it. Must not be null.