Skip to content

Commit

Permalink
preserve UUIDs in EChangeResolverAndApplicator
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Wittler committed Nov 4, 2022
1 parent 259a853 commit bfae7d7
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 129 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package tools.vitruv.change.atomic

import org.eclipse.emf.ecore.EObject
import tools.vitruv.change.atomic.eobject.CreateEObject
import tools.vitruv.change.atomic.eobject.EObjectAddedEChange
import tools.vitruv.change.atomic.eobject.EObjectSubtractedEChange
import tools.vitruv.change.atomic.eobject.EObjectExistenceEChange
import tools.vitruv.change.atomic.eobject.EObjectSubtractedEChange
import tools.vitruv.change.atomic.feature.FeatureEChange
import org.eclipse.emf.ecore.EObject
import static com.google.common.base.Preconditions.checkArgument
import static com.google.common.base.Preconditions.checkState
import tools.vitruv.change.atomic.id.IdResolver
import tools.vitruv.change.atomic.uuid.UuidResolver
import tools.vitruv.change.atomic.eobject.DeleteEObject
import tools.vitruv.change.atomic.eobject.CreateEObject

import static com.google.common.base.Preconditions.checkArgument
import static com.google.common.base.Preconditions.checkState

/**
* Provides logic for initializing the IDs within changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.util.EcoreUtil
import tools.vitruv.change.atomic.EChange
import tools.vitruv.change.atomic.command.ApplyEChangeSwitch
import tools.vitruv.change.atomic.eobject.EObjectExistenceEChange
import tools.vitruv.change.atomic.feature.FeatureEChange
import tools.vitruv.change.atomic.feature.reference.SubtractiveReferenceEChange
import tools.vitruv.change.atomic.feature.reference.UpdateReferenceEChange
import tools.vitruv.change.atomic.root.InsertRootEObject
import tools.vitruv.change.atomic.root.RemoveRootEObject
import tools.vitruv.change.atomic.eobject.CreateEObject
import tools.vitruv.change.atomic.eobject.DeleteEObject
import tools.vitruv.change.atomic.eobject.EObjectAddedEChange
import tools.vitruv.change.atomic.eobject.EObjectSubtractedEChange
import tools.vitruv.change.atomic.uuid.UuidResolver

import static com.google.common.base.Preconditions.checkArgument
Expand All @@ -25,78 +23,57 @@ class EChangeResolverAndApplicator {
EChangeUnresolver.unresolve(copy)
return copy
}

static def EChange resolveBefore(EChange eChange, UuidResolver idResolver) {
return resolveCopy(eChange, idResolver)
}

static def void applyForward(EChange eChange, UuidResolver idResolver) {
executeUpdatingIds(eChange, idResolver, true)
static def EChange resolveBefore(EChange eChange, UuidResolver uuidResolver) {
return resolveCopy(eChange, uuidResolver)
}

static def void applyBackward(EChange eChange, UuidResolver idResolver) {
executeUpdatingIds(eChange, idResolver, false)
static def void applyForward(EChange eChange, UuidResolver uuidResolver) {
executeUpdatingIds(eChange, uuidResolver, true)
}

static def void applyBackward(EChange eChange) {
ApplyEChangeSwitch.applyEChange(eChange, false)
static def void applyBackward(EChange eChange, UuidResolver uuidResolver) {
executeUpdatingIds(eChange, uuidResolver, false)
}

static def void executeUpdatingIds(EChange eChange, UuidResolver idResolver, boolean forward) {
val affectedObject = eChange.affectedEObject
val affectedId = idResolver.getUuid(affectedObject)
val oldObject = eChange.oldContainedEObject

static def void executeUpdatingIds(EChange eChange, UuidResolver uuidResolver, boolean forward) {
ApplyEChangeSwitch.applyEChange(eChange, forward)
if (eChange.isContainmentChange || affectedId != idResolver.getUuid(affectedObject)) {
affectedObject.updateIds(idResolver)
}
if (oldObject !== null) {
oldObject.updateIds(idResolver)
if (forward) {
switch (eChange) {
CreateEObject<?>:
uuidResolver.registerEObject(eChange.affectedEObjectID, eChange.affectedEObject)
EObjectAddedEChange<?>:
if (eChange.newValue !== null) {
uuidResolver.registerEObject(eChange.newValueID, eChange.newValue)
}
}
} else {
switch (eChange) {
DeleteEObject<?>:
uuidResolver.registerEObject(eChange.affectedEObjectID, eChange.affectedEObject)
EObjectSubtractedEChange<?>:
if (eChange.oldValue !== null) {
uuidResolver.registerEObject(eChange.oldValueID, eChange.oldValue)
}
}
}
}

private static def boolean isContainmentChange(EChange eChange) {
if (eChange instanceof UpdateReferenceEChange) {
return eChange.containment
}
return false
}

private static def getAffectedEObject(EChange eChange) {
switch (eChange) {
FeatureEChange<?, ?>: eChange.affectedEObject
EObjectExistenceEChange<?>: eChange.affectedEObject
InsertRootEObject<?>: eChange.newValue
RemoveRootEObject<?>: eChange.oldValue
}
}

private static def EObject getOldContainedEObject(EChange eChange) {
switch (eChange) {
SubtractiveReferenceEChange<?, ?>: if (eChange.affectedFeature.containment) eChange.oldValue
}
}

private static def void updateIds(EObject object, UuidResolver idResolver) {
idResolver.getUuid(object)
object.eContents.forEach[updateIds(idResolver)]
}

/**
* Creates a copy of the change and resolves it using the given {@link idResolver}.
* Creates a copy of the change and resolves it using the given {@link UuidResolver}.
*
* @param change The {@link EChange} which shall be resolved.
* @param idResolver The {@link idResolver} to resolve {@link EObject}s from
* @param uuidResolver The {@link UuidResolver} to resolve {@link EObject}s from
* @return Returns a resolved copy of the change. If the copy could not be resolved
* an {@link IllegalStateException} is thrown
* @throws IllegalArgumentException The change is already resolved.
* @throws IllegalStateException The change cannot be resolved.
*/
def private static EChange resolveCopy(EChange change, UuidResolver idResolver) {
def private static EChange resolveCopy(EChange change, UuidResolver uuidResolver) {
checkArgument(!change.isResolved, "change must not be resolved when trying to resolve")
var EChange copy = EcoreUtil.copy(change)
new AtomicEChangeResolver(idResolver).resolve(copy)
new AtomicEChangeResolver(uuidResolver).resolve(copy)
return copy
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import static org.eclipse.emf.ecore.resource.ResourceSet.*

import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
import static extension tools.vitruv.change.atomic.EChangeUtil.*
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.applyBackward
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.applyForward

/**
* Records changes to model elements as a {@link TransactionalChange}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ abstract class EChangeTest {

def protected void applyBackward(List<EChange> changes) {
assertIsResolved(changes)
changes.reverseView.forEach[applyBackward]
changes.reverseView.forEach[applyBackward(uuidResolver)]
}

def protected void applyBackward(EChange change) {
assertIsResolved(change)
change.assertApplyForward
}

def protected void applyForward(List<EChange> changes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ package tools.vitruv.change.atomic.feature.attribute

import allElementTypes.NonRoot
import allElementTypes.Root
import tools.vitruv.change.atomic.feature.attribute.InsertEAttributeValue

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertFalse

import static org.junit.jupiter.api.Assertions.assertEquals
import static org.junit.jupiter.api.Assertions.assertNull
import static org.junit.jupiter.api.Assertions.assertThrows
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.*
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*

/**
* Test class for the concrete {@link InsertEAttributeValue} EChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ package tools.vitruv.change.atomic.feature.attribute

import allElementTypes.NonRoot
import allElementTypes.Root
import tools.vitruv.change.atomic.feature.attribute.RemoveEAttributeValue

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertFalse

import static org.junit.jupiter.api.Assertions.assertEquals
import static org.junit.jupiter.api.Assertions.assertNull
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.*
import static org.junit.jupiter.api.Assertions.assertThrows
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.*

/**
* Test class for the concrete {@link RemoveEAttributeValue} EChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import allElementTypes.AllElementTypesPackage
import allElementTypes.NonRoot
import allElementTypes.Root
import org.eclipse.emf.ecore.EAttribute
import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute
import tools.vitruv.change.atomic.EChangeTest

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertFalse
import tools.vitruv.change.atomic.EChangeTest

import static org.junit.jupiter.api.Assertions.assertEquals
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.*
import static org.junit.jupiter.api.Assertions.assertThrows
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.*

/**
* Test class for the concrete {@link ReplaceSingleValuedEAttribute} EChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ import allElementTypes.NonRoot
import allElementTypes.Root
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.ecore.EReference
import tools.vitruv.change.atomic.feature.reference.InsertEReference

import org.junit.jupiter.api.Test
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertFalse

import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.assertEquals
import static org.junit.jupiter.api.Assertions.assertSame
import static org.junit.jupiter.api.Assertions.assertFalse
import static org.junit.jupiter.api.Assertions.assertNotSame
import static org.junit.jupiter.api.Assertions.assertSame
import static org.junit.jupiter.api.Assertions.assertThrows
import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.matchers.ModelMatchers.equalsDeeply
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*

/**
* Test class for the concrete {@link InsertEReferenceValue} EChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,16 @@ import allElementTypes.Root
import org.eclipse.emf.common.util.EList
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import tools.vitruv.change.atomic.feature.reference.RemoveEReference

import org.junit.jupiter.api.Test
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertFalse

import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.assertEquals
import static org.junit.jupiter.api.Assertions.assertNull
import static org.junit.jupiter.api.Assertions.assertSame
import static org.junit.jupiter.api.Assertions.assertFalse
import static org.junit.jupiter.api.Assertions.assertNotSame
import static org.junit.jupiter.api.Assertions.assertSame
import static org.junit.jupiter.api.Assertions.assertThrows
import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.matchers.ModelMatchers.equalsDeeply
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*

/**
* Test class for the concrete {@link RemoveEReference} EChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class EChangeAssertHelper {
def void assertApplyBackward(EChange change) {
assertNotNull(change)
assertTrue(change.isResolved)
change.applyBackward
change.applyBackward(uuidResolver)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
package tools.vitruv.change.composite

import allElementTypes.Root
import java.nio.file.Path
import java.util.List

import tools.vitruv.change.atomic.EChange
import java.util.function.Consumer
import org.eclipse.emf.common.notify.Notifier
import org.eclipse.emf.ecore.resource.ResourceSet
import org.junit.jupiter.api.BeforeEach
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
import org.eclipse.emf.ecore.util.EcoreUtil
import org.junit.jupiter.api.AfterEach
import static org.junit.jupiter.api.Assertions.assertEquals
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.aet
import org.eclipse.emf.common.notify.Notifier
import java.util.function.Consumer
import static com.google.common.base.Preconditions.checkState
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.^extension.ExtendWith
import tools.vitruv.testutils.TestProjectManager
import tools.vitruv.testutils.TestProject
import java.nio.file.Path
import tools.vitruv.testutils.RegisterMetamodelsInStandalone
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil.withGlobalFactories
import tools.vitruv.change.composite.recording.ChangeRecorder
import tools.vitruv.change.atomic.EChange
import tools.vitruv.change.atomic.uuid.UuidResolver
import tools.vitruv.change.composite.description.TransactionalChange
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.common.util.URIUtil.createFileURI
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil.loadOrCreateResource
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*
import org.eclipse.emf.ecore.util.EcoreUtil
import static tools.vitruv.testutils.matchers.ModelMatchers.equalsDeeply
import tools.vitruv.change.composite.recording.ChangeRecorder
import tools.vitruv.testutils.RegisterMetamodelsInStandalone
import tools.vitruv.testutils.TestProject
import tools.vitruv.testutils.TestProjectManager

import static com.google.common.base.Preconditions.checkState
import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.assertTrue
import static org.junit.jupiter.api.Assertions.assertEquals
import static org.junit.jupiter.api.Assertions.assertNotNull
import static org.junit.jupiter.api.Assertions.assertTrue
import static tools.vitruv.testutils.matchers.ModelMatchers.equalsDeeply
import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.aet

import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.common.util.URIUtil.createFileURI
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil.loadOrCreateResource
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil.withGlobalFactories
import static extension edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceUtil.getFirstRootEObject
import tools.vitruv.change.atomic.id.IdResolver
import tools.vitruv.change.atomic.uuid.UuidResolver
import static extension tools.vitruv.change.atomic.resolve.EChangeResolverAndApplicator.*

@ExtendWith(TestProjectManager, RegisterMetamodelsInStandalone)
abstract class ChangeDescription2ChangeTransformationTest {
Expand Down Expand Up @@ -109,11 +109,12 @@ abstract class ChangeDescription2ChangeTransformationTest {
// be applied to a different state
val monitoredChanges = change.EChanges
monitoredChanges.reverseView.forEach[monitoredChange|
monitoredChange.applyBackward
monitoredChange.applyBackward(uuidResolver)
]
uuidResolver.endTransaction
val comparisonResourceSet = new ResourceSetImpl().withGlobalFactories()
val comparisonIdResolver = UuidResolver.create(comparisonResourceSet)
resourceSet.copyTo(comparisonResourceSet)
val comparisonIdResolver = uuidResolver.resolveIn(comparisonResourceSet)
monitoredChanges.map[
applyForward(uuidResolver)
EcoreUtil.copy(it)
Expand Down Expand Up @@ -156,5 +157,4 @@ abstract class ChangeDescription2ChangeTransformationTest {
)
return changes
}

}

0 comments on commit bfae7d7

Please sign in to comment.