diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c29156dfd..93cc57cc67 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: release: types: [created] schedule: - - cron: '0 3 * * *' # run nightly at 3:00 am + - cron: '5 3 * * *' # run nightly at 3:05 am workflow_call: jobs: @@ -18,7 +18,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache uses: actions/cache@v3 with: diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index fe2e1f9c53..cd238cd88e 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout DSLs - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: dsls repository: vitruv-tools/Vitruv-DSLs @@ -72,7 +72,7 @@ jobs: name: dsls path: dsls - name: Checkout Case Studies - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: casestudies repository: vitruv-tools/Vitruv-CaseStudies @@ -110,52 +110,3 @@ jobs: -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog env: MAVEN_OPTS: -Djansi.force=true - - validate_tool_adapters: - needs: [validate_framework] - name: Tool Adapters - runs-on: ubuntu-latest - steps: - - name: Download Framework Artifact - uses: actions/download-artifact@v3 - with: - name: framework - path: framework - - name: Checkout Tool Adapters - uses: actions/checkout@v3 - with: - path: tool_adapters - repository: vitruv-tools/Vitruv-Tool-Adapters - ref: main - fetch-depth: 0 - - name: Checkout Matching Tool Adapters Branch - run: | - cd tool_adapters - git checkout -B ${{ github.head_ref }} origin/${{ github.head_ref }} || true - - name: Cache - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml', '**/MANIFEST.MF') }} - restore-keys: ${{ runner.os }}-m2 - - name: Set up JDK - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: 17 - - name: Build and Verify Tools Adapters - uses: coactions/setup-xvfb@v1 - with: - working-directory: ./tool_adapters - run: > - ./mvnw -B -U package -Dmaven.test.skip=true - -Dvitruv.framework.url=file:///${{ github.workspace }}/framework - -Dstyle.color=always - -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn - -Dorg.slf4j.simpleLogger.log.org.eclipse.tycho.core.resolver.DefaultTychoResolver=warn - -Dorg.slf4j.simpleLogger.log.org.eclipse.tycho.osgi.configuration.MavenContextConfigurator=warn - -Dorg.slf4j.simpleLogger.log.org.eclipse.sisu.equinox.launching.internal.DefaultEquinoxLauncher=warn - -Dorg.slf4j.simpleLogger.log.org.eclipse.xtext.maven.XtextGenerateMojo=warn - -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog - env: - MAVEN_OPTS: -Djansi.force=true diff --git a/README.md b/README.md index 55b3d62e55..3cfe44de35 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,23 @@ -# Vitruv V-SUM +# Vitruv [![GitHub Action CI](https://github.com/vitruv-tools/Vitruv/actions/workflows/ci.yml/badge.svg)](https://github.com/vitruv-tools/Vitruv/actions/workflows/ci.yml) [![Latest Release](https://img.shields.io/github/release/vitruv-tools/Vitruv.svg)](https://github.com/vitruv-tools/Vitruv/releases/latest) [![Issues](https://img.shields.io/github/issues/vitruv-tools/Vitruv.svg)](https://github.com/vitruv-tools/Vitruv/issues) [![License](https://img.shields.io/github/license/vitruv-tools/Vitruv.svg)](https://raw.githubusercontent.com/vitruv-tools/Vitruv/main/LICENSE) -[Vitruvius](https://vitruv.tools) is a framework for view-based software development. It assumes different models to be used for describing a software system, -which are automatically kept consistent by the framework and its applications. For general information on Vitruvius, see our [GitHub Organisation](https://github.com/vitruv-tools) and our [Wiki](https://github.com/vitruv-tools/.github/wiki). +[Vitruvius](https://vitruv.tools) is a framework for view-based (software) development. +It assumes different models to be used for describing a system, which are automatically kept consistent by the framework executing (semi-)automated rules that preserve consistency. +These models are modified only via views, which are projections from the underlying models. +For general information on Vitruvius, see our [GitHub Organisation](https://github.com/vitruv-tools) and our [Wiki](https://github.com/vitruv-tools/.github/wiki). -This project contains the central definition of a V-SUM (Virtual Single Underlying Model) containing development artifacts to be kept consistent and to be accessed and modified via views. +This project contains the central Vitruvius framework, providing the definition of a V-SUM (Virtual Single Underlying Model) containing development artifacts to be kept consistent and to be accessed and modified via views. +In the implementation, a V-SUM is called `VirtualModel`, which is instantiated with a set of `ChangePropagationSpecifications` (no matter whether they are developed with the [Vitruv-DSLs](https://github.com/vitruv-tools/Vitruv-DSLs) or just as an implementation of the interface defined in the [Vitruv-Change](https://github.com/vitruv-tools/Vitruv-Change) repository). +The `VirtualModel` then provides functionality to derive and modify views and to propagate the changes in these views back to the `VirtualModel`, which then executes the `ChangePropagationSpecifications` to preserve consistency. ## Installation -Vitruvius can be installed in Eclipse via the [nightly update site](https://vitruv.tools/updatesite/nightly). A wiki page provides [detailed instructions for using or extending Vitruvius](https://github.com/vitruv-tools/.github/wiki/Getting-Started). +Vitruvius can be installed in Eclipse via the [nightly update site](https://vitruv.tools/updatesite/nightly). A wiki page provides [detailed instructions for using or extending Vitruvius or parts of it](https://github.com/vitruv-tools/.github/wiki/Getting-Started). -## Project Development +## Framework-internal Dependencies -Vitruvius is realized as Eclipse plug-ins and depends on the following Eclipse tools: -- Eclipse Modeling Framework (EMF) _as the modelling environment_ -- Xtend _for code_ +This project depends on the following other projects from the Vitruvius framework: +- [Vitruv-Change](https://github.com/vitruv-tools/Vitruv-Change) diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/AbstractViewType.xtend b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/AbstractViewType.xtend index 07e2e4cf92..7eea1879ff 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/AbstractViewType.xtend +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/AbstractViewType.xtend @@ -5,7 +5,7 @@ import tools.vitruv.framework.views.ViewSelector import static com.google.common.base.Preconditions.checkArgument -abstract package class AbstractViewType implements ViewCreatingViewType { +abstract package class AbstractViewType implements ViewCreatingViewType { @Accessors(PUBLIC_GETTER) val String name diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/BasicView.xtend b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/BasicView.xtend index 7636ed0358..8fef150386 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/BasicView.xtend +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/BasicView.xtend @@ -9,6 +9,8 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.emf.ecore.resource.ResourceSet import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl import org.eclipse.xtend.lib.annotations.Accessors +import tools.vitruv.change.atomic.hid.HierarchicalId +import tools.vitruv.change.atomic.uuid.Uuid import tools.vitruv.change.composite.description.PropagatedChange import tools.vitruv.change.composite.description.VitruviusChange import tools.vitruv.change.composite.propagation.ChangePropagationListener @@ -25,7 +27,7 @@ package class BasicView implements ModifiableView, ChangePropagationListener { @Accessors(PUBLIC_GETTER, PROTECTED_SETTER) var ViewSelection selection @Accessors(PUBLIC_GETTER, PROTECTED_SETTER) - var ViewCreatingViewType viewType + var ViewCreatingViewType viewType @Accessors(PUBLIC_GETTER, PROTECTED_SETTER) var ChangeableViewSource viewSource @Accessors(PROTECTED_GETTER) @@ -35,7 +37,7 @@ package class BasicView implements ModifiableView, ChangePropagationListener { boolean viewChanged boolean closed - protected new(ViewCreatingViewType viewType, ChangeableViewSource viewSource, + protected new(ViewCreatingViewType viewType, ChangeableViewSource viewSource, ViewSelection selection) { checkArgument(viewType !== null, "view type must not be null") checkArgument(viewSource !== null, "view selection must not be null") @@ -88,7 +90,7 @@ package class BasicView implements ModifiableView, ChangePropagationListener { modelChanged = true } - override startedChangePropagation(VitruviusChange changeToPropagate) { + override startedChangePropagation(VitruviusChange changeToPropagate) { // do nothing } diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeDerivingView.xtend b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeDerivingView.xtend index d6c5de859d..caeb8e469a 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeDerivingView.xtend +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeDerivingView.xtend @@ -7,12 +7,12 @@ import org.eclipse.emf.ecore.resource.Resource import org.eclipse.emf.ecore.resource.ResourceSet import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl import org.eclipse.xtend.lib.annotations.Delegate +import tools.vitruv.change.atomic.hid.HierarchicalId import tools.vitruv.change.composite.description.VitruviusChange import tools.vitruv.change.composite.description.VitruviusChangeFactory import tools.vitruv.framework.views.CommittableView import tools.vitruv.framework.views.View import tools.vitruv.change.changederivation.StateBasedChangeResolutionStrategy - import static com.google.common.base.Preconditions.checkArgument import static com.google.common.base.Preconditions.checkState @@ -75,7 +75,7 @@ class ChangeDerivingView implements ModifiableView, CommittableView { view.close } - private def VitruviusChange generateChange(Resource newState, Resource referenceState) { + private def VitruviusChange generateChange(Resource newState, Resource referenceState) { if (referenceState === null) { return changeResolutionStrategy.getChangeSequenceForCreated(newState) } else if (newState === null) { diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeRecordingView.xtend b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeRecordingView.xtend index 6366e715b7..8405187a41 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeRecordingView.xtend +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ChangeRecordingView.xtend @@ -1,10 +1,7 @@ package tools.vitruv.framework.views.impl -import java.util.List import org.eclipse.xtend.lib.annotations.Delegate -import tools.vitruv.change.atomic.EChange -import tools.vitruv.change.atomic.EChangeIdManager -import tools.vitruv.change.atomic.id.IdResolver +import tools.vitruv.change.composite.description.VitruviusChangeResolver import tools.vitruv.change.composite.recording.ChangeRecorder import tools.vitruv.framework.views.CommittableView import tools.vitruv.framework.views.View @@ -13,9 +10,6 @@ import tools.vitruv.change.changederivation.StateBasedChangeResolutionStrategy import static com.google.common.base.Preconditions.checkArgument import static com.google.common.base.Preconditions.checkState -import static extension tools.vitruv.change.atomic.resolve.EChangeIdResolverAndApplicator.applyBackward -import static extension tools.vitruv.change.atomic.resolve.EChangeIdResolverAndApplicator.applyForward - /** * A {@link View} that records changes to its resources and allows to propagate them * back to the underlying models using the {@link #commitChanges} method. @@ -43,21 +37,13 @@ class ChangeRecordingView implements ModifiableView, CommittableView { changeRecorder.addToRecording(view.viewResourceSet) changeRecorder.beginRecording() } - def private void assignIds(List changes) { - val idResolver = IdResolver.create(view.viewResourceSet) - val idManager = new EChangeIdManager(idResolver) - changes.toList.reverseView.forEach[applyBackward] - changes.forEach[ - idManager.setOrGenerateIds(it) - it.applyForward(idResolver) - ] - } override commitChanges() { view.checkNotClosed() val recordedChange = changeRecorder.endRecording() - assignIds(recordedChange.EChanges) - view.viewType.commitViewChanges(this, recordedChange) + val changeResolver = VitruviusChangeResolver.forHierarchicalIds(view.viewResourceSet) + val unresolvedChanges = changeResolver.assignIds(recordedChange) + view.viewType.commitViewChanges(this, unresolvedChanges) view.viewChanged = false changeRecorder.beginRecording() } diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/IdentityMappingViewType.java b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/IdentityMappingViewType.java index 4d9d4f10cf..133ef6466f 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/IdentityMappingViewType.java +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/IdentityMappingViewType.java @@ -9,16 +9,18 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceCopier; -import tools.vitruv.change.atomic.EChangeUuidManager; -import tools.vitruv.change.atomic.id.IdResolver; +import tools.vitruv.change.atomic.hid.HierarchicalId; +import tools.vitruv.change.atomic.uuid.Uuid; import tools.vitruv.change.atomic.uuid.UuidResolver; import tools.vitruv.change.changederivation.DeltaBasedResourceUtil; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.change.composite.description.VitruviusChangeResolver; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.View; import tools.vitruv.framework.views.ViewSelection; @@ -30,14 +32,14 @@ * selection mechanism and providing a one-to-one (identity) mapping of elements * within the {@link ViewSource} to a created {@link View}. */ -public class IdentityMappingViewType extends AbstractViewType { +public class IdentityMappingViewType extends AbstractViewType, HierarchicalId> { public IdentityMappingViewType(String name) { super(name); } @Override - public DirectViewElementSelector createSelector(ChangeableViewSource viewSource) { - return new DirectViewElementSelector(this, viewSource, + public DirectViewElementSelector createSelector(ChangeableViewSource viewSource) { + return new DirectViewElementSelector<>(this, viewSource, viewSource.getViewSourceModels().stream().map(resource -> { if (!resource.getContents().isEmpty() && ResourceCopier.requiresFullCopy(resource)) { // Some resources (like UML) can only be copied as a whole, so no option to select @@ -49,7 +51,7 @@ public DirectViewElementSelector createSelector(ChangeableViewSource viewSource) } @Override - public ModifiableView createView(DirectViewElementSelector selector) { + public ModifiableView createView(DirectViewElementSelector selector) { checkArgument(selector.getViewType() == this, "cannot create view with selector for different view type"); return new BasicView(selector.getViewType(), selector.getViewSource(), selector.getSelection()); } @@ -64,16 +66,18 @@ public void updateView(ModifiableView view) { } @Override - public void commitViewChanges(ModifiableView view, VitruviusChange viewChange) { + public void commitViewChanges(ModifiableView view, VitruviusChange viewChange) { ResourceSet viewSourceCopyResourceSet = DeltaBasedResourceUtil.withDeltaFactory(new ResourceSetImpl()); - IdResolver viewSourceCopyIdResolver = IdResolver.create(viewSourceCopyResourceSet); + VitruviusChangeResolver idChangeResolver = VitruviusChangeResolver.forHierarchicalIds(viewSourceCopyResourceSet); + UuidResolver viewSourceCopyUuidResolver = UuidResolver.create(viewSourceCopyResourceSet); + VitruviusChangeResolver uuidChangeResolver = VitruviusChangeResolver.forUuids(viewSourceCopyUuidResolver); Map mapping = createViewResources(view, viewSourceCopyResourceSet); view.getViewSource().getUuidResolver().resolveResources(mapping, viewSourceCopyUuidResolver); - VitruviusChange resolvedChange = viewChange.unresolve().resolveAndApply(viewSourceCopyIdResolver); - EChangeUuidManager.setOrGenerateIds(resolvedChange.getEChanges(), viewSourceCopyUuidResolver); - view.getViewSource().propagateChange(resolvedChange.unresolve()); + VitruviusChange resolvedChange = idChangeResolver.resolveAndApply(viewChange); + VitruviusChange unresolvedChanges = uuidChangeResolver.assignIds(resolvedChange); + view.getViewSource().propagateChange(unresolvedChanges); } private Map createViewResources(ModifiableView view, ResourceSet viewResourceSet) { diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ViewCreatingViewType.java b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ViewCreatingViewType.java index 15604c0043..b11791df43 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ViewCreatingViewType.java +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/impl/ViewCreatingViewType.java @@ -9,9 +9,10 @@ * A specific view type that is able to create and update views. This is not its * public interface but only for internal usage by views and their selectors. * - * @param the type of view selector this view type uses + * @param the type of view selector this view type uses. + * @param the type of Id the changes to commit must have. */ -public interface ViewCreatingViewType extends ViewType { +public interface ViewCreatingViewType extends ViewType { /** * Creates a view for the given {@link ViewSelector}. The selector must have * been created by calling the {@link #createSelector} method of the same @@ -35,11 +36,10 @@ public interface ViewCreatingViewType extends ViewType viewChange); } diff --git a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/selectors/DirectViewElementSelector.xtend b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/selectors/DirectViewElementSelector.xtend index 10d296b48e..50add0b64f 100644 --- a/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/selectors/DirectViewElementSelector.xtend +++ b/bundles/tools.vitruv.framework.views/src/tools/vitruv/framework/views/selectors/DirectViewElementSelector.xtend @@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkState * and view elements (such as selecting types but providing instances in the view), * but a selection is performed on the view elements themselves. */ -class DirectViewElementSelector implements ViewSelector { +class DirectViewElementSelector implements ViewSelector { @Delegate val ModifiableViewSelection viewSelection @@ -28,7 +28,7 @@ class DirectViewElementSelector implements ViewSelector { val ChangeableViewSource viewSource @Accessors(PUBLIC_GETTER) - val ViewCreatingViewType viewType + val ViewCreatingViewType, Id> viewType /** * Creates a new selector based on the given collection of selectable elements @@ -43,7 +43,7 @@ class DirectViewElementSelector implements ViewSelector { * @param selectableElements - the elements to select from to be used by the * {@link ViewType} when creating a view */ - new(ViewCreatingViewType viewType, ChangeableViewSource viewSource, + new(ViewCreatingViewType, Id> viewType, ChangeableViewSource viewSource, Collection selectableElements) { checkArgument(selectableElements !== null, "selectable elements must not be null") checkArgument(viewType !== null, "view type must not be null") diff --git a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/ResourceRepositoryImpl.java b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/ResourceRepositoryImpl.java index b33fcdd8bd..a963b2ae15 100644 --- a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/ResourceRepositoryImpl.java +++ b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/ResourceRepositoryImpl.java @@ -23,10 +23,11 @@ import org.eclipse.emf.ecore.util.EcoreUtil; import edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceSetUtil; -import tools.vitruv.change.atomic.EChangeUuidManager; +import tools.vitruv.change.atomic.uuid.Uuid; import tools.vitruv.change.atomic.uuid.UuidResolver; import tools.vitruv.change.composite.description.TransactionalChange; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.change.composite.description.VitruviusChangeResolver; import tools.vitruv.change.composite.recording.ChangeRecorder; import tools.vitruv.change.correspondence.Correspondence; import tools.vitruv.change.correspondence.model.PersistableCorrespondenceModel; @@ -41,8 +42,9 @@ class ResourceRepositoryImpl implements ModelRepository { private final ResourceSet modelsResourceSet = new ResourceSetImpl(); private final Map modelInstances = new HashMap<>(); private final PersistableCorrespondenceModel correspondenceModel; - private final UuidResolver uuidResolver = UuidResolver.create(modelsResourceSet); + private UuidResolver uuidResolver = UuidResolver.create(modelsResourceSet); private final ChangeRecorder changeRecorder = new ChangeRecorder(modelsResourceSet); + private final VitruviusChangeResolver changeResolver = VitruviusChangeResolver.forUuids(uuidResolver); private final VsumFileSystemLayout fileSystemLayout; @@ -198,7 +200,7 @@ public void saveOrDeleteModels() { } @Override - public Iterable recordChanges(Runnable changeApplicator) { + public Iterable> recordChanges(Runnable changeApplicator) { changeRecorder.beginRecording(); isRecording = true; LOGGER.debug("Start recording virtual model"); @@ -206,14 +208,14 @@ public Iterable recordChanges(Runnable changeApplicator) { LOGGER.debug("End recording virtual model"); isRecording = false; changeRecorder.endRecording(); - TransactionalChange change = changeRecorder.getChange(); - EChangeUuidManager.setOrGenerateIds(change.getEChanges(), uuidResolver); + TransactionalChange change = changeRecorder.getChange(); + changeResolver.assignIds(change); return change.containsConcreteChange() ? List.of(change) : List.of(); } @Override - public VitruviusChange applyChange(VitruviusChange change) { - return change.resolveAndApply(uuidResolver); + public VitruviusChange applyChange(VitruviusChange change) { + return changeResolver.resolveAndApply(change); } @Override @@ -236,6 +238,6 @@ public void close() { changeRecorder.close(); modelsResourceSet.getResources().forEach(Resource::unload); modelsResourceSet.getResources().clear(); - uuidResolver.endTransaction(); + uuidResolver = null; } } \ No newline at end of file diff --git a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/VirtualModelImpl.java b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/VirtualModelImpl.java index e0154c8c04..0f09d7d5a5 100644 --- a/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/VirtualModelImpl.java +++ b/bundles/tools.vitruv.framework.vsum/src/tools/vitruv/framework/vsum/internal/VirtualModelImpl.java @@ -12,6 +12,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; +import tools.vitruv.change.atomic.uuid.Uuid; import tools.vitruv.change.atomic.uuid.UuidResolver; import tools.vitruv.change.composite.description.PropagatedChange; import tools.vitruv.change.composite.description.VitruviusChange; @@ -75,37 +76,36 @@ private synchronized void save() { } @Override - public synchronized List propagateChange(VitruviusChange change) { + public synchronized List propagateChange(VitruviusChange change) { checkNotNull(change, "change to propagate"); checkArgument(change.containsConcreteChange(), "This change contains no concrete change:%s%s", System.lineSeparator(), change); - VitruviusChange unresolvedChange = change.unresolve(); LOGGER.info("Starting change propagation"); - startChangePropagation(unresolvedChange); + startChangePropagation(change); ChangePropagator changePropagator = new ChangePropagator(resourceRepository, changePropagationSpecificationProvider, userInteractor, changePropagationMode); - List result = changePropagator.propagateChange(unresolvedChange); + List result = changePropagator.propagateChange(change); save(); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Propagated changes: " + result); } - finishChangePropagation(unresolvedChange, result); + finishChangePropagation(change, result); LOGGER.info("Finished change propagation"); return result; } - private void startChangePropagation(VitruviusChange change) { + private void startChangePropagation(VitruviusChange change) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Started synchronizing change: " + change); } changePropagationListeners.stream().forEach(it -> it.startedChangePropagation(change)); } - private void finishChangePropagation(VitruviusChange inputChange, Iterable generatedChanges) { + private void finishChangePropagation(VitruviusChange inputChange, Iterable generatedChanges) { changePropagationListeners.stream().forEach(it -> it.finishedChangePropagation(generatedChanges)); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Finished synchronizing change: " + inputChange); diff --git a/bundles/tools.vitruv.testutils.vsum/src/tools/vitruv/testutils/LegacyVitruvApplicationTest.xtend b/bundles/tools.vitruv.testutils.vsum/src/tools/vitruv/testutils/LegacyVitruvApplicationTest.xtend index d8b686fe4a..401c092bd1 100644 --- a/bundles/tools.vitruv.testutils.vsum/src/tools/vitruv/testutils/LegacyVitruvApplicationTest.xtend +++ b/bundles/tools.vitruv.testutils.vsum/src/tools/vitruv/testutils/LegacyVitruvApplicationTest.xtend @@ -10,7 +10,7 @@ import tools.vitruv.testutils.views.TestView import static com.google.common.base.Preconditions.checkArgument -import static extension tools.vitruv.change.atomic.id.ObjectResolutionUtil.getHierarchicUriFragment +import static extension tools.vitruv.change.atomic.hid.ObjectResolutionUtil.getHierarchicUriFragment /** * DO NOT USE THIS CLASS! Use {@link VitruvApplicationTest} instead. diff --git a/releng/tools.vitruv.parent/pom.xml b/releng/tools.vitruv.parent/pom.xml index a9116a6225..8af57e689f 100644 --- a/releng/tools.vitruv.parent/pom.xml +++ b/releng/tools.vitruv.parent/pom.xml @@ -6,7 +6,7 @@ tools.vitruv parent - 2.1.3 + 2.1.4 framework-parent 3.0.1-SNAPSHOT @@ -53,6 +53,22 @@ + + org.apache.maven.plugins + maven-dependency-plugin + 3.6.0 + + + copy-dependencies + + copy-dependencies + + + true + + + + diff --git a/tests/tools.vitruv.framework.views.tests/.classpath b/tests/tools.vitruv.framework.views.tests/.classpath index c348871474..f136b38310 100644 --- a/tests/tools.vitruv.framework.views.tests/.classpath +++ b/tests/tools.vitruv.framework.views.tests/.classpath @@ -8,8 +8,5 @@ - - - diff --git a/tests/tools.vitruv.framework.views.tests/META-INF/MANIFEST.MF b/tests/tools.vitruv.framework.views.tests/META-INF/MANIFEST.MF index c0ee65e382..b654679fce 100644 --- a/tests/tools.vitruv.framework.views.tests/META-INF/MANIFEST.MF +++ b/tests/tools.vitruv.framework.views.tests/META-INF/MANIFEST.MF @@ -20,6 +20,7 @@ Require-Bundle: org.apache.log4j, org.eclipse.uml2.uml, org.hamcrest.core, edu.kit.ipd.sdq.commons.util.java -Bundle-ClassPath: ., lib/byte-buddy-1.12.4.jar, lib/mockito-core-4.2.0.jar, lib/objenesis-3.2.jar +Bundle-ClassPath: ., + target/dependency/mockito-core.jar Bundle-ActivationPolicy: lazy Bundle-Vendor: vitruv.tools diff --git a/tests/tools.vitruv.framework.views.tests/build.properties b/tests/tools.vitruv.framework.views.tests/build.properties index 26fd246c73..5a0ec391e1 100644 --- a/tests/tools.vitruv.framework.views.tests/build.properties +++ b/tests/tools.vitruv.framework.views.tests/build.properties @@ -1,6 +1,6 @@ bin.includes = .,\ META-INF/,\ - lib/ + target/dependency/ source.. = src/,\ xtend-gen output.. = target/classes/ diff --git a/tests/tools.vitruv.framework.views.tests/lib/byte-buddy-1.12.4.jar b/tests/tools.vitruv.framework.views.tests/lib/byte-buddy-1.12.4.jar deleted file mode 100644 index 490efacf4b..0000000000 Binary files a/tests/tools.vitruv.framework.views.tests/lib/byte-buddy-1.12.4.jar and /dev/null differ diff --git a/tests/tools.vitruv.framework.views.tests/lib/mockito-core-4.2.0.jar b/tests/tools.vitruv.framework.views.tests/lib/mockito-core-4.2.0.jar deleted file mode 100644 index 2fedb0f4f2..0000000000 Binary files a/tests/tools.vitruv.framework.views.tests/lib/mockito-core-4.2.0.jar and /dev/null differ diff --git a/tests/tools.vitruv.framework.views.tests/lib/objenesis-3.2.jar b/tests/tools.vitruv.framework.views.tests/lib/objenesis-3.2.jar deleted file mode 100644 index 1888e2ea10..0000000000 Binary files a/tests/tools.vitruv.framework.views.tests/lib/objenesis-3.2.jar and /dev/null differ diff --git a/tests/tools.vitruv.framework.views.tests/pom.xml b/tests/tools.vitruv.framework.views.tests/pom.xml index 5da60e0dd0..3512bdf344 100644 --- a/tests/tools.vitruv.framework.views.tests/pom.xml +++ b/tests/tools.vitruv.framework.views.tests/pom.xml @@ -12,10 +12,21 @@ [test-bundle] Vitruv Framwork Views Tests + org.mockito mockito-core 4.2.0 + test + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + \ No newline at end of file diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/BasicStateChangePropagationTest.xtend b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/BasicStateChangePropagationTest.xtend index 071e6c6f0e..76fc1df437 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/BasicStateChangePropagationTest.xtend +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/BasicStateChangePropagationTest.xtend @@ -9,9 +9,9 @@ import org.junit.jupiter.params.provider.MethodSource import tools.vitruv.change.atomic.eobject.CreateEObject import tools.vitruv.change.atomic.eobject.DeleteEObject import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute -import tools.vitruv.change.atomic.id.IdResolver import tools.vitruv.change.atomic.root.InsertRootEObject import tools.vitruv.change.atomic.root.RemoveRootEObject +import tools.vitruv.change.composite.description.VitruviusChangeResolver import tools.vitruv.testutils.Capture import static org.hamcrest.CoreMatchers.instanceOf @@ -49,7 +49,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { // Create empty resource to apply generated changes to val validationResourceSet = new ResourceSetImpl() - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) modelResource.save(null) assertEquals(1, validationResourceSet.resources.size) @@ -77,7 +77,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { // Load resource to apply generated changes to val validationResourceSet = new ResourceSetImpl() validationResourceSet.getResource(testUri, true) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) assertEquals(1, validationResourceSet.resources.size) assertTrue(validationResourceSet.resources.get(0).contents.empty) @@ -108,7 +108,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { val oldState = validationResourceSet.getResource(testUri, true) val changes = strategyToTest.getChangeSequenceBetween(-modelResource, oldState) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) assertEquals(1, validationResourceSet.resources.size) assertThat(validationResourceSet.resources.get(0), containsModelOf(-modelResource)) @@ -139,7 +139,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { assertEquals(1, changes.EChanges.size) assertEquals(1, changes.EChanges.filter(ReplaceSingleValuedEAttribute).size) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) assertEquals(1, validationResourceSet.resources.size) assertThat(validationResourceSet.resources.get(0), containsModelOf(-modelResource)) @@ -167,19 +167,19 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { val validationResourceSet = new ResourceSetImpl().withGlobalFactories() val oldState = validationResourceSet.getResource(testUri, true) val unresolvedChanges = strategyToTest.getChangeSequenceBetween(-modelResource, oldState) - val changes = unresolvedChanges.resolveAndApply(IdResolver.create(validationResourceSet)) + val changes = VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(unresolvedChanges) switch (strategyToTest.useIdentifiers) { case ONLY, case WHEN_AVAILABLE: { val Iterable> deleteChanges = newArrayList(changes.EChanges.filter(DeleteEObject)) assertEquals(1, deleteChanges.size) - assertThat(deleteChanges.head.affectedEObject, instanceOf(Root)) - assertEquals("Root", (deleteChanges.head.affectedEObject as Root).id) + assertThat(deleteChanges.head.affectedElement, instanceOf(Root)) + assertEquals("Root", (deleteChanges.head.affectedElement as Root).id) val Iterable> createChanges = newArrayList(changes.EChanges.filter(CreateEObject)) assertEquals(1, createChanges.size) - assertThat(createChanges.head.affectedEObject, instanceOf(Root)) - assertEquals("Root2", (createChanges.head.affectedEObject as Root).id) + assertThat(createChanges.head.affectedElement, instanceOf(Root)) + assertEquals("Root2", (createChanges.head.affectedElement as Root).id) } case NEVER: { assertEquals(1, changes.EChanges.size) @@ -221,7 +221,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { assertEquals(1, changes.EChanges.size) assertEquals(1, changes.EChanges.filter(ReplaceSingleValuedEAttribute).size) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) assertEquals(1, validationResourceSet.resources.size) assertThat(validationResourceSet.resources.get(0), containsModelOf(-modelResource)) @@ -254,19 +254,19 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { val validationResourceSet = new ResourceSetImpl().withGlobalFactories() val oldState = validationResourceSet.getResource(testUri, true) val unresolvedChanges = strategyToTest.getChangeSequenceBetween(-modelResource, oldState) - val changes = unresolvedChanges.resolveAndApply(IdResolver.create(validationResourceSet)) + val changes = VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(unresolvedChanges) switch (strategyToTest.useIdentifiers) { case ONLY, case WHEN_AVAILABLE: { val Iterable> deleteChanges = newArrayList(changes.EChanges.filter(DeleteEObject)) assertEquals(1, deleteChanges.size) - assertThat(deleteChanges.head.affectedEObject, instanceOf(Root)) - assertEquals("ContainedRoot", (deleteChanges.head.affectedEObject as Root).id) + assertThat(deleteChanges.head.affectedElement, instanceOf(Root)) + assertEquals("ContainedRoot", (deleteChanges.head.affectedElement as Root).id) val Iterable> createChanges = newArrayList(changes.EChanges.filter(CreateEObject)) assertEquals(1, createChanges.size) - assertThat(createChanges.head.affectedEObject, instanceOf(Root)) - assertEquals("ContainedRoot2", (createChanges.head.affectedEObject as Root).id) + assertThat(createChanges.head.affectedElement, instanceOf(Root)) + assertEquals("ContainedRoot2", (createChanges.head.affectedElement as Root).id) } case NEVER: { assertEquals(1, changes.EChanges.size) @@ -308,7 +308,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { assertEquals(1, changes.EChanges.filter(RemoveRootEObject).size) assertEquals(1, changes.EChanges.filter(InsertRootEObject).size) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) (-modelResource).save(null) assertEquals(2, validationResourceSet.resources.size) @@ -348,7 +348,7 @@ class BasicStateChangePropagationTest extends StateChangePropagationTest { assertEquals(1, changes.EChanges.filter(InsertRootEObject).size) assertEquals(1, changes.EChanges.filter(ReplaceSingleValuedEAttribute).size) - changes.resolveAndApply(IdResolver.create(validationResourceSet)) + VitruviusChangeResolver.forHierarchicalIds(validationResourceSet).resolveAndApply(changes) (-modelResource).save(null) assertEquals(2, validationResourceSet.resources.size) diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/StateChangePropagationTest.xtend b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/StateChangePropagationTest.xtend index ce1bab8555..4b5f9ff8b0 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/StateChangePropagationTest.xtend +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/changederivation/StateChangePropagationTest.xtend @@ -5,6 +5,7 @@ import java.util.stream.Stream import org.eclipse.emf.common.notify.Notifier import org.eclipse.emf.common.util.URI import org.eclipse.emf.compare.utils.UseIdentifiers +import org.eclipse.emf.ecore.EObject import org.eclipse.emf.ecore.resource.Resource import org.eclipse.emf.ecore.resource.ResourceSet import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl @@ -15,8 +16,8 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Named import org.junit.jupiter.api.^extension.ExtendWith import pcm_mockup.Repository -import tools.vitruv.change.atomic.id.IdResolver import tools.vitruv.change.composite.description.VitruviusChange +import tools.vitruv.change.composite.description.VitruviusChangeResolver import tools.vitruv.change.composite.recording.ChangeRecorder import tools.vitruv.testutils.RegisterMetamodelsInStandalone import tools.vitruv.testutils.TestLogging @@ -102,7 +103,7 @@ abstract class StateChangePropagationTest { val deltaBasedChange = resourceSet.endRecording val unresolvedStateBasedChange = strategyToTest.getChangeSequenceBetween(model, checkpoint) assertNotNull(unresolvedStateBasedChange) - val stateBasedChange = unresolvedStateBasedChange.resolveAndApply(IdResolver.create(checkpoint.resourceSet)) + val stateBasedChange = VitruviusChangeResolver.forHierarchicalIds(checkpoint.resourceSet).resolveAndApply(unresolvedStateBasedChange) val message = getTextualRepresentation(stateBasedChange, deltaBasedChange) val stateBasedChangedObjects = stateBasedChange.affectedAndReferencedEObjects val deltaBasedChangedObjects = deltaBasedChange.affectedAndReferencedEObjects @@ -121,12 +122,12 @@ abstract class StateChangePropagationTest { /** * Returns the recorded change sequences (the "original" changes) for a specific model instance. */ - private def VitruviusChange endRecording(Notifier notifier) { + private def VitruviusChange endRecording(Notifier notifier) { changeRecorder.removeFromRecording(notifier) return changeRecorder.endRecording } - private def String getTextualRepresentation(VitruviusChange stateBasedChange, VitruviusChange deltaBasedChange) ''' + private def String getTextualRepresentation(VitruviusChange stateBasedChange, VitruviusChange deltaBasedChange) ''' State-based «stateBasedChange» Delta-based «deltaBasedChange» ''' diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/BasicViewTest.java b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/BasicViewTest.java index cda335aa31..97616f2b03 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/BasicViewTest.java +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/BasicViewTest.java @@ -21,6 +21,7 @@ import allElementTypes.NonRoot; import allElementTypes.Root; +import tools.vitruv.change.atomic.hid.HierarchicalId; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.ModifiableViewSelection; import tools.vitruv.testutils.RegisterMetamodelsInStandalone; @@ -29,7 +30,7 @@ @ExtendWith({ TestLogging.class, RegisterMetamodelsInStandalone.class }) public class BasicViewTest { @Mock - ViewCreatingViewType mockViewType; + ViewCreatingViewType mockViewType; @Mock ChangeableViewSource mockChangeableViewSource; @Mock diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeDerivingViewTest.java b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeDerivingViewTest.java index f9ab130c0b..6bf83253a4 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeDerivingViewTest.java +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeDerivingViewTest.java @@ -29,14 +29,14 @@ import allElementTypes.NonRoot; import allElementTypes.Root; -import tools.vitruv.change.atomic.eobject.EobjectPackage; import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute; -import tools.vitruv.change.atomic.id.IdResolver; +import tools.vitruv.change.atomic.hid.HierarchicalId; import tools.vitruv.change.atomic.root.InsertRootEObject; import tools.vitruv.change.atomic.root.RootFactory; import tools.vitruv.change.atomic.root.RootPackage; import tools.vitruv.change.changederivation.DefaultStateBasedChangeResolutionStrategy; import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.change.composite.description.VitruviusChangeResolver; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.ModifiableViewSelection; import tools.vitruv.testutils.RegisterMetamodelsInStandalone; @@ -45,7 +45,7 @@ @ExtendWith({ TestLogging.class, RegisterMetamodelsInStandalone.class }) public class ChangeDerivingViewTest { @Mock - ViewCreatingViewType mockViewType; + ViewCreatingViewType mockViewType; @Mock ChangeableViewSource mockChangeableViewSource; @Mock @@ -207,19 +207,18 @@ public void commitChanges() throws Exception { view.registerRoot(root, URI.createURI(testResourceUriString)); assertThat(view.getRootObjects(), hasItem(root)); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeDerivingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); - VitruviusChange change = changeArgument.getValue().resolveAndApply(IdResolver.create(root.eResource().getResourceSet())); + VitruviusChange change = VitruviusChangeResolver.forHierarchicalIds(root.eResource().getResourceSet()).resolveAndApply(changeArgument.getValue()); InsertRootEObject expectedChange = RootFactory.eINSTANCE.createInsertRootEObject(); expectedChange.setNewValue(root); expectedChange.setUri(testResourceUriString); assertThat(change.getEChanges().size(), is(3)); // Create, Insert, ReplaceId assertThat(change.getEChanges().get(1), equalsDeeply(expectedChange, - ignoringFeatures(EobjectPackage.eINSTANCE.getEObjectAddedEChange_NewValueID(), - RootPackage.eINSTANCE.getRootEChange_Resource()))); + ignoringFeatures(RootPackage.eINSTANCE.getRootEChange_Resource()))); assertThat(change.getEChanges().get(2), instanceOf(ReplaceSingleValuedEAttribute.class)); } } @@ -285,7 +284,7 @@ public void commitChanges() throws Exception { view.moveRoot(root, URI.createURI(movedResourceUriString)); assertThat(view.getRootObjects(), hasItem(root)); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeDerivingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); view.commitChangesAndUpdate(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); @@ -325,7 +324,7 @@ public void once() { nonRoot.setId("nonRoot"); root.setSingleValuedContainmentEReference(nonRoot); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeDerivingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); view.commitChangesAndUpdate(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); @@ -348,7 +347,7 @@ public void twice() { secondNonRoot.setId("second"); root.setSingleValuedContainmentEReference(secondNonRoot); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeDerivingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); view.commitChangesAndUpdate(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); @@ -363,7 +362,7 @@ public void twice() { @DisplayName("without changes") public void withoutChanges() { ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeDerivingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); view.commitChangesAndUpdate(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeRecordingViewTest.java b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeRecordingViewTest.java index 01bb50a503..c08fa2557a 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeRecordingViewTest.java +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/ChangeRecordingViewTest.java @@ -17,6 +17,9 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -30,19 +33,19 @@ import allElementTypes.AllElementTypesPackage; import allElementTypes.NonRoot; import allElementTypes.Root; -import tools.vitruv.change.composite.description.VitruviusChange; import tools.vitruv.change.atomic.EChange; import tools.vitruv.change.atomic.eobject.CreateEObject; import tools.vitruv.change.atomic.eobject.DeleteEObject; -import tools.vitruv.change.atomic.eobject.EobjectPackage; -import tools.vitruv.change.atomic.feature.FeaturePackage; import tools.vitruv.change.atomic.feature.attribute.AttributeFactory; import tools.vitruv.change.atomic.feature.attribute.AttributePackage; import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute; import tools.vitruv.change.atomic.feature.reference.ReplaceSingleValuedEReference; +import tools.vitruv.change.atomic.hid.HierarchicalId; import tools.vitruv.change.atomic.root.InsertRootEObject; import tools.vitruv.change.atomic.root.RootFactory; import tools.vitruv.change.atomic.root.RootPackage; +import tools.vitruv.change.composite.description.VitruviusChange; +import tools.vitruv.change.composite.description.VitruviusChangeResolver; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.ModifiableViewSelection; import tools.vitruv.testutils.RegisterMetamodelsInStandalone; @@ -51,7 +54,7 @@ @ExtendWith({ TestLogging.class, RegisterMetamodelsInStandalone.class }) public class ChangeRecordingViewTest { @Mock - ViewCreatingViewType mockViewType; + ViewCreatingViewType mockViewType; @Mock ChangeableViewSource mockChangeableViewSource; @Mock @@ -68,14 +71,14 @@ public class Initialize { @Test @DisplayName("with null view") public void withNullViewType() { - assertThrows(IllegalArgumentException.class, - () -> new ChangeRecordingView(null)); + assertThrows(IllegalArgumentException.class, () -> new ChangeRecordingView(null)); } @Test @DisplayName("with proper arguments") public void withEmptySource() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { assertThat(view.isClosed(), is(false)); assertThat(view.getRootObjects(), not(hasItem(anything()))); } @@ -88,7 +91,8 @@ public class RetrieveRootElements { @Test @DisplayName("all of same type") public void allOfSameType() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); view.registerRoot(root, URI.createURI("test://test.aet")); Root root2 = aet.Root(); @@ -105,7 +109,8 @@ public void allOfSameType() throws Exception { @Test @DisplayName("all of one out of two types") public void containingAllOfOneType() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); view.registerRoot(root, URI.createURI("test://test.aet")); NonRoot otherRoot = aet.NonRoot(); @@ -121,7 +126,8 @@ public void containingAllOfOneType() throws Exception { @Test @DisplayName("containing none of a type") public void containingNoneOfType() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); view.registerRoot(root, URI.createURI("test://test.aet")); Root otherRoot = aet.Root(); @@ -140,7 +146,8 @@ public class Update { @Test @DisplayName("without previous modification") public void withoutPreviousModification() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { view.update(); } } @@ -148,7 +155,8 @@ public void withoutPreviousModification() throws Exception { @Test @DisplayName("with previous modification") public void withPreviousModification() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { view.modifyContents((resourceSet) -> resourceSet.createResource(URI.createURI("test://test.aet"))); assertThrows(IllegalStateException.class, () -> view.update()); } @@ -161,7 +169,8 @@ public class AddRoot { @Test @DisplayName("being null") public void nullElement() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { assertThrows(IllegalArgumentException.class, () -> view.registerRoot(null, URI.createURI("test://test.aet"))); } @@ -170,7 +179,8 @@ public void nullElement() throws Exception { @Test @DisplayName("with null URI") public void nullUri() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); assertThrows(IllegalArgumentException.class, () -> view.registerRoot(root, null)); } @@ -179,7 +189,8 @@ public void nullUri() throws Exception { @Test @DisplayName("with proper arguments") public void properArguments() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); String testResourceUriString = "test://test.aet"; view.registerRoot(root, URI.createURI(testResourceUriString)); @@ -190,27 +201,30 @@ public void properArguments() throws Exception { @Test @DisplayName("committing changes") public void commitChanges() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); root.setId("root"); String testResourceUriString = "test://test.aet"; view.registerRoot(root, URI.createURI(testResourceUriString)); assertThat(view.getRootObjects(), hasItem(root)); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeRecordingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor + .forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); + assertThat(viewArgument.getValue(), is(view)); - VitruviusChange recordedChange = changeArgument.getValue(); + ResourceSet resolveInResourceSet = new ResourceSetImpl(); + VitruviusChange resolvedChange = VitruviusChangeResolver + .forHierarchicalIds(resolveInResourceSet).resolveAndApply(changeArgument.getValue()); InsertRootEObject expectedChange = RootFactory.eINSTANCE.createInsertRootEObject(); expectedChange.setNewValue(root); expectedChange.setUri(testResourceUriString); - assertThat(recordedChange.getEChanges().size(), is(3)); // Create, Insert, ReplaceId - assertThat(recordedChange.getEChanges().get(1), - equalsDeeply(expectedChange, - ignoringFeatures(EobjectPackage.eINSTANCE.getEObjectAddedEChange_NewValueID(), - RootPackage.eINSTANCE.getRootEChange_Resource()))); - assertThat(recordedChange.getEChanges().get(2), instanceOf(ReplaceSingleValuedEAttribute.class)); + assertThat(resolvedChange.getEChanges().size(), is(3)); // Create, Insert, ReplaceId + assertThat(resolvedChange.getEChanges().get(1), equalsDeeply(expectedChange, + ignoringFeatures(RootPackage.eINSTANCE.getRootEChange_Resource()))); + assertThat(resolvedChange.getEChanges().get(2), instanceOf(ReplaceSingleValuedEAttribute.class)); } } } @@ -221,7 +235,8 @@ public class MoveRoot { @Test @DisplayName("being null") public void nullElement() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { assertThrows(IllegalArgumentException.class, () -> view.moveRoot(null, URI.createURI("test://test.aet"))); } @@ -230,7 +245,8 @@ public void nullElement() throws Exception { @Test @DisplayName("with null URI") public void nullUri() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); view.registerRoot(root, URI.createURI("test://test.aet")); assertThrows(IllegalArgumentException.class, () -> view.moveRoot(root, null)); @@ -240,7 +256,8 @@ public void nullUri() throws Exception { @Test @DisplayName("with element not beeing root") public void notBeingRoot() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); assertThrows(IllegalStateException.class, () -> view.moveRoot(root, URI.createURI("test://test.aet"))); } @@ -249,7 +266,8 @@ public void notBeingRoot() throws Exception { @Test @DisplayName("with proper arguments") public void properArguments() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); view.registerRoot(root, URI.createURI("test://test.aet")); view.moveRoot(root, URI.createURI("test://test2.aet")); @@ -261,28 +279,36 @@ public void properArguments() throws Exception { @Test @DisplayName("committing changes") public void commitChanges() throws Exception { - try (ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { + try (ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection))) { Root root = aet.Root(); String movedResourceUriString = "test://test2.aet"; view.registerRoot(root, URI.createURI("test://test.aet")); view.commitChanges(); reset(mockChangeableViewSource, mockViewType); + + ResourceSet resolveInResourceSet = new ResourceSetImpl(); + resolveInResourceSet.createResource(root.eResource().getURI()); + resolveInResourceSet.getResource(root.eResource().getURI(), false).getContents() + .add(EcoreUtil.copy(root)); + view.moveRoot(root, URI.createURI(movedResourceUriString)); assertThat(view.getRootObjects(), hasItem(root)); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeRecordingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor + .forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); - List capturedEChanges = changeArgument.getValue().getEChanges(); + VitruviusChange resolvedChange = VitruviusChangeResolver + .forHierarchicalIds(resolveInResourceSet).resolveAndApply(changeArgument.getValue()); + List> capturedEChanges = resolvedChange.getEChanges(); InsertRootEObject expectedChange = RootFactory.eINSTANCE.createInsertRootEObject(); expectedChange.setNewValue(root); expectedChange.setUri(movedResourceUriString); assertThat(capturedEChanges.size(), is(2)); // Remove, Insert - assertThat(capturedEChanges.get(1), - equalsDeeply(expectedChange, - ignoringFeatures(EobjectPackage.eINSTANCE.getEObjectAddedEChange_NewValueID(), - RootPackage.eINSTANCE.getRootEChange_Resource()))); + assertThat(capturedEChanges.get(1), equalsDeeply(expectedChange, + ignoringFeatures(RootPackage.eINSTANCE.getRootEChange_Resource()))); } } } @@ -314,11 +340,12 @@ public void once() { nonRoot.setId("nonRoot"); root.setSingleValuedContainmentEReference(nonRoot); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeRecordingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor + .forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); - List capturedEChanges = changeArgument.getValue().getEChanges(); + List> capturedEChanges = changeArgument.getValue().getEChanges(); assertThat(capturedEChanges.size(), is(3)); // Create, Insert, ReplaceId assertThat(capturedEChanges.get(0), instanceOf(CreateEObject.class)); assertThat(capturedEChanges.get(1), instanceOf(ReplaceSingleValuedEReference.class)); @@ -332,27 +359,34 @@ public void twice() { firstNonRoot.setId("first"); root.setSingleValuedContainmentEReference(firstNonRoot); view.commitChanges(); + + ResourceSet resolveInResourceSet = new ResourceSetImpl(); + resolveInResourceSet.createResource(root.eResource().getURI()); + resolveInResourceSet.getResource(root.eResource().getURI(), false).getContents().add(EcoreUtil.copy(root)); + reset(mockChangeableViewSource, mockViewType); NonRoot secondNonRoot = aet.NonRoot(); secondNonRoot.setId("second"); root.setSingleValuedContainmentEReference(secondNonRoot); ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeRecordingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor + .forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); - List capturedEChanges = changeArgument.getValue().getEChanges(); + + VitruviusChange resolvedChange = VitruviusChangeResolver.forHierarchicalIds(resolveInResourceSet) + .resolveAndApply(changeArgument.getValue()); + List> capturedEChanges = resolvedChange.getEChanges(); assertThat(capturedEChanges.size(), is(4)); // Create, Insert, ReplaceValue, Delete assertThat(capturedEChanges.get(0), instanceOf(CreateEObject.class)); assertThat(capturedEChanges.get(1), instanceOf(ReplaceSingleValuedEReference.class)); ReplaceSingleValuedEAttribute replaceIdChange = AttributeFactory.eINSTANCE .createReplaceSingleValuedEAttribute(); - replaceIdChange.setAffectedEObject(secondNonRoot); + replaceIdChange.setAffectedElement(secondNonRoot); replaceIdChange.setAffectedFeature(AllElementTypesPackage.eINSTANCE.getIdentified_Id()); replaceIdChange.setNewValue("second"); - assertThat(capturedEChanges.get(2), - equalsDeeply(replaceIdChange, - ignoringFeatures(AttributePackage.eINSTANCE.getSubtractiveAttributeEChange_OldValue(), - FeaturePackage.eINSTANCE.getFeatureEChange_AffectedEObjectID()))); + assertThat(capturedEChanges.get(2), equalsDeeply(replaceIdChange, + ignoringFeatures(AttributePackage.eINSTANCE.getSubtractiveAttributeEChange_OldValue()))); assertThat(capturedEChanges.get(3), instanceOf(DeleteEObject.class)); } @@ -360,7 +394,8 @@ public void twice() { @DisplayName("without changes") public void withoutChanges() { ArgumentCaptor viewArgument = ArgumentCaptor.forClass(ChangeRecordingView.class); - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + ArgumentCaptor> changeArgument = ArgumentCaptor + .forClass(VitruviusChange.class); view.commitChanges(); verify(mockViewType).commitViewChanges(viewArgument.capture(), changeArgument.capture()); assertThat(viewArgument.getValue(), is(view)); @@ -374,7 +409,8 @@ public class Close { @Test @DisplayName("and is closed afterwards") public void isClosed() throws Exception { - ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); + ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); view.close(); assertThat("view should be closed", view.isClosed()); } @@ -382,7 +418,8 @@ public void isClosed() throws Exception { @Test @DisplayName("can be called multiple times") public void callMultipleTimes() throws Exception { - ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); + ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); view.close(); view.close(); assertThat("view should be closed", view.isClosed()); @@ -391,7 +428,8 @@ public void callMultipleTimes() throws Exception { @Test @DisplayName("and does not allow further operations") public void noOperations() throws Exception { - ChangeRecordingView view = new ChangeRecordingView(new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); + ChangeRecordingView view = new ChangeRecordingView( + new BasicView(mockViewType, mockChangeableViewSource, mockViewSelection)); view.close(); assertThrows(IllegalStateException.class, () -> view.getRootObjects()); assertThrows(IllegalStateException.class, () -> view.getRootObjects(Root.class)); diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/IdentityMappingViewTypeTest.java b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/IdentityMappingViewTypeTest.java index 1bd50cc174..fd65a9f53a 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/IdentityMappingViewTypeTest.java +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/impl/IdentityMappingViewTypeTest.java @@ -15,8 +15,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static tools.vitruv.change.atomic.resolve.EChangeIdResolverAndApplicator.applyBackward; -import static tools.vitruv.change.atomic.resolve.EChangeIdResolverAndApplicator.applyForward; import static tools.vitruv.testutils.matchers.ModelMatchers.equalsDeeply; import static tools.vitruv.testutils.metamodels.AllElementTypesCreators.aet; @@ -43,12 +41,13 @@ import allElementTypes.Root; import tools.vitruv.change.atomic.EChange; -import tools.vitruv.change.atomic.EChangeIdManager; import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute; -import tools.vitruv.change.atomic.id.IdResolver; +import tools.vitruv.change.atomic.hid.HierarchicalId; +import tools.vitruv.change.atomic.uuid.Uuid; import tools.vitruv.change.atomic.uuid.UuidResolver; import tools.vitruv.change.composite.description.VitruviusChange; import tools.vitruv.change.composite.description.VitruviusChangeFactory; +import tools.vitruv.change.composite.description.VitruviusChangeResolver; import tools.vitruv.change.composite.recording.ChangeRecorder; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.View; @@ -97,7 +96,8 @@ public void initializeViewType() { @Test @DisplayName("for empty source") public void forEmptySource() { - DirectViewElementSelector selector = basicViewType.createSelector(mock(ChangeableViewSource.class)); + DirectViewElementSelector selector = basicViewType + .createSelector(mock(ChangeableViewSource.class)); assertThat(selector.getSelectableElements(), is(emptySet())); } @@ -110,7 +110,7 @@ public void forSourceContainingElement() { resource.getContents().add(rootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(resource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); assertThat(selector.getSelectableElements(), is(Set.of(rootElement))); } @@ -124,7 +124,7 @@ public void forSourceContainingNonRootElements() { resource.getContents().add(rootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(resource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); assertThat(selector.getSelectableElements(), is(Set.of(rootElement))); } } @@ -145,7 +145,7 @@ public void initializeViewTypeAndResourceSet() { @DisplayName("with empty source") public void withNoElements() throws Exception { ChangeableViewSource viewSource = mock(ChangeableViewSource.class); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); try (View view = basicViewType.createView(selector)) { assertThat(view.getRootObjects(), not(hasItem(anything()))); } @@ -155,7 +155,8 @@ public void withNoElements() throws Exception { @DisplayName("with selector from other view type") public void withSelectorFromOtherViewtype() { ChangeableViewSource viewSource = mock(ChangeableViewSource.class); - DirectViewElementSelector selector = new IdentityMappingViewType("other").createSelector(viewSource); + DirectViewElementSelector selector = new IdentityMappingViewType("other") + .createSelector(viewSource); assertThrows(IllegalArgumentException.class, () -> basicViewType.createView(selector)); } @@ -168,7 +169,7 @@ public void withNoSelectedElement() throws Exception { resource.getContents().add(rootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(resource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); try (View view = basicViewType.createView(selector)) { assertThat(view.getRootObjects(), not(hasItem(anything()))); } @@ -183,7 +184,7 @@ public void withSingleSelectedElement() throws Exception { resource.getContents().add(rootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(resource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.setSelected(rootElement, true); try (View view = basicViewType.createView(selector)) { assertThat(view.getRootObjects().size(), is(1)); @@ -204,7 +205,7 @@ public void withOneOfTwoElementsSelected() throws Exception { secondResource.getContents().add(secondRootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(firstResource, secondResource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.setSelected(firstRootElement, true); try (View view = basicViewType.createView(selector)) { assertThat(view.getRootObjects().size(), is(1)); @@ -225,7 +226,7 @@ public void withBothOfTwoElementsSelected() throws Exception { secondResource.getContents().add(secondRootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(firstResource, secondResource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.setSelected(firstRootElement, true); selector.setSelected(secondRootElement, true); try (View view = basicViewType.createView(selector)) { @@ -258,7 +259,7 @@ public void forTwoResourcesWithContainmentInBetween() throws Exception { secondResource.getContents().add(secondRootElement); ChangeableViewSource viewSource = mock(ChangeableViewSource.class); when(viewSource.getViewSourceModels()).thenReturn(Set.of(firstResource, secondResource)); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.setSelected(firstRootElement, true); selector.setSelected(secondRootElement, true); try (View view = basicViewType.createView(selector)) { @@ -302,7 +303,7 @@ private Root createResourceWithSingleRoot(URI uri) { @DisplayName("adding a non-root element") public void addingANonRootElement() throws Exception { Root root = createResourceWithSingleRoot(URI.createURI("test://test.aet")); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.getSelectableElements().forEach((element) -> selector.setSelected(element, true)); try (ModifiableView view = basicViewType.createView(selector)) { root.setSingleValuedContainmentEReference(aet.NonRoot()); @@ -319,7 +320,7 @@ public void addingANonRootElement() throws Exception { @DisplayName("adding a root element") public void addingARootElement() throws Exception { Root root = createResourceWithSingleRoot(URI.createURI("test://test.aet")); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.getSelectableElements().forEach((element) -> selector.setSelected(element, true)); try (ModifiableView view = basicViewType.createView(selector)) { root.setId("secondId"); @@ -334,7 +335,7 @@ public void addingARootElement() throws Exception { @DisplayName("removing a selected root element") public void removingSelectedRoot() throws Exception { Root root = createResourceWithSingleRoot(URI.createURI("test://test.aet")); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.getSelectableElements().forEach((element) -> selector.setSelected(element, true)); try (ModifiableView view = basicViewType.createView(selector)) { EcoreUtil.delete(root); @@ -349,7 +350,7 @@ public void removingSelectedRoot() throws Exception { public void removingUnselectedRoot() throws Exception { Root firstRoot = createResourceWithSingleRoot(URI.createURI("test://test.aet")); Root secondRoot = createResourceWithSingleRoot(URI.createURI("test://test2.aet")); - DirectViewElementSelector selector = basicViewType.createSelector(viewSource); + DirectViewElementSelector selector = basicViewType.createSelector(viewSource); selector.setSelected(firstRoot, true); try (ModifiableView view = basicViewType.createView(selector)) { EcoreUtil.delete(secondRoot); @@ -360,7 +361,7 @@ public void removingUnselectedRoot() throws Exception { } } } - + @Nested @DisplayName("commit view changes") class CommitViewChanges { @@ -387,51 +388,49 @@ void initializeViewTypeAndResourceSetAndViewSource() { when(viewSource.getUuidResolver()).thenReturn(uuidResolver); when(viewSelection.isViewObjectSelected(any(EObject.class))).thenReturn(true); } - + private Root createResourceWithSingleRoot(URI uri) { Resource resource = viewSourceResourceSet.createResource(uri); Root rootElement = aet.Root(); uuidResolver.registerEObject(rootElement); rootElement.setId("testid"); resource.getContents().add(rootElement); - + Resource viewResource = viewResourceSet.createResource(uri); Root viewRootElement = EcoreUtil.copy(rootElement); viewResource.getContents().add(viewRootElement); return viewRootElement; } - + @Test @DisplayName("with null changes") void withNull() { assertThrows(NullPointerException.class, () -> basicViewType.commitViewChanges(view, null)); } - + @Test @DisplayName("with null view") void withNullView() { - VitruviusChange someChange = VitruviusChangeFactory.getInstance().createTransactionalChange(Set.of()); + VitruviusChange someChange = VitruviusChangeFactory.getInstance() + .createTransactionalChange(Set.of()); assertThrows(NullPointerException.class, () -> basicViewType.commitViewChanges(null, someChange)); } - + @ParameterizedTest @MethodSource("testEmptyChanges") @DisplayName("with empty changes") - void withEmptyChanges(VitruviusChange change) { - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + void withEmptyChanges(VitruviusChange change) { + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); basicViewType.commitViewChanges(view, change); verify(viewSource).propagateChange(changeArgument.capture()); assertEquals(changeArgument.getValue(), change); } - - private static Stream testEmptyChanges() { + + private static Stream> testEmptyChanges() { VitruviusChangeFactory factory = VitruviusChangeFactory.getInstance(); - return Stream.of( - factory.createTransactionalChange(Set.of()), - factory.createCompositeChange(Set.of()) - ); + return Stream.of(factory.createTransactionalChange(Set.of()), factory.createCompositeChange(Set.of())); } - + @Test @DisplayName("with non-empty change") void withNonEmptyChange() { @@ -441,31 +440,25 @@ void withNonEmptyChange() { changeRecorder.beginRecording(); root.setId("testid2"); changeRecorder.endRecording(); - VitruviusChange change = changeRecorder.getChange(); - assignIds(change); - - ArgumentCaptor changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); - basicViewType.commitViewChanges(view, change); + VitruviusChange change = changeRecorder.getChange(); + VitruviusChange idAssignedChange = assignIds(change); + + ArgumentCaptor> changeArgument = ArgumentCaptor.forClass(VitruviusChange.class); + basicViewType.commitViewChanges(view, idAssignedChange); verify(viewSource).propagateChange(changeArgument.capture()); - List eChanges = changeArgument.getValue().unresolve().getEChanges(); + List> eChanges = changeArgument.getValue().getEChanges(); assertThat(eChanges.size(), is(1)); assertThat(eChanges.get(0), instanceOf(ReplaceSingleValuedEAttribute.class)); - var attributeChange = (ReplaceSingleValuedEAttribute)eChanges.get(0); + var attributeChange = (ReplaceSingleValuedEAttribute) eChanges.get(0); assertThat(attributeChange.getOldValue(), is("testid")); assertThat(attributeChange.getNewValue(), is("testid2")); } } - - private void assignIds(VitruviusChange change) { - IdResolver idResolver = IdResolver.create(viewResourceSet); - EChangeIdManager idManager = new EChangeIdManager(idResolver); - for (int i = change.getEChanges().size() - 1; i >= 0; i--) { - applyBackward(change.getEChanges().get(i)); - } - change.getEChanges().forEach(eChange -> { - idManager.setOrGenerateIds(eChange); - applyForward(eChange, idResolver); - }); + + private VitruviusChange assignIds(VitruviusChange change) { + VitruviusChangeResolver idChangeResolver = VitruviusChangeResolver + .forHierarchicalIds(viewResourceSet); + return idChangeResolver.assignIds(change); } } } diff --git a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/selectors/DirectViewElementSelectorTest.java b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/selectors/DirectViewElementSelectorTest.java index 55eba440f6..a099cef99d 100644 --- a/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/selectors/DirectViewElementSelectorTest.java +++ b/tests/tools.vitruv.framework.views.tests/src/tools/vitruv/framework/views/selectors/DirectViewElementSelectorTest.java @@ -22,6 +22,7 @@ import org.mockito.MockitoAnnotations; import allElementTypes.Root; +import tools.vitruv.change.atomic.hid.HierarchicalId; import tools.vitruv.framework.views.ChangeableViewSource; import tools.vitruv.framework.views.ViewSelector; import tools.vitruv.framework.views.impl.ModifiableView; @@ -32,7 +33,7 @@ @ExtendWith({ TestLogging.class, RegisterMetamodelsInStandalone.class }) public class DirectViewElementSelectorTest { @Mock - ViewCreatingViewType mockViewType; + ViewCreatingViewType, HierarchicalId> mockViewType; @Mock ChangeableViewSource mockViewSource; @@ -52,28 +53,28 @@ class WithNullElements { @DisplayName("with null view type") public void nullViewType() { assertThrows(IllegalArgumentException.class, - () -> new DirectViewElementSelector(null, mockViewSource, emptySet())); + () -> new DirectViewElementSelector<>(null, mockViewSource, emptySet())); } @Test @DisplayName("with null view source") public void nullViewSource() { assertThrows(IllegalArgumentException.class, - () -> new DirectViewElementSelector(mockViewType, null, emptySet())); + () -> new DirectViewElementSelector<>(mockViewType, null, emptySet())); } @Test @DisplayName("with null selectable elements") public void nullElements() { assertThrows(IllegalArgumentException.class, - () -> new DirectViewElementSelector(mockViewType, mockViewSource, null)); + () -> new DirectViewElementSelector<>(mockViewType, mockViewSource, null)); } } @Test @DisplayName("with no selectable elements") public void empty() { - ViewSelector selector = new DirectViewElementSelector(mockViewType, mockViewSource, emptySet()); + ViewSelector selector = new DirectViewElementSelector<>(mockViewType, mockViewSource, emptySet()); assertThat(selector.getSelectableElements(), is(emptySet())); assertThat("BasicViewElementSelectors must always be valid", selector.isValid()); } @@ -82,7 +83,7 @@ public void empty() { @DisplayName("with single selectable element") public void withSingleSelectableElement() { Root root = aet.Root(); - ViewSelector selector = new DirectViewElementSelector(mockViewType, mockViewSource, Set.of(root)); + ViewSelector selector = new DirectViewElementSelector<>(mockViewType, mockViewSource, Set.of(root)); assertThat(selector.getSelectableElements(), is(Set.of(root))); assertThat("BasicViewElementSelectors must always be valid", selector.isValid()); } @@ -92,7 +93,7 @@ public void withSingleSelectableElement() { public void withMultipleSelectableElements() { Root firstRoot = aet.Root(); Root secondRoot = aet.Root(); - ViewSelector selector = new DirectViewElementSelector(mockViewType, mockViewSource, + ViewSelector selector = new DirectViewElementSelector<>(mockViewType, mockViewSource, Set.of(firstRoot, secondRoot)); assertThat(selector.getSelectableElements(), is(Set.of(firstRoot, secondRoot))); assertThat("BasicViewElementSelectors must always be valid", selector.isValid()); @@ -111,7 +112,7 @@ public void setupSelectionWithFirstOfTwoElementsSelected() { selectableElements = new ArrayList<>(); selectableElements.add(aet.Root()); selectableElements.add(aet.Root()); - selector = new DirectViewElementSelector(mockViewType, mockViewSource, selectableElements); + selector = new DirectViewElementSelector<>(mockViewType, mockViewSource, selectableElements); selector.setSelected(selectableElements.get(0), true); assertThat("BasicViewElementSelectors must always be valid", selector.isValid()); } @@ -144,7 +145,8 @@ class Returns { @Test @DisplayName("view created from view type") public void createView() { - DirectViewElementSelector selector = new DirectViewElementSelector(mockViewType, mockViewSource, emptySet()); + DirectViewElementSelector selector = new DirectViewElementSelector<>(mockViewType, + mockViewSource, emptySet()); ModifiableView view = mock(ModifiableView.class); when(mockViewType.createView(selector)).thenReturn(view); assertThat(selector.createView(), is(view)); @@ -153,7 +155,8 @@ public void createView() { @Test @DisplayName("view source") public void getViewSource() { - DirectViewElementSelector selector = new DirectViewElementSelector(mockViewType, mockViewSource, emptySet()); + DirectViewElementSelector selector = new DirectViewElementSelector<>(mockViewType, + mockViewSource, emptySet()); assertThat(selector.getViewSource(), is(mockViewSource)); } diff --git a/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTest.xtend b/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTest.xtend index 7391a84684..4011ba5102 100644 --- a/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTest.xtend +++ b/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTest.xtend @@ -9,12 +9,12 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.api.^extension.ExtendWith -import tools.vitruv.change.atomic.EChangeUuidManager import tools.vitruv.change.atomic.eobject.CreateEObject import tools.vitruv.change.atomic.feature.attribute.ReplaceSingleValuedEAttribute import tools.vitruv.change.atomic.feature.reference.ReplaceSingleValuedEReference import tools.vitruv.change.atomic.root.InsertRootEObject import tools.vitruv.change.atomic.uuid.UuidResolver +import tools.vitruv.change.composite.description.VitruviusChangeResolver import tools.vitruv.change.composite.recording.ChangeRecorder import tools.vitruv.framework.views.View import tools.vitruv.framework.views.ViewTypeFactory @@ -371,8 +371,8 @@ class VirtualModelTest { private def endRecording(ChangeRecorder changeRecorder, UuidResolver uuidResolver) { val change = changeRecorder.endRecording - EChangeUuidManager.setOrGenerateIds(change.EChanges, uuidResolver) - return change + val changeResolver = VitruviusChangeResolver.forUuids(uuidResolver) + return changeResolver.assignIds(change) } def private createAndPropagateRoot(VirtualModel virtualModel, ResourceSet resourceSet, UuidResolver uuidResolver, String rootId) { diff --git a/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTestUtil.xtend b/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTestUtil.xtend index 3686b162fb..6eb6031b19 100644 --- a/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTestUtil.xtend +++ b/tests/tools.vitruv.framework.vsum.tests/src/tools/vitruv/framework/vsum/VirtualModelTestUtil.xtend @@ -5,13 +5,15 @@ import allElementTypes.Root import edu.kit.ipd.sdq.activextendannotations.Utility import java.nio.file.Path import org.eclipse.emf.common.util.URI +import org.eclipse.emf.ecore.EObject import org.eclipse.emf.ecore.resource.ResourceSet import tools.vitruv.change.atomic.EChange -import tools.vitruv.change.atomic.EChangeUuidManager import tools.vitruv.change.atomic.root.InsertRootEObject +import tools.vitruv.change.atomic.uuid.Uuid import tools.vitruv.change.atomic.uuid.UuidResolver import tools.vitruv.change.composite.MetamodelDescriptor import tools.vitruv.change.composite.description.VitruviusChange +import tools.vitruv.change.composite.description.VitruviusChangeResolver import tools.vitruv.change.composite.recording.ChangeRecorder import tools.vitruv.change.correspondence.Correspondence import tools.vitruv.change.correspondence.view.EditableCorrespondenceModelView @@ -31,15 +33,16 @@ class VirtualModelTestUtil { /** * Create a recorder, start recording a resource set, apply changes, stop and return the recorded changes. */ - def static VitruviusChange recordChanges(ResourceSet resourceSet, UuidResolver uuidResolver, Runnable changesToPerform) { + def static VitruviusChange recordChanges(ResourceSet resourceSet, UuidResolver uuidResolver, Runnable changesToPerform) { val recorder = new ChangeRecorder(resourceSet) + val changeResolver = VitruviusChangeResolver.forUuids(uuidResolver) recorder.addToRecording(resourceSet) recorder.beginRecording changesToPerform.run() val result = recorder.endRecording - EChangeUuidManager.setOrGenerateIds(result.EChanges, uuidResolver) + val resolvedChange = changeResolver.assignIds(result) recorder.close - return result + return resolvedChange } /** @@ -86,20 +89,20 @@ class VirtualModelTestUtil { super(sourceMetamodelDescriptor, targetMetamodelDescriptor) } - override doesHandleChange(EChange change, EditableCorrespondenceModelView correspondenceModel) { + override doesHandleChange(EChange change, EditableCorrespondenceModelView correspondenceModel) { if(change instanceof InsertRootEObject) { return change.newValue instanceof Root } return false } - override propagateChange(EChange change, EditableCorrespondenceModelView correspondenceModel, + override propagateChange(EChange change, EditableCorrespondenceModelView correspondenceModel, extension ResourceAccess resourceAccess) { if(!doesHandleChange(change, correspondenceModel)) { return } - val typedChange = change as InsertRootEObject - val insertedRoot = typedChange.newValue + val typedChange = change as InsertRootEObject + val insertedRoot = typedChange.newValue as Root // If there is a corresponding element, reuse it, otherwise create one val correspondingRoots = correspondenceModel.getCorrespondingEObjects(insertedRoot).filter(Root) val correspondingRoot = if(correspondingRoots.size == 1) {