Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ target/
.flattened-pom.xml
dependency-reduced-pom.xml

# Idea
.idea/

# Eclipse
META-INF
build.properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -52,7 +53,7 @@ interface ChangePropagationSpecification extends ChangePropagationObservable {
* @return <code>true</code> if {@link #propagateChange} will perform modifications in response to the
* given change, <code>false</code> otherwise
*/
def boolean doesHandleChange(EChange<EObject> change, EditableCorrespondenceModelView<Correspondence> correspondenceModel)
def boolean doesHandleChange(EChange<EObject> change, EditableCorrespondenceModelView<Correspondence> correspondenceModel) { false }

/**
* Performs modifications in target models identified by accessing the given <code>CorrespondenceModel</code>
Expand All @@ -68,4 +69,35 @@ interface ChangePropagationSpecification extends ChangePropagationObservable {
* Must not be <code>null</code>.
*/
def void propagateChange(EChange<EObject> change, EditableCorrespondenceModelView<Correspondence> correspondenceModel, ResourceAccess resourceAccess)


/**
* Returns whether this <code>ChangePropagationSpecification</code> handles the given change, i.e.,
* whether {@link #propagateChange} will perform changes when applied to that change.
*
* @return <code>true</code> if {@link #propagateNonAtomicChange} will perform modifications in response to the
* given change, <code>false</code> otherwise.
*/
def boolean doesHandleNonAtomicChanges() { false }

/**
* If this <code>ChangePropagationSpecification</code> handles non-atomic changes (change sequences),
* see {@link #doesHandleNonAtomicChanges }, this
* performs modifications in target models identified by accessing the given <code>CorrespondenceModel</code>
* for the elements changed by the given <code>EChange</code> in order to reflect the changes in the
* target model.
*
* 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
* {@link #getSourceMetamodelDescriptor}). Must not be <code>null</code>.
* @param correspondenceModel the correspondence model to retrieve information about the target
* model from. Must not be <code>null</code>.
* @param resourceAccess an object for resource access, in particular to create new model files.
* Must not be <code>null</code>.
*/
def void propagateNonAtomicChange(VitruviusChange<EObject> change, EditableCorrespondenceModelView<Correspondence> correspondenceModel, ResourceAccess resourceAccess) {
// noop
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,67 @@ class ChangePropagator {
val List<UserInteractionBase> userInteractions = new ArrayList

def private propagateChanges() {
val result = sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)]
/* 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, too, but perform noops)
*/
val result = propagateNonAtomicChange()
result += sourceChange.transactionalChangeSequence.flatMapFixed[propagateSingleChange(it)]

handleObjectsWithoutResource()
changedResources.forEach[modified = true]
return result
}

def private List<PropagatedChange> propagateNonAtomicChange() {
val userInteractorChange = installUserInteractorForChange(sourceChange)
changePropagationProvider.forEach[registerObserver(this)]
userInteractor.registerUserInputListener(this)

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 [
propagateNonAtomicChangeForChangePropagationSpecification(sourceChange, it)
]
} finally {
userInteractor.deregisterUserInputListener(this)
changePropagationProvider.forEach[deregisterObserver(this)]
userInteractorChange.close()
}

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»
''')
}

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<PropagatedChange> propagateSingleChange(TransactionalChange<EObject> change) {
checkState(!change.affectedEObjects.isNullOrEmpty, "There are no objects affected by this change:%s%s",
System.lineSeparator, change)
Expand Down Expand Up @@ -163,6 +218,21 @@ class ChangePropagator {
return nextPropagations.mapFixed[propagateChanges()].flatten
}

def private propagateNonAtomicChangeForChangePropagationSpecification(
VitruviusChange<EObject> change,
ChangePropagationSpecification propagationSpecification
) {
val transitiveChanges = modelRepository.recordChanges [
propagationSpecification.propagateNonAtomicChange(change, modelRepository.correspondenceModel,
modelRepository)
]

// Store modification information
changedResources += transitiveChanges.flatMap[it.affectedEObjects].map[eResource].filterNull

return transitiveChanges
}

def private propagateChangeForChangePropagationSpecification(
TransactionalChange<EObject> change,
ChangePropagationSpecification propagationSpecification
Expand Down
Loading