userInputs) {
+ base.checkNotClosed();
+ var recordedChange = changeRecorder.endRecording();
+ var changeResolver = VitruviusChangeResolverFactory.forHierarchicalIds(base.viewSource);
+ var unresolvedChanges = changeResolver.assignIds(recordedChange);
+ ((TransactionalChange>) unresolvedChanges).setUserInteractions(userInputs);
+ base.remoteConnection.propagateChanges(base.uuid, unresolvedChanges);
+ base.modified = false;
+ changeRecorder.beginRecording();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteView.java b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteView.java
index 88a4a91..b476328 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteView.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteView.java
@@ -1,7 +1,9 @@
package tools.vitruv.framework.remote.client.impl;
-import java.util.Collection;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import java.util.Collection;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
@@ -9,7 +11,6 @@
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
-
import tools.vitruv.framework.views.CommittableView;
import tools.vitruv.framework.views.View;
import tools.vitruv.framework.views.ViewSelection;
@@ -17,210 +18,212 @@
import tools.vitruv.framework.views.ViewType;
import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
/**
- * A {@link View} which is a copy of a {@link View} from the VSUM of a Vitruvius
- * server.
- *
- * Actions performed on this remote view or to the original view can be
- * synchronized via the network. This view uses
- * a {@link VitruvRemoteConnection} to do so.
+ * A {@link View} which is a copy of a {@link View} from the VSUM of a Vitruvius server.
+ *
+ *
Actions performed on this remote view or to the original view can be synchronized via the
+ * network. This view uses a {@link VitruvRemoteConnection} to do so.
*/
public class RemoteView implements View {
- private final ViewSelector selector;
-
- protected final String uuid;
- protected final VitruvRemoteConnection remoteConnection;
-
- protected ResourceSet viewSource;
- protected boolean modified = false;
-
- RemoteView(String uuid, ResourceSet viewSource, ViewSelector selector, VitruvRemoteConnection remoteConnection) {
- checkArgument(uuid != null, "uuid must not be null");
- checkArgument(viewSource != null, "view source must not be null");
- checkArgument(remoteConnection != null, "remote connection must not be null");
- checkArgument(selector != null, "selector must not be null");
- this.uuid = uuid;
- this.remoteConnection = remoteConnection;
- this.viewSource = viewSource;
- this.selector = selector;
-
- addChangeListeners(viewSource);
- }
-
- /**
- * Provides the root model elements of this view.
- *
- * @throws IllegalStateException If called on a closed view.
- * @see View#isClosed()
- */
- @Override
- public Collection getRootObjects() {
- checkNotClosed();
- return viewSource.getResources().stream().map(Resource::getContents).flatMap(Collection::stream).toList();
- }
-
- /**
- * Checks whether the view was closed. Closed views cannot be used further. All
- * methods may throw an {@link IllegalStateException}.
- */
- @Override
- public boolean isClosed() {
- return remoteConnection.isViewClosed(uuid);
- }
-
- /**
- * Returns whether the view was modified.
- */
- @Override
- public boolean isModified() {
- return modified;
- }
-
- /**
- * Returns whether the view is outdated, i.e., whether the underlying view
- * sources have changed.
- */
- @Override
- public boolean isOutdated() {
- return remoteConnection.isViewOutdated(uuid);
- }
-
- /**
- * Updates the view via the {@link VitruvRemoteConnection}, thus invalidating
- * its previous state and now providing
- * an updated view. This can only be done for an unmodified view.
- *
- * @throws UnsupportedOperationException If called on a modified view.
- * @throws IllegalStateException If called on a closed view.
- * @see #isClosed()
- * @see #isModified()
- */
- @Override
- public void update() {
- checkNotClosed();
- checkState(!isModified(), "cannot update from model when view is modified");
- removeChangeListeners(viewSource);
- viewSource = remoteConnection.updateView(uuid);
- modified = false;
- addChangeListeners(viewSource);
- }
-
- @Override
- public void close() {
- if (!isClosed()) {
- remoteConnection.closeView(uuid);
- viewSource.getResources().forEach(Resource::unload);
- viewSource.getResources().clear();
- removeChangeListeners(viewSource);
- }
- }
-
- /**
- * Persists the given object at the given {@link URI} and adds it as view root.
- */
- @Override
- public void registerRoot(EObject object, URI persistAt) {
- checkNotClosed();
- checkArgument(object != null, "object must not be null");
- checkArgument(persistAt != null, "URI for root must not be null");
- viewSource.createResource(persistAt).getContents().add(object);
- }
-
- /**
- * Moves the given object to the given {@link URI}. The given {@link EObject}
- * must already be a root object of the view, otherwise an
- * {@link IllegalStateException} is thrown.
- */
- @Override
- public void moveRoot(EObject object, URI newLocation) {
- checkNotClosed();
- checkArgument(object != null, "object to move must not be null");
- checkState(getRootObjects().contains(object), "view must contain element %s to move", object);
- checkArgument(newLocation != null, "URI for new location of root must not be null");
- viewSource.getResources().stream()
- .filter(it -> it.getContents().contains(object))
- .findFirst()
- .ifPresent(resource -> resource.setURI(newLocation));
- }
-
- /**
- * Returns the {@link ViewSelection} with which this view has been created.
- */
- @Override
- public ViewSelection getSelection() {
- return selector;
- }
-
- /**
- * UNSUPPORTED AT THE MOMENT!!
- */
- @Override
- public ViewType extends ViewSelector> getViewType() {
- // The client has no knowledge which view type was used to create the remote
- // view.
- // Additionally, the client is not able to create views.
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns a {@link CommittableView} based on the view's configuration.
- * Changes to commit are identified by recording any changes made to the view.
- *
- * @throws UnsupportedOperationException If called on a modified view.
- * @throws IllegalStateException If called on a closed view.
- * @see #isClosed()
- * @see #isModified()
- */
- @Override
- public CommittableView withChangeRecordingTrait() {
- checkNotClosed();
- return new ChangeRecordingRemoteView(this);
- }
-
- /**
- * Returns a {@link CommittableView} based on the view's configuration.
- * Changes to commit are identified by comparing the current view state with its
- * state from the last update.
- *
- * @param changeResolutionStrategy The change resolution strategy to use for
- * view state comparison. Must not be
- * null.
- * @throws UnsupportedOperationException If called on a modified view.
- * @throws IllegalStateException If called on a closed view.
- * @see #isClosed()
- * @see #isModified()
- */
- @Override
- public CommittableView withChangeDerivingTrait(StateBasedChangeResolutionStrategy changeResolutionStrategy) {
- checkNotClosed();
- return new ChangeDerivingRemoteView(this, changeResolutionStrategy);
- }
-
- void checkNotClosed() {
- checkState(!isClosed(), "view is already closed");
- }
-
- private void addChangeListeners(Notifier notifier) {
- notifier.eAdapters().add(new AdapterImpl() {
- @Override
- public void notifyChanged(Notification message) {
+ private final ViewSelector selector;
+
+ protected final String uuid;
+ protected final VitruvRemoteConnection remoteConnection;
+
+ protected ResourceSet viewSource;
+ protected boolean modified = false;
+
+ /**
+ * Creates a new {@link RemoteView}.
+ *
+ * @param uuid the unique identifier of the view
+ * @param viewSource the resource set representing the view's content
+ * @param selector the view selector used to create this view
+ * @param remoteConnection the remote connection to the Vitruvius server
+ */
+ RemoteView(
+ String uuid,
+ ResourceSet viewSource,
+ ViewSelector selector,
+ VitruvRemoteConnection remoteConnection) {
+ checkArgument(uuid != null, "uuid must not be null");
+ checkArgument(viewSource != null, "view source must not be null");
+ checkArgument(remoteConnection != null, "remote connection must not be null");
+ checkArgument(selector != null, "selector must not be null");
+ this.uuid = uuid;
+ this.remoteConnection = remoteConnection;
+ this.viewSource = viewSource;
+ this.selector = selector;
+
+ addChangeListeners(viewSource);
+ }
+
+ /**
+ * Provides the root model elements of this view.
+ *
+ * @throws IllegalStateException If called on a closed view.
+ * @see View#isClosed()
+ */
+ @Override
+ public Collection getRootObjects() {
+ checkNotClosed();
+ return viewSource.getResources().stream()
+ .map(Resource::getContents)
+ .flatMap(Collection::stream)
+ .toList();
+ }
+
+ /**
+ * Checks whether the view was closed. Closed views cannot be used further. All methods may throw
+ * an {@link IllegalStateException}.
+ */
+ @Override
+ public boolean isClosed() {
+ return remoteConnection.isViewClosed(uuid);
+ }
+
+ /** Returns whether the view was modified. */
+ @Override
+ public boolean isModified() {
+ return modified;
+ }
+
+ /**
+ * Returns whether the view is outdated, i.e., whether the underlying view sources have changed.
+ */
+ @Override
+ public boolean isOutdated() {
+ return remoteConnection.isViewOutdated(uuid);
+ }
+
+ /**
+ * Updates the view via the {@link VitruvRemoteConnection}, thus invalidating its previous state
+ * and now providing an updated view. This can only be done for an unmodified view.
+ *
+ * @throws UnsupportedOperationException If called on a modified view.
+ * @throws IllegalStateException If called on a closed view.
+ * @see #isClosed()
+ * @see #isModified()
+ */
+ @Override
+ public void update() {
+ checkNotClosed();
+ checkState(!isModified(), "cannot update from model when view is modified");
+ removeChangeListeners(viewSource);
+ viewSource = remoteConnection.updateView(uuid);
+ modified = false;
+ addChangeListeners(viewSource);
+ }
+
+ @Override
+ public void close() {
+ if (!isClosed()) {
+ remoteConnection.closeView(uuid);
+ viewSource.getResources().forEach(Resource::unload);
+ viewSource.getResources().clear();
+ removeChangeListeners(viewSource);
+ }
+ }
+
+ /** Persists the given object at the given {@link URI} and adds it as view root. */
+ @Override
+ public void registerRoot(EObject object, URI persistAt) {
+ checkNotClosed();
+ checkArgument(object != null, "object must not be null");
+ checkArgument(persistAt != null, "URI for root must not be null");
+ viewSource.createResource(persistAt).getContents().add(object);
+ }
+
+ /**
+ * Moves the given object to the given {@link URI}. The given {@link EObject} must already be a
+ * root object of the view, otherwise an {@link IllegalStateException} is thrown.
+ */
+ @Override
+ public void moveRoot(EObject object, URI newLocation) {
+ checkNotClosed();
+ checkArgument(object != null, "object to move must not be null");
+ checkState(getRootObjects().contains(object), "view must contain element %s to move", object);
+ checkArgument(newLocation != null, "URI for new location of root must not be null");
+ viewSource.getResources().stream()
+ .filter(it -> it.getContents().contains(object))
+ .findFirst()
+ .ifPresent(resource -> resource.setURI(newLocation));
+ }
+
+ /** Returns the {@link ViewSelection} with which this view has been created. */
+ @Override
+ public ViewSelection getSelection() {
+ return selector;
+ }
+
+ /** UNSUPPORTED AT THE MOMENT!!. */
+ @Override
+ public ViewType extends ViewSelector> getViewType() {
+ // The client has no knowledge which view type was used to create the remote
+ // view.
+ // Additionally, the client is not able to create views.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a {@link CommittableView} based on the view's configuration. Changes to commit are
+ * identified by recording any changes made to the view.
+ *
+ * @throws UnsupportedOperationException If called on a modified view.
+ * @throws IllegalStateException If called on a closed view.
+ * @see #isClosed()
+ * @see #isModified()
+ */
+ @Override
+ public CommittableView withChangeRecordingTrait() {
+ checkNotClosed();
+ return new ChangeRecordingRemoteView(this);
+ }
+
+ /**
+ * Returns a {@link CommittableView} based on the view's configuration. Changes to commit are
+ * identified by comparing the current view state with its state from the last update.
+ *
+ * @param changeResolutionStrategy The change resolution strategy to use for view state
+ * comparison. Must not be null.
+ * @throws UnsupportedOperationException If called on a modified view.
+ * @throws IllegalStateException If called on a closed view.
+ * @see #isClosed()
+ * @see #isModified()
+ */
+ @Override
+ public CommittableView withChangeDerivingTrait(
+ StateBasedChangeResolutionStrategy changeResolutionStrategy) {
+ checkNotClosed();
+ return new ChangeDerivingRemoteView(this, changeResolutionStrategy);
+ }
+
+ /** Checks that the view is not closed. */
+ void checkNotClosed() {
+ checkState(!isClosed(), "view is already closed");
+ }
+
+ private void addChangeListeners(Notifier notifier) {
+ notifier
+ .eAdapters()
+ .add(
+ new AdapterImpl() {
+ @Override
+ public void notifyChanged(Notification message) {
modified = true;
- }
- });
-
- if (notifier instanceof ResourceSet resourceSet) {
- resourceSet.getResources().forEach(this::addChangeListeners);
- } else if (notifier instanceof Resource resource) {
- resource.getContents().forEach(this::addChangeListeners);
- } else if (notifier instanceof EObject eObject) {
- eObject.eContents().forEach(this::addChangeListeners);
- }
- }
+ }
+ });
- private void removeChangeListeners(ResourceSet resourceSet) {
- resourceSet.getAllContents().forEachRemaining(it -> it.eAdapters().clear());
+ if (notifier instanceof ResourceSet resourceSet) {
+ resourceSet.getResources().forEach(this::addChangeListeners);
+ } else if (notifier instanceof Resource resource) {
+ resource.getContents().forEach(this::addChangeListeners);
+ } else if (notifier instanceof EObject eObject) {
+ eObject.eContents().forEach(this::addChangeListeners);
}
+ }
+
+ private void removeChangeListeners(ResourceSet resourceSet) {
+ resourceSet.getAllContents().forEachRemaining(it -> it.eAdapters().clear());
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewSelector.java b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewSelector.java
index 502f433..500fef0 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewSelector.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewSelector.java
@@ -1,93 +1,114 @@
package tools.vitruv.framework.remote.client.impl;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emfcloud.jackson.resource.JsonResource;
-
import tools.vitruv.framework.views.ModifiableViewSelection;
import tools.vitruv.framework.views.View;
import tools.vitruv.framework.views.ViewSelection;
import tools.vitruv.framework.views.ViewSelector;
import tools.vitruv.framework.views.selection.ElementViewSelection;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
/**
- * A selector for selecting the elements to be represented in a view, but on the Vitruvius client itself.
- * It is capable of acting as a builder for a view by providing an appropriate creation method, handling the remote connection.
+ * A selector for selecting the elements to be represented in a view, but on the Vitruvius client
+ * itself. It is capable of acting as a builder for a view by providing an appropriate creation
+ * method, handling the remote connection.
*/
public class RemoteViewSelector implements ViewSelector {
- private final String uuid;
- private final VitruvRemoteConnection remoteConnection;
- private final ModifiableViewSelection viewSelection;
+ private final String uuid;
+ private final VitruvRemoteConnection remoteConnection;
+ private final ModifiableViewSelection viewSelection;
- public RemoteViewSelector(String uuid, Resource selection, VitruvRemoteConnection remoteConnection) {
- this.uuid = uuid;
- this.remoteConnection = remoteConnection;
- this.viewSelection = new ElementViewSelection(selection.getContents());
- }
+ /**
+ * Creates a new {@link RemoteViewSelector}.
+ *
+ * @param uuid the unique identifier of the view
+ * @param selection the selection defining the elements to be included in the view
+ * @param remoteConnection the remote connection to the Vitruvius server
+ */
+ public RemoteViewSelector(
+ String uuid, Resource selection, VitruvRemoteConnection remoteConnection) {
+ this.uuid = uuid;
+ this.remoteConnection = remoteConnection;
+ this.viewSelection = new ElementViewSelection(selection.getContents());
+ }
- /**
- * Creates a view by delegating the request to the Vitruvius server, performing the selection done by this selector.
- *
- * @return The created view.
- */
- @Override
- public View createView() {
- return remoteConnection.getView(this);
- }
+ /**
+ * Creates a view by delegating the request to the Vitruvius server, performing the selection done
+ * by this selector.
+ *
+ * @return The created view.
+ */
+ @Override
+ public View createView() {
+ return remoteConnection.getView(this);
+ }
- @Override
- public boolean isValid() {
- return true;
- }
+ @Override
+ public boolean isValid() {
+ return true;
+ }
- @Override
- public ViewSelection getSelection() {
- return viewSelection;
- }
+ @Override
+ public ViewSelection getSelection() {
+ return viewSelection;
+ }
- @Override
- public Collection getSelectableElements() {
- return viewSelection.getSelectableElements();
- }
+ @Override
+ public Collection getSelectableElements() {
+ return viewSelection.getSelectableElements();
+ }
- @Override
- public boolean isSelected(EObject eObject) {
- return viewSelection.isSelected(eObject);
- }
+ @Override
+ public boolean isSelected(EObject eObject) {
+ return viewSelection.isSelected(eObject);
+ }
- @Override
- public boolean isSelectable(EObject eObject) {
- return viewSelection.isSelectable(eObject);
- }
+ @Override
+ public boolean isSelectable(EObject eObject) {
+ return viewSelection.isSelectable(eObject);
+ }
- @Override
- public void setSelected(EObject eObject, boolean selected) {
- viewSelection.setSelected(eObject, selected);
- }
+ @Override
+ public void setSelected(EObject eObject, boolean selected) {
+ viewSelection.setSelected(eObject, selected);
+ }
- @Override
- public boolean isViewObjectSelected(EObject eObject) {
- return viewSelection.getSelectableElements().stream().anyMatch(it ->
- EcoreUtil.equals(eObject, it) && viewSelection.isViewObjectSelected(it));
- }
+ @Override
+ public boolean isViewObjectSelected(EObject eObject) {
+ return viewSelection.getSelectableElements().stream()
+ .anyMatch(it -> EcoreUtil.equals(eObject, it) && viewSelection.isViewObjectSelected(it));
+ }
- String getUUID() {
- return this.uuid;
- }
+ /**
+ * Gets the UUID of the view to be created.
+ *
+ * @return The UUID.
+ */
+ String getUUID() {
+ return this.uuid;
+ }
- List getSelectionIds() {
- var ids = new LinkedList();
- viewSelection.getSelectableElements().forEach(it -> {
- if (viewSelection.isSelected(it)) {
- var resource = (JsonResource) it.eResource();
+ /**
+ * Gets the IDs of the selected elements in the selection.
+ *
+ * @return The list of IDs.
+ */
+ List getSelectionIds() {
+ var ids = new LinkedList();
+ viewSelection
+ .getSelectableElements()
+ .forEach(
+ it -> {
+ if (viewSelection.isSelected(it)) {
+ var resource = (JsonResource) it.eResource();
ids.add(resource.getID(it));
- }
- });
- return ids;
- }
+ }
+ });
+ return ids;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewType.java b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewType.java
index 3e9e597..fd49ac5 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewType.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/RemoteViewType.java
@@ -1,53 +1,63 @@
package tools.vitruv.framework.remote.client.impl;
import org.eclipse.emf.ecore.EPackage;
-
import tools.vitruv.framework.views.ChangeableViewSource;
import tools.vitruv.framework.views.ViewSelector;
import tools.vitruv.framework.views.ViewType;
/**
- * A Vitruvius view type representing actual types on the virtual model, but is
- * still capable of providing a view selector and allows creating
- * views by querying the Vitruvius server.
+ * A Vitruvius view type representing actual types on the virtual model, but is still capable of
+ * providing a view selector and allows creating views by querying the Vitruvius server.
*/
public class RemoteViewType implements ViewType {
- private final String name;
- private final VitruvRemoteConnection remoteConnection;
- private final EPackage metamodel;
-
- RemoteViewType(String name, VitruvRemoteConnection remoteConnection, EPackage metamodel) {
- this.name = name;
- this.remoteConnection = remoteConnection;
- this.metamodel = metamodel;
- }
-
- RemoteViewType(String name, VitruvRemoteConnection remoteConnection) {
- this.name = name;
- this.remoteConnection = remoteConnection;
- this.metamodel = null;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- /**
- * Returns the {@link ViewSelector} of the {@link ViewType}, which allows
- * configuring views by delegating the request to the Vitruvius server.
- *
- * @param viewSource Ignored, can be null.
- * @return A view selector for the view type represented by this remote view
- * type.
- */
- @Override
- public ViewSelector createSelector(ChangeableViewSource viewSource) {
- return remoteConnection.getSelector(name);
- }
-
- @Override
- public EPackage getMetamodel() {
- return this.metamodel;
- }
+ private final String name;
+ private final VitruvRemoteConnection remoteConnection;
+ private final EPackage metamodel;
+
+ /**
+ * Creates a new RemoteViewType.
+ *
+ * @param name the name of the view type
+ * @param remoteConnection the remote connection to the Vitruvius server
+ * @param metamodel the metamodel of the view type
+ */
+ RemoteViewType(String name, VitruvRemoteConnection remoteConnection, EPackage metamodel) {
+ this.name = name;
+ this.remoteConnection = remoteConnection;
+ this.metamodel = metamodel;
+ }
+
+ /**
+ * Creates a new RemoteViewType without metamodel.
+ *
+ * @param name the name of the view type
+ * @param remoteConnection the remote connection to the Vitruvius server
+ */
+ RemoteViewType(String name, VitruvRemoteConnection remoteConnection) {
+ this.name = name;
+ this.remoteConnection = remoteConnection;
+ this.metamodel = null;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the {@link ViewSelector} of the {@link ViewType}, which allows configuring views by
+ * delegating the request to the Vitruvius server.
+ *
+ * @param viewSource Ignored, can be null.
+ * @return A view selector for the view type represented by this remote view type.
+ */
+ @Override
+ public ViewSelector createSelector(ChangeableViewSource viewSource) {
+ return remoteConnection.getSelector(name);
+ }
+
+ @Override
+ public EPackage getMetamodel() {
+ return this.metamodel;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java
index 831de65..463eb2b 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/VitruvRemoteConnection.java
@@ -1,5 +1,7 @@
package tools.vitruv.framework.remote.client.impl;
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.core.instrument.Timer;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
@@ -17,8 +19,6 @@
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.emf.ecore.resource.ResourceSet;
-import io.micrometer.core.instrument.Metrics;
-import io.micrometer.core.instrument.Timer;
import tools.vitruv.change.atomic.root.InsertRootEObject;
import tools.vitruv.change.composite.description.VitruviusChange;
import tools.vitruv.change.utils.ProjectMarker;
@@ -39,268 +39,333 @@
* server. This enables the ability to perform actions on this remote Vitruvius instance.
*/
public class VitruvRemoteConnection implements VitruvClient {
- private static final String SUCCESS = "success";
- private static final String EXCEPTION = "exception";
- private static final String RESULT = "result";
- private static final String METHOD = "method";
- private static final String ENDPOINT = "endpoint";
- private static final String METRIC_CLIENT_NAME = "vitruv.client.rest.client";
- private final int port;
- private final String hostOrIp;
- private final String protocol;
- private final HttpClient client;
- private final JsonMapper mapper;
+ /** Constant for successful request result. */
+ private static final String SUCCESS = "success";
+
+ /** Constant for exception during request processing. */
+ private static final String EXCEPTION = "exception";
+
+ /** The constant result. */
+ private static final String RESULT = "result";
+
+ /** The method constant. */
+ private static final String METHOD = "method";
- /**
- * Creates a new {@link VitruvRemoteConnection} using the given URL and port to connect to the
- * Vitruvius server.
- *
- * @param protocol The protocol of the Vitruvius server.
- * @param hostOrIp The host name of IP address of the Vitruvius server.
- * @param port of the Vitruvius server.
- */
- public VitruvRemoteConnection(String protocol, String hostOrIp, int port, Path temp) {
- this.client = HttpClient.newHttpClient();
- this.protocol = protocol;
- this.hostOrIp = hostOrIp;
- this.port = port;
+ /** The endpoint constant. */
+ private static final String ENDPOINT = "endpoint";
- try {
- if (Files.notExists(temp) || (Files.isDirectory(temp) && isDirectoryEmpty(temp))) {
- Files.createDirectories(temp);
- ProjectMarker.markAsProjectRootFolder(temp);
- }
- } catch (IOException e) {
- throw new IllegalArgumentException(
- "Given temporary directory for models could not be created!", e);
- }
+ /** The metric client name. */
+ private static final String METRIC_CLIENT_NAME = "vitruv.client.rest.client";
- this.mapper = new JsonMapper(temp);
+ private final int port;
+ private final String hostOrIp;
+ private final String protocol;
+ private final HttpClient client;
+ private final JsonMapper mapper;
+
+ /**
+ * Creates a new {@link VitruvRemoteConnection} using the given URL and port to connect to the
+ * Vitruvius server.
+ *
+ * @param protocol The protocol of the Vitruvius server.
+ * @param hostOrIp The host name of IP address of the Vitruvius server.
+ * @param port of the Vitruvius server.
+ */
+ public VitruvRemoteConnection(String protocol, String hostOrIp, int port, Path temp) {
+ this.client = HttpClient.newHttpClient();
+ this.protocol = protocol;
+ this.hostOrIp = hostOrIp;
+ this.port = port;
+
+ try {
+ if (Files.notExists(temp) || (Files.isDirectory(temp) && isDirectoryEmpty(temp))) {
+ Files.createDirectories(temp);
+ ProjectMarker.markAsProjectRootFolder(temp);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ "Given temporary directory for models could not be created!", e);
}
- private boolean isDirectoryEmpty(Path directory) throws IOException {
- try (Stream entries = Files.list(directory)) {
- return entries.findAny().isEmpty();
- }
+ this.mapper = new JsonMapper(temp);
+ }
+
+ private boolean isDirectoryEmpty(Path directory) throws IOException {
+ try (Stream entries = Files.list(directory)) {
+ return entries.findAny().isEmpty();
}
+ }
- /**
- * Returns a list of remote representations of {@link ViewType}s available at the Vitruvius
- * server.
- */
- @Override
- public Collection> getViewTypes() {
- var request =
- HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW_TYPES)).GET().build();
- try {
- var response = sendRequest(request);
- var typeNames = mapper.deserializeArrayOf(response.body(), String.class);
- var list = new LinkedList>();
- typeNames.forEach(it -> list.add(new RemoteViewType(it, this)));
- return list;
- } catch (IOException e) {
- throw new BadClientResponseException(e);
- }
+ /**
+ * Returns a list of remote representations of {@link ViewType}s available at the Vitruvius
+ * server.
+ */
+ @Override
+ public Collection> getViewTypes() {
+ var request =
+ HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW_TYPES)).GET().build();
+ try {
+ var response = sendRequest(request);
+ var typeNames = mapper.deserializeArrayOf(response.body(), String.class);
+ var list = new LinkedList>();
+ typeNames.forEach(it -> list.add(new RemoteViewType(it, this)));
+ return list;
+ } catch (IOException e) {
+ throw new BadClientResponseException(e);
}
+ }
- /**
- * Returns a view selector for the given {@link ViewType} by querying the selector from the
- * Vitruvius server. The view type must be of type {@link RemoteViewType} as these represent the
- * actual view types available at the server side.
- *
- * @param viewType The {@link ViewType} to create a selector for.
- * @return A {@link ViewSelector} for the given view type.
- * @throws IllegalArgumentException If view type is no {@link RemoteViewType}.
- */
- @Override
- public S createSelector(ViewType viewType) {
- if (!(viewType instanceof RemoteViewType)) {
- throw new IllegalArgumentException(
- "This vitruv client can only process RemoteViewType!");
- }
- return viewType.createSelector(null);
+ /**
+ * Returns a view selector for the given {@link ViewType} by querying the selector from the
+ * Vitruvius server. The view type must be of type {@link RemoteViewType} as these represent the
+ * actual view types available at the server side.
+ *
+ * @param viewType The {@link ViewType} to create a selector for.
+ * @return A {@link ViewSelector} for the given view type.
+ * @throws IllegalArgumentException If view type is no {@link RemoteViewType}.
+ */
+ @Override
+ public S createSelector(ViewType viewType) {
+ if (!(viewType instanceof RemoteViewType)) {
+ throw new IllegalArgumentException("This vitruv client can only process RemoteViewType!");
}
+ return viewType.createSelector(null);
+ }
- /**
- * Queries the Vitruvius server to obtain a view selector from the view type with the given
- * name.
- *
- * @param typeName The name of the view type.
- * @return The selector generated with the view type of the given name.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- * @throws NoSuchElementException If the response headers do not contain the expected selector
- * UUID.
- */
- RemoteViewSelector getSelector(String typeName) throws BadServerResponseException {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW_SELECTOR))
- .header(Header.VIEW_TYPE, typeName).GET().build();
- try {
- var response = sendRequest(request);
- var resource = mapper.deserializeResource(response.body(), JsonFieldName.TEMP_VALUE,
- ResourceUtil.createJsonResourceSet());
- Optional selectorUuid = response.headers().firstValue(Header.SELECTOR_UUID);
- if (selectorUuid.isPresent()) {
- return new RemoteViewSelector(selectorUuid.get(), resource, this);
- } else {
- // Handle the case where the value is not present
- throw new NoSuchElementException(
- "Header.SELECTOR_UUID not found in response headers");
- }
- } catch (IOException e) {
- throw new BadClientResponseException(e);
- }
+ /**
+ * Queries the Vitruvius server to obtain a view selector from the view type with the given name.
+ *
+ * @param typeName The name of the view type.
+ * @return The selector generated with the view type of the given name.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ * @throws NoSuchElementException If the response headers do not contain the expected selector
+ * UUID.
+ */
+ RemoteViewSelector getSelector(String typeName) throws BadServerResponseException {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.VIEW_SELECTOR))
+ .header(Header.VIEW_TYPE, typeName)
+ .GET()
+ .build();
+ try {
+ var response = sendRequest(request);
+ var resource =
+ mapper.deserializeResource(
+ response.body(), JsonFieldName.TEMP_VALUE, ResourceUtil.createJsonResourceSet());
+ Optional selectorUuid = response.headers().firstValue(Header.SELECTOR_UUID);
+ if (selectorUuid.isPresent()) {
+ return new RemoteViewSelector(selectorUuid.get(), resource, this);
+ } else {
+ // Handle the case where the value is not present
+ throw new NoSuchElementException("Header.SELECTOR_UUID not found in response headers");
+ }
+ } catch (IOException e) {
+ throw new BadClientResponseException(e);
}
+ }
- /**
- * Queries the Vitruvius server to obtain the view using the given view selector.
- *
- * @param selector The {@link tools.vitruv.framework.views.ViewSelector} which should be used to
- * create the view.
- * @return The view generated with the given view selector.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- */
- RemoteView getView(RemoteViewSelector selector) throws BadServerResponseException {
- try {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW))
- .header(Header.SELECTOR_UUID, selector.getUUID())
- .POST(BodyPublishers.ofString(mapper.serialize(selector.getSelectionIds())))
- .build();
- var response = sendRequest(request);
- var rSet = mapper.deserialize(response.body(), ResourceSet.class);
- Optional viewUuid = response.headers().firstValue(Header.VIEW_UUID);
- if (viewUuid.isPresent()) {
- return new RemoteView(viewUuid.get(), rSet, selector, this);
- } else {
- // Handle the case where the value is not present
- throw new NoSuchElementException("Header.VIEW_UUID not found in response headers");
- }
- } catch (IOException e) {
- throw new BadClientResponseException(e);
- }
+ /**
+ * Queries the Vitruvius server to obtain the view using the given view selector.
+ *
+ * @param selector The {@link tools.vitruv.framework.views.ViewSelector} which should be used to
+ * create the view.
+ * @return The view generated with the given view selector.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ */
+ RemoteView getView(RemoteViewSelector selector) throws BadServerResponseException {
+ try {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.VIEW))
+ .header(Header.SELECTOR_UUID, selector.getUUID())
+ .POST(BodyPublishers.ofString(mapper.serialize(selector.getSelectionIds())))
+ .build();
+ var response = sendRequest(request);
+ var rSet = mapper.deserialize(response.body(), ResourceSet.class);
+ Optional viewUuid = response.headers().firstValue(Header.VIEW_UUID);
+ if (viewUuid.isPresent()) {
+ return new RemoteView(viewUuid.get(), rSet, selector, this);
+ } else {
+ // Handle the case where the value is not present
+ throw new NoSuchElementException("Header.VIEW_UUID not found in response headers");
+ }
+ } catch (IOException e) {
+ throw new BadClientResponseException(e);
}
+ }
- /**
- * Queries the Vitruvius server to propagate the given changes for the view with the given UUID.
- *
- * @param uuid UUID of the changed view.
- * @param change The changes performed on the affected view.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- */
- void propagateChanges(String uuid, VitruviusChange> change)
- throws BadServerResponseException {
- try {
- change.getEChanges().forEach(it -> {
+ /**
+ * Queries the Vitruvius server to propagate the given changes for the view with the given UUID.
+ *
+ * @param uuid UUID of the changed view.
+ * @param change The changes performed on the affected view.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ */
+ void propagateChanges(String uuid, VitruviusChange> change) throws BadServerResponseException {
+ try {
+ change
+ .getEChanges()
+ .forEach(
+ it -> {
if (it instanceof InsertRootEObject>) {
- ((InsertRootEObject>) it).setResource(null);
+ ((InsertRootEObject>) it).setResource(null);
}
- });
- var jsonBody = mapper.serialize(change);
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW))
- .header(Header.CONTENT_TYPE, ContentType.APPLICATION_JSON)
- .header(Header.VIEW_UUID, uuid)
- .method("PATCH", BodyPublishers.ofString(jsonBody)).build();
- sendRequest(request);
- } catch (IOException e) {
- throw new BadClientResponseException(e);
- }
+ });
+ var jsonBody = mapper.serialize(change);
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.VIEW))
+ .header(Header.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+ .header(Header.VIEW_UUID, uuid)
+ .method("PATCH", BodyPublishers.ofString(jsonBody))
+ .build();
+ sendRequest(request);
+ } catch (IOException e) {
+ throw new BadClientResponseException(e);
}
+ }
- /**
- * Queries the Vitruvius server to close the view with the given.
- *
- * @param uuid UUID of the view.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- */
- void closeView(String uuid) throws BadServerResponseException {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW))
- .header(Header.VIEW_UUID, uuid).DELETE().build();
- sendRequest(request);
- }
+ /**
+ * Queries the Vitruvius server to close the view with the given.
+ *
+ * @param uuid UUID of the view.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ */
+ void closeView(String uuid) throws BadServerResponseException {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.VIEW))
+ .header(Header.VIEW_UUID, uuid)
+ .DELETE()
+ .build();
+ sendRequest(request);
+ }
- /**
- * Queries the Vitruvius serve to check if the view with the given ID is closed.
- *
- * @param uuid UUID of the view.
- * @return {@code true} if the view is closed, {@code false} otherwise.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- */
- boolean isViewClosed(String uuid) throws BadServerResponseException {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.IS_VIEW_CLOSED))
- .header(Header.VIEW_UUID, uuid).GET().build();
- return sendRequestAndCheckBooleanResult(request);
- }
+ /**
+ * Queries the Vitruvius serve to check if the view with the given ID is closed.
+ *
+ * @param uuid UUID of the view.
+ * @return {@code true} if the view is closed, {@code false} otherwise.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ */
+ boolean isViewClosed(String uuid) throws BadServerResponseException {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.IS_VIEW_CLOSED))
+ .header(Header.VIEW_UUID, uuid)
+ .GET()
+ .build();
+ return sendRequestAndCheckBooleanResult(request);
+ }
- /**
- * Queries the Vitruvius server to check if the view with the given ID is outdated.
- *
- * @param uuid UUID of the view.
- * @return {@code true} if the view is outdated, {@code false} otherwise.
- */
- boolean isViewOutdated(String uuid) {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.IS_VIEW_OUTDATED))
- .header(Header.VIEW_UUID, uuid).GET().build();
- return sendRequestAndCheckBooleanResult(request);
- }
+ /**
+ * Queries the Vitruvius server to check if the view with the given ID is outdated.
+ *
+ * @param uuid UUID of the view.
+ * @return {@code true} if the view is outdated, {@code false} otherwise.
+ */
+ boolean isViewOutdated(String uuid) {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.IS_VIEW_OUTDATED))
+ .header(Header.VIEW_UUID, uuid)
+ .GET()
+ .build();
+ return sendRequestAndCheckBooleanResult(request);
+ }
- /**
- * Queries the Vitruvius server to update the view with the given ID.
- *
- * @param uuid UUID of the view.
- * @return The updated {@link ResourceSet} of the view.
- * @throws BadServerResponseException If the server answered with a bad response or a connection
- * error occurred.
- */
- ResourceSet updateView(String uuid) throws BadServerResponseException {
- var request = HttpRequest.newBuilder().uri(createURIFrom(EndpointPath.VIEW))
- .header(Header.VIEW_UUID, uuid).GET().build();
- try {
- var response = sendRequest(request);
- return mapper.deserialize(response.body(), ResourceSet.class);
- } catch (IOException e) {
- throw new BadClientResponseException(e);
- }
+ /**
+ * Queries the Vitruvius server to update the view with the given ID.
+ *
+ * @param uuid UUID of the view.
+ * @return The updated {@link ResourceSet} of the view.
+ * @throws BadServerResponseException If the server answered with a bad response or a connection
+ * error occurred.
+ */
+ ResourceSet updateView(String uuid) throws BadServerResponseException {
+ var request =
+ HttpRequest.newBuilder()
+ .uri(createURIFrom(EndpointPath.VIEW))
+ .header(Header.VIEW_UUID, uuid)
+ .GET()
+ .build();
+ try {
+ var response = sendRequest(request);
+ return mapper.deserialize(response.body(), ResourceSet.class);
+ } catch (IOException e) {
+ throw new BadClientResponseException(e);
}
+ }
- private boolean sendRequestAndCheckBooleanResult(HttpRequest request) {
- var response = sendRequest(request);
- if (!Objects.equals(response.body(), Boolean.TRUE.toString())
- && !Objects.equals(response.body(), Boolean.FALSE.toString())) {
- throw new BadServerResponseException(
- "Expected response to be true or false! Actual: " + response);
- }
- return response.body().equals(Boolean.TRUE.toString());
+ private boolean sendRequestAndCheckBooleanResult(HttpRequest request) {
+ var response = sendRequest(request);
+ if (!Objects.equals(response.body(), Boolean.TRUE.toString())
+ && !Objects.equals(response.body(), Boolean.FALSE.toString())) {
+ throw new BadServerResponseException(
+ "Expected response to be true or false! Actual: " + response);
}
+ return response.body().equals(Boolean.TRUE.toString());
+ }
- private HttpResponse sendRequest(HttpRequest request) {
- var timer = Timer.start(Metrics.globalRegistry);
- try {
- var response = client.send(request, BodyHandlers.ofString());
- if (response.statusCode() != HttpURLConnection.HTTP_OK) {
- timer.stop(Metrics.timer(METRIC_CLIENT_NAME, ENDPOINT, request.uri().getPath(),
- METHOD, request.method(), RESULT, "" + response.statusCode()));
- throw new BadServerResponseException(response.body(), response.statusCode());
- }
- timer.stop(Metrics.timer(METRIC_CLIENT_NAME, ENDPOINT, request.uri().getPath(),
- METHOD, request.method(), RESULT, SUCCESS));
- return response;
- } catch (IOException e) {
- timer.stop(Metrics.timer(METRIC_CLIENT_NAME, ENDPOINT, request.uri().getPath(),
- METHOD, request.method(), RESULT, EXCEPTION));
- throw new BadServerResponseException(e);
- } catch (InterruptedException e) {
- timer.stop(Metrics.timer(METRIC_CLIENT_NAME, ENDPOINT, request.uri().getPath(),
- METHOD, request.method(), RESULT, EXCEPTION));
- Thread.currentThread().interrupt(); // Re-interrupt the current thread
- throw new BadServerResponseException(e);
- }
+ private HttpResponse sendRequest(HttpRequest request) {
+ var timer = Timer.start(Metrics.globalRegistry);
+ try {
+ var response = client.send(request, BodyHandlers.ofString());
+ if (response.statusCode() != HttpURLConnection.HTTP_OK) {
+ timer.stop(
+ Metrics.timer(
+ METRIC_CLIENT_NAME,
+ ENDPOINT,
+ request.uri().getPath(),
+ METHOD,
+ request.method(),
+ RESULT,
+ "" + response.statusCode()));
+ throw new BadServerResponseException(response.body(), response.statusCode());
+ }
+ timer.stop(
+ Metrics.timer(
+ METRIC_CLIENT_NAME,
+ ENDPOINT,
+ request.uri().getPath(),
+ METHOD,
+ request.method(),
+ RESULT,
+ SUCCESS));
+ return response;
+ } catch (IOException e) {
+ timer.stop(
+ Metrics.timer(
+ METRIC_CLIENT_NAME,
+ ENDPOINT,
+ request.uri().getPath(),
+ METHOD,
+ request.method(),
+ RESULT,
+ EXCEPTION));
+ throw new BadServerResponseException(e);
+ } catch (InterruptedException e) {
+ timer.stop(
+ Metrics.timer(
+ METRIC_CLIENT_NAME,
+ ENDPOINT,
+ request.uri().getPath(),
+ METHOD,
+ request.method(),
+ RESULT,
+ EXCEPTION));
+ Thread.currentThread().interrupt(); // Re-interrupt the current thread
+ throw new BadServerResponseException(e);
}
+ }
- private URI createURIFrom(String path) {
- return URI.create(String.format("%s://%s:%d%s", protocol, hostOrIp, port, path));
- }
+ private URI createURIFrom(String path) {
+ return URI.create(String.format("%s://%s:%d%s", protocol, hostOrIp, port, path));
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/package-info.java
index 9d21012..07e7347 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/impl/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/impl/package-info.java
@@ -1,5 +1,5 @@
/**
- * In this package, the Vitruvius View API is re-implemented for the Vitruvius client.
- * Additionally, the package contains the remote connection handling.
+ * In this package, the Vitruvius View API is re-implemented for the Vitruvius client. Additionally,
+ * the package contains the remote connection handling.
*/
package tools.vitruv.framework.remote.client.impl;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/client/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/client/package-info.java
index 7dba503..67e2e76 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/client/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/client/package-info.java
@@ -1,4 +1,2 @@
-/**
- * This package provides the Vitruvius client.
- */
+/** This package provides the Vitruvius client. */
package tools.vitruv.framework.remote.client;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/DefaultConnectionSettings.java b/remote/src/main/java/tools/vitruv/framework/remote/common/DefaultConnectionSettings.java
index 4ca62b0..b504ce5 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/DefaultConnectionSettings.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/DefaultConnectionSettings.java
@@ -1,13 +1,18 @@
package tools.vitruv.framework.remote.common;
/**
- * Defines default settings for the connection between a Vitruvius server and client.
- * They are only used if no other settings are provided.
+ * Defines default settings for the connection between a Vitruvius server and client. They are only
+ * used if no other settings are provided.
*/
public class DefaultConnectionSettings {
- public static final String STD_PROTOCOL = "http";
- public static final String STD_HOST = "localhost";
- public static final int STD_PORT = 8080;
-
- private DefaultConnectionSettings() {}
+ /** The standard protocol used for the connection. */
+ public static final String STD_PROTOCOL = "http";
+
+ /** The standard host used for the connection. */
+ public static final String STD_HOST = "localhost";
+
+ /** The standard port used for the connection. */
+ public static final int STD_PORT = 8080;
+
+ private DefaultConnectionSettings() {}
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/SingleMeasureRecordingTimer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/SingleMeasureRecordingTimer.java
index 33b803f..39931d9 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/SingleMeasureRecordingTimer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/SingleMeasureRecordingTimer.java
@@ -1,56 +1,81 @@
package tools.vitruv.framework.remote.common.apm;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
import io.micrometer.core.instrument.step.StepTimer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
-/**
- * Provides a specialized {@link StepTimer}, which records every single
- * measurement.
- */
+/** Provides a specialized {@link StepTimer}, which records every single measurement. */
public class SingleMeasureRecordingTimer extends StepTimer {
- public static record SingleRecordedMeasure(long amount, TimeUnit unit) {
- }
-
- private List recordings = new ArrayList<>();
-
- public SingleMeasureRecordingTimer(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig,
- PauseDetector pauseDetector, TimeUnit baseTimeUnit, long stepDurationMillis,
- boolean supportsAggregablePercentiles) {
- super(id, clock, distributionStatisticConfig, pauseDetector, baseTimeUnit, stepDurationMillis,
- supportsAggregablePercentiles);
- }
-
- @Override
- protected void recordNonNegative(long amount, TimeUnit unit) {
- super.recordNonNegative(amount, unit);
- recordings.add(new SingleRecordedMeasure(amount, unit));
- }
-
- public List getRecordings() {
- return List.copyOf(recordings);
- }
-
- public void clear() {
- recordings.clear();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!(obj instanceof SingleMeasureRecordingTimer))
- return false;
- return super.equals(obj);
- }
-
- @Override
- public int hashCode() {
- return super.hashCode();
- }
+ public static record SingleRecordedMeasure(long amount, TimeUnit unit) {}
+
+ private final List recordings = new ArrayList<>();
+
+ /**
+ * Creates a new SingleMeasureRecordingTimer.
+ *
+ * @param id the id of the timer
+ * @param clock the clock to use
+ * @param distributionStatisticConfig the distribution statistic configuration
+ * @param pauseDetector the pause detector
+ * @param baseTimeUnit the base time unit
+ * @param stepDurationMillis the step duration in milliseconds
+ * @param supportsAggregablePercentiles whether the timer supports aggregable percentiles
+ */
+ public SingleMeasureRecordingTimer(
+ Id id,
+ Clock clock,
+ DistributionStatisticConfig distributionStatisticConfig,
+ PauseDetector pauseDetector,
+ TimeUnit baseTimeUnit,
+ long stepDurationMillis,
+ boolean supportsAggregablePercentiles) {
+ super(
+ id,
+ clock,
+ distributionStatisticConfig,
+ pauseDetector,
+ baseTimeUnit,
+ stepDurationMillis,
+ supportsAggregablePercentiles);
+ }
+
+ @Override
+ protected void recordNonNegative(long amount, TimeUnit unit) {
+ super.recordNonNegative(amount, unit);
+ recordings.add(new SingleRecordedMeasure(amount, unit));
+ }
+
+ /**
+ * Gets the list of single recorded measurements.
+ *
+ * @return the list of single recorded measurements
+ */
+ public List getRecordings() {
+ return List.copyOf(recordings);
+ }
+
+ /** Clears the recorded measurements. */
+ public void clear() {
+ recordings.clear();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SingleMeasureRecordingTimer)) {
+ return false;
+ }
+ return super.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvApmController.java b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvApmController.java
index 9e53e21..4407775 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvApmController.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvApmController.java
@@ -1,18 +1,16 @@
package tools.vitruv.framework.remote.common.apm;
-import java.nio.file.Path;
-
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Metrics;
+import java.nio.file.Path;
-/**
- * This class allows controlling the Vitruvius monitoring.
- */
+/** This class allows controlling the Vitruvius monitoring. */
public final class VitruvApmController {
private static VitruvStepMeterRegistry activeRegistry; // Use the same variable name consistently
/**
- * Constructor to initialize the monitoring (No initialization needed here, since we're using static methods).
+ * Constructor to initialize the monitoring (No initialization needed here, since we're using
+ * static methods).
*/
private VitruvApmController() {
// Private constructor to prevent instantiation
@@ -20,19 +18,18 @@ private VitruvApmController() {
/**
* Enables the monitoring for Vitruvius.
- *
+ *
* @param output Path to a file in which all measurements are stored.
*/
public static void enable(Path output) {
if (activeRegistry == null) { // Use the correct variable name here
- activeRegistry = new VitruvStepMeterRegistry(new VitruvStepRegistryConfig(), Clock.SYSTEM, output);
+ activeRegistry =
+ new VitruvStepMeterRegistry(new VitruvStepRegistryConfig(), Clock.SYSTEM, output);
Metrics.globalRegistry.add(activeRegistry); // Register the registry globally
}
}
- /**
- * Disables the monitoring for Vitruvius.
- */
+ /** Disables the monitoring for Vitruvius. */
public static void disable() {
if (activeRegistry != null) {
activeRegistry.stop(); // Stop the active registry
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistry.java b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistry.java
index c5cf42d..9db4f5d 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistry.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistry.java
@@ -1,12 +1,5 @@
package tools.vitruv.framework.remote.common.apm;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.concurrent.TimeUnit;
-
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter.Id;
import io.micrometer.core.instrument.Timer;
@@ -15,53 +8,71 @@
import io.micrometer.core.instrument.step.StepMeterRegistry;
import io.micrometer.core.instrument.step.StepRegistryConfig;
import io.micrometer.core.instrument.util.NamedThreadFactory;
-
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
- * Provides a specialized {@link StepMeterRegistry} for Vitruvius, which stores measurements in a file.
+ * Provides a specialized {@link StepMeterRegistry} for Vitruvius, which stores measurements in a
+ * file.
*/
class VitruvStepMeterRegistry extends StepMeterRegistry {
- private Path output;
- private StepRegistryConfig config;
- private static final Logger LOGGER = LogManager.getLogger(VitruvStepMeterRegistry.class);
+ private Path output;
+ private StepRegistryConfig config;
+ private static final Logger LOGGER = LogManager.getLogger(VitruvStepMeterRegistry.class);
- VitruvStepMeterRegistry(StepRegistryConfig config, Clock clock, Path output) {
- super(config, clock);
- this.output = output.toAbsolutePath();
- this.config = config;
- this.start(new NamedThreadFactory("vitruv-tf"));
- }
+ /**
+ * Creates a new {@link VitruvStepMeterRegistry}.
+ *
+ * @param config The step registry configuration.
+ * @param clock the clock to use.
+ * @param output Path to a file in which all measurements are stored.
+ */
+ VitruvStepMeterRegistry(StepRegistryConfig config, Clock clock, Path output) {
+ super(config, clock);
+ this.output = output.toAbsolutePath();
+ this.config = config;
+ this.start(new NamedThreadFactory("vitruv-tf"));
+ }
- @Override
- protected void publish() {
- try (BufferedWriter writer = Files.newBufferedWriter(output, StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
- for (var meter : getMeters()) {
- if (meter instanceof SingleMeasureRecordingTimer timer) {
- for (var recording : timer.getRecordings()) {
- writer.append(meter.getId().toString() + "," + recording.unit().toMillis(recording.amount()) + "\n");
- }
- timer.clear();
- } else {
- for (var measurement : meter.measure()) {
- writer.append(meter.getId().toString() + "," + measurement.getValue() + "\n");
- }
- }
- }
- } catch (IOException e) {
- LOGGER.error("Could not write metrics because: {}", e.getMessage());
- }
- }
+ @Override
+ protected void publish() {
+ try (BufferedWriter writer =
+ Files.newBufferedWriter(output, StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
+ for (var meter : getMeters()) {
+ if (meter instanceof SingleMeasureRecordingTimer timer) {
+ for (var recording : timer.getRecordings()) {
+ writer.append(
+ meter.getId().toString()
+ + ","
+ + recording.unit().toMillis(recording.amount())
+ + "\n");
+ }
+ timer.clear();
+ } else {
+ for (var measurement : meter.measure()) {
+ writer.append(meter.getId().toString() + "," + measurement.getValue() + "\n");
+ }
+ }
+ }
+ } catch (IOException e) {
+ LOGGER.error("Could not write metrics because: {}", e.getMessage());
+ }
+ }
- @Override
- protected TimeUnit getBaseTimeUnit() {
- return TimeUnit.MILLISECONDS;
- }
+ @Override
+ protected TimeUnit getBaseTimeUnit() {
+ return TimeUnit.MILLISECONDS;
+ }
- @Override
- protected Timer newTimer(Id id, DistributionStatisticConfig config, PauseDetector detector) {
- return new SingleMeasureRecordingTimer(id, this.clock, config, detector,
- getBaseTimeUnit(), this.config.step().toMillis(), false);
- }
+ @Override
+ protected Timer newTimer(Id id, DistributionStatisticConfig config, PauseDetector detector) {
+ return new SingleMeasureRecordingTimer(
+ id, this.clock, config, detector, getBaseTimeUnit(), this.config.step().toMillis(), false);
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepRegistryConfig.java b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepRegistryConfig.java
index 6293daa..33d8214 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepRegistryConfig.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/apm/VitruvStepRegistryConfig.java
@@ -2,14 +2,15 @@
import io.micrometer.core.instrument.step.StepRegistryConfig;
+/** Configuration for the Vitruvius step meter registry. */
class VitruvStepRegistryConfig implements StepRegistryConfig {
- @Override
- public String get(String arg0) {
- return null;
- }
+ @Override
+ public String get(String arg0) {
+ return null;
+ }
- @Override
- public String prefix() {
- return "vitruv-step-config";
- }
+ @Override
+ public String prefix() {
+ return "vitruv-step-config";
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/ChangeType.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/ChangeType.java
index 1dfaae6..6766bb4 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/ChangeType.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/ChangeType.java
@@ -4,28 +4,28 @@
import tools.vitruv.change.composite.description.TransactionalChange;
import tools.vitruv.change.composite.description.VitruviusChange;
-/**
- * Represents the type of the {@link VitruviusChange}.
- *
- * @see CompositeChange
- * @see TransactionalChange
- */
+/** An enumeration representing different types of Vitruvius changes. */
public enum ChangeType {
- TRANSACTIONAL, COMPOSITE, UNKNOWN;
+ /** Transaltional change type. */
+ TRANSACTIONAL,
+ /** Composite change type. */
+ COMPOSITE,
+ /** Unknown change type. */
+ UNKNOWN;
- /**
- * Returns the type of the given {@link VitruviusChange}.
- *
- * @param change The change to obtain the type from.
- * @return The type of the change.
- */
- public static ChangeType getChangeTypeOf(VitruviusChange> change) {
- if (change instanceof TransactionalChange) {
- return TRANSACTIONAL;
- }
- if (change instanceof CompositeChange, ?>) {
- return COMPOSITE;
- }
- return UNKNOWN;
+ /**
+ * Returns the type of the given {@link VitruviusChange}.
+ *
+ * @param change The change to obtain the type from.
+ * @return The type of the change.
+ */
+ public static ChangeType getChangeTypeOf(VitruviusChange> change) {
+ if (change instanceof TransactionalChange) {
+ return TRANSACTIONAL;
}
+ if (change instanceof CompositeChange, ?>) {
+ return COMPOSITE;
+ }
+ return UNKNOWN;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/IdTransformation.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/IdTransformation.java
index c663881..5f53498 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/IdTransformation.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/IdTransformation.java
@@ -2,81 +2,97 @@
import java.nio.file.Path;
import java.util.List;
-
import org.eclipse.emf.common.util.URI;
-
import tools.vitruv.change.atomic.EChange;
import tools.vitruv.change.atomic.hid.HierarchicalId;
import tools.vitruv.change.atomic.root.RootEChange;
import tools.vitruv.change.utils.ProjectMarker;
/**
- * Contains functions to transform IDs used by the Vitruvius framework to identify
- * {@link org.eclipse.emf.ecore.EObject EObjects}.
+ * Contains functions to transform IDs used by the Vitruvius framework to identify {@link
+ * org.eclipse.emf.ecore.EObject EObjects}.
*/
public class IdTransformation {
- private URI root;
-
- IdTransformation(Path vsumPath) {
- root = URI.createFileURI(ProjectMarker.getProjectRootFolder(vsumPath).toString());
-
- var nextToCheck = vsumPath;
- while ((nextToCheck = nextToCheck.getParent()) != null) {
- try {
- root = URI.createFileURI(ProjectMarker.getProjectRootFolder(nextToCheck).toString());
- } catch (IllegalStateException e) {
- break;
- }
- }
+ private URI root;
+
+ /**
+ * Creates a new IdTransformation.
+ *
+ * @param vsumPath the path to the .vsum file of the project
+ */
+ public IdTransformation(Path vsumPath) {
+ root = URI.createFileURI(ProjectMarker.getProjectRootFolder(vsumPath).toString());
+
+ var nextToCheck = vsumPath;
+ while ((nextToCheck = nextToCheck.getParent()) != null) {
+ try {
+ root = URI.createFileURI(ProjectMarker.getProjectRootFolder(nextToCheck).toString());
+ } catch (IllegalStateException e) {
+ break;
+ }
}
+ }
- /**
- * Transforms the given global (absolute path) ID to a local ID (relative path).
- *
- * @param global The ID to transform.
- * @return The local ID.
- */
- public URI toLocal(URI global) {
- if (global == null || global.toString().contains("cache") ||
- global.toString().equals(JsonFieldName.TEMP_VALUE) || !global.isFile()) {
- return global;
- }
-
- return URI.createURI(global.toString().replace(root.toString(), ""));
+ /**
+ * Transforms the given global (absolute path) ID to a local ID (relative path).
+ *
+ * @param global The ID to transform.
+ * @return The local ID.
+ */
+ public URI toLocal(URI global) {
+ if (global == null
+ || global.toString().contains("cache")
+ || global.toString().equals(JsonFieldName.TEMP_VALUE)
+ || !global.isFile()) {
+ return global;
}
- /**
- * Transforms the given local ID (relative path) to a global ID (absolute path).
- *
- * @param local The ID to transform.
- * @return The global ID.
- */
- public URI toGlobal(URI local) {
- if (local == null || local.toString().contains("cache") ||
- local.toString().equals(JsonFieldName.TEMP_VALUE)) {
- return local;
- }
-
- if (!local.isRelative()) {
- return local;
- }
-
- return URI.createURI(root.toString() + local.toString());
+ return URI.createURI(global.toString().replace(root.toString(), ""));
+ }
+
+ /**
+ * Transforms the given local ID (relative path) to a global ID (absolute path).
+ *
+ * @param local The ID to transform.
+ * @return The global ID.
+ */
+ public URI toGlobal(URI local) {
+ if (local == null
+ || local.toString().contains("cache")
+ || local.toString().equals(JsonFieldName.TEMP_VALUE)) {
+ return local;
}
- public void allToGlobal(List extends EChange> eChanges) {
- for (var eChange : eChanges) {
- if (eChange instanceof RootEChange> change) {
- change.setUri(toGlobal(URI.createURI(change.getUri())).toString());
- }
- }
+ if (!local.isRelative()) {
+ return local;
}
-
- public void allToLocal(List extends EChange> eChanges) {
- for (var eChange : eChanges) {
- if (eChange instanceof RootEChange> change) {
- change.setUri(toLocal(URI.createURI(change.getUri())).toString());
- }
- }
+
+ return URI.createURI(root.toString() + local.toString());
+ }
+
+ /**
+ * Transforms all root change URIs in the given list of changes to global IDs.
+ *
+ * @param eChanges the list of changes
+ */
+ public void allToGlobal(List extends EChange> eChanges) {
+ for (var eChange : eChanges) {
+ if (eChange instanceof RootEChange> change) {
+ change.setUri(toGlobal(URI.createURI(change.getUri())).toString());
+ }
+ }
+ }
+
+ /**
+ * Transforms all root change URIs in the given list of changes to local IDs.
+ *
+ * @param eChanges the list of changes
+ */
+ public void allToLocal(List extends EChange> eChanges) {
+ for (var eChange : eChanges) {
+ if (eChange instanceof RootEChange> change) {
+ change.setUri(toLocal(URI.createURI(change.getUri())).toString());
+ }
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonFieldName.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonFieldName.java
index 1b5e4ae..32782c9 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonFieldName.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonFieldName.java
@@ -1,15 +1,29 @@
package tools.vitruv.framework.remote.common.json;
+/** Field names used in JSON serialization and deserialization. */
public final class JsonFieldName {
- public static final String CHANGE_TYPE = "changeType";
- public static final String E_CHANGES = "eChanges";
- public static final String V_CHANGES = "vChanges";
- public static final String U_INTERACTIONS = "uInteractions";
- public static final String TEMP_VALUE = "temp";
- public static final String CONTENT = "content";
- public static final String URI = "uri";
-
- private JsonFieldName() throws InstantiationException {
- throw new InstantiationException("Cannot be instantiated");
- }
+ /** The field name for the change type. */
+ public static final String CHANGE_TYPE = "changeType";
+
+ /** The field name for eChanges. */
+ public static final String E_CHANGES = "eChanges";
+
+ /** The field name for vChanges. */
+ public static final String V_CHANGES = "vChanges";
+
+ /** The field name for user interactions. */
+ public static final String U_INTERACTIONS = "uInteractions";
+
+ /** The field name for temporary values. */
+ public static final String TEMP_VALUE = "temp";
+
+ /** The field name for content. */
+ public static final String CONTENT = "content";
+
+ /** The field name for URI. */
+ public static final String URI = "uri";
+
+ private JsonFieldName() throws InstantiationException {
+ throw new InstantiationException("Cannot be instantiated");
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonMapper.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonMapper.java
index a7c7833..ff7b4bb 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonMapper.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/JsonMapper.java
@@ -1,9 +1,12 @@
package tools.vitruv.framework.remote.common.json;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
-
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
@@ -11,12 +14,6 @@
import org.eclipse.emfcloud.jackson.databind.EMFContext;
import org.eclipse.emfcloud.jackson.module.EMFModule;
import org.eclipse.emfcloud.jackson.module.EMFModule.Feature;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-
import tools.vitruv.change.composite.description.VitruviusChange;
import tools.vitruv.framework.remote.common.json.deserializer.ReferenceDeserializerModifier;
import tools.vitruv.framework.remote.common.json.deserializer.ResourceSetDeserializer;
@@ -26,90 +23,110 @@
import tools.vitruv.framework.remote.common.json.serializer.VitruviusChangeSerializer;
/**
- * This mapper can be used to serialize objects and deserialize JSON in the context of Vitruvius.
- * It has custom De-/Serializers for {@link ResourceSet}s, {@link Resource}s and {@link VitruviusChange}s.
+ * This mapper can be used to serialize objects and deserialize JSON in the context of Vitruvius. It
+ * has custom De-/Serializers for {@link ResourceSet}s, {@link Resource}s and {@link
+ * VitruviusChange}s.
*/
public class JsonMapper {
- private final ObjectMapper mapper = new ObjectMapper();
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ /**
+ * Creates a new JsonMapper.
+ *
+ * @param vsumPath the path to the .vsum file of the project
+ */
+ public JsonMapper(Path vsumPath) {
+ final var transformation = new IdTransformation(vsumPath);
+
+ mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
+ var module = new EMFModule();
+
+ // Register serializer
+ module.addSerializer(ResourceSet.class, new ResourceSetSerializer(transformation));
+ module.addSerializer(VitruviusChange.class, new VitruviusChangeSerializer());
+
+ // Register deserializer
+ module.addDeserializer(ResourceSet.class, new ResourceSetDeserializer(this, transformation));
+ module.addDeserializer(
+ VitruviusChange.class, new VitruviusChangeDeserializer(this, transformation));
+
+ // Register modifiers for references to handle HierarichalId
+ module.setSerializerModifier(new ReferenceSerializerModifier(transformation));
+ module.setDeserializerModifier(new ReferenceDeserializerModifier(transformation));
+
+ // Use IDs to identify eObjects on client and server
+ module.configure(Feature.OPTION_USE_ID, true);
+ module.setIdentityInfo(new EcoreIdentityInfo("_id"));
- public JsonMapper(Path vsumPath) {
- final var transformation = new IdTransformation(vsumPath);
-
- mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
- var module = new EMFModule();
-
- //Register serializer
- module.addSerializer(ResourceSet.class, new ResourceSetSerializer(transformation));
- module.addSerializer(VitruviusChange.class, new VitruviusChangeSerializer());
+ mapper.registerModule(module);
+ }
- //Register deserializer
- module.addDeserializer(ResourceSet.class, new ResourceSetDeserializer(this, transformation));
- module.addDeserializer(VitruviusChange.class, new VitruviusChangeDeserializer(this, transformation));
-
- //Register modifiers for references to handle HierarichalId
- module.setSerializerModifier(new ReferenceSerializerModifier(transformation));
- module.setDeserializerModifier(new ReferenceDeserializerModifier(transformation));
-
- //Use IDs to identify eObjects on client and server
- module.configure(Feature.OPTION_USE_ID, true);
- module.setIdentityInfo(new EcoreIdentityInfo("_id"));
+ /**
+ * Serializes the given object.
+ *
+ * @param obj The object to serialize.
+ * @return The JSON or {@code null} if an {@link JsonProcessingException} occurred.
+ */
+ public String serialize(Object obj) throws JsonProcessingException {
+ return mapper.writeValueAsString(obj);
+ }
- mapper.registerModule(module);
- }
+ /**
+ * Deserializes the given JSON string.
+ *
+ * @param The type of the returned object.
+ * @param json The JSON to deserialize.
+ * @param clazz The class of the JSON type.
+ * @return The object or {@code null} if an {@link JsonProcessingException} occurred.
+ */
+ public T deserialize(String json, Class clazz) throws JsonProcessingException {
+ return mapper.reader().forType(clazz).readValue(json);
+ }
- /**
- * Serializes the given object.
- *
- * @param obj The object to serialize.
- * @return The JSON or {@code null} if an {@link JsonProcessingException} occurred.
- */
- public String serialize(Object obj) throws JsonProcessingException {
- return mapper.writeValueAsString(obj);
- }
+ /**
+ * Deserializes the given JSON node.
+ *
+ * @param The type of the returned object.
+ * @param json The JSON node to deserialize.
+ * @param clazz The class of the JSON type.
+ * @return The object.
+ * @throws JsonProcessingException If the JSON node cannot be processed.
+ * @throws IOException If there is an IO exception during deserialization.
+ */
+ public T deserialize(JsonNode json, Class clazz)
+ throws JsonProcessingException, IOException {
+ return mapper.reader().forType(clazz).readValue(json);
+ }
- /**
- * Deserializes the given JSON string.
- *
- * @param The type of the returned object.
- * @param json The JSON to deserialize.
- * @param clazz The class of the JSON type.
- * @return The object or {@code null} if an {@link JsonProcessingException} occurred.
- */
- public T deserialize(String json, Class clazz) throws JsonProcessingException {
- return mapper.reader().forType(clazz).readValue(json);
- }
-
- /**
- * Deserializes the given JSON node.
- *
- * @param The type of the returned object.
- * @param json The JSON node to deserialize.
- * @param clazz The class of the JSON type.
- * @return The object.
- * @throws JsonProcessingException If the JSON node cannot be processed.
- * @throws IOException If there is an IO exception during deserialization.
- */
- public T deserialize(JsonNode json, Class clazz) throws JsonProcessingException, IOException {
- return mapper.reader().forType(clazz).readValue(json);
- }
-
- public Resource deserializeResource(String json, String uri, ResourceSet parentSet) throws JsonProcessingException {
- return mapper.reader()
- .withAttribute(EMFContext.Attributes.RESOURCE_SET, parentSet)
- .withAttribute(EMFContext.Attributes.RESOURCE_URI, URI.createURI(uri))
- .forType(Resource.class)
- .readValue(json);
- }
+ /**
+ * Deserializes the given JSON string to a Resource.
+ *
+ * @param json The JSON string representing the Resource.
+ * @param uri The URI of the Resource.
+ * @param parentSet The parent ResourceSet of the Resource.
+ * @return The deserialized Resource.
+ * @throws JsonProcessingException If an error occurs during deserialization.
+ */
+ public Resource deserializeResource(String json, String uri, ResourceSet parentSet)
+ throws JsonProcessingException {
+ return mapper
+ .reader()
+ .withAttribute(EMFContext.Attributes.RESOURCE_SET, parentSet)
+ .withAttribute(EMFContext.Attributes.RESOURCE_URI, URI.createURI(uri))
+ .forType(Resource.class)
+ .readValue(json);
+ }
- /**
- * Deserializes the given JSON array to a list.
- *
- * @param json The JSON array to deserialize.
- * @param clazz The class representing the JSON type of the objects in the JSON array.
- * @return The list of objects or {@code null} if an {@link JsonProcessingException} occurred.
- */
- public List deserializeArrayOf(String json, Class clazz) throws JsonProcessingException {
- var javaType = mapper.getTypeFactory().constructCollectionType(List.class, clazz);
- return mapper.readValue(json, javaType);
- }
+ /**
+ * Deserializes the given JSON array to a list.
+ *
+ * @param json The JSON array to deserialize.
+ * @param clazz The class representing the JSON type of the objects in the JSON array.
+ * @return The list of objects or {@code null} if an {@link JsonProcessingException} occurred.
+ */
+ public List deserializeArrayOf(String json, Class clazz)
+ throws JsonProcessingException {
+ var javaType = mapper.getTypeFactory().constructCollectionType(List.class, clazz);
+ return mapper.readValue(json, javaType);
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/HidReferenceEntry.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/HidReferenceEntry.java
index 4c6f014..3739b01 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/HidReferenceEntry.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/HidReferenceEntry.java
@@ -1,28 +1,34 @@
package tools.vitruv.framework.remote.common.json.deserializer;
+import com.fasterxml.jackson.databind.DatabindContext;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emfcloud.jackson.databind.deser.ReferenceEntry;
import org.eclipse.emfcloud.jackson.handlers.URIHandler;
import org.eclipse.emfcloud.jackson.utils.EObjects;
-
-import com.fasterxml.jackson.databind.DatabindContext;
-
import tools.vitruv.change.atomic.hid.HierarchicalId;
+/** A {@link ReferenceEntry} for hierarchical IDs (HIDs). */
public class HidReferenceEntry implements ReferenceEntry {
- private final EObject owner;
- private final EReference reference;
- private final String hid;
-
- public HidReferenceEntry(EObject owner, EReference reference, String hid) {
- this.owner = owner;
- this.reference = reference;
- this.hid = hid;
- }
+ private final EObject owner;
+ private final EReference reference;
+ private final String hid;
+
+ /**
+ * Creates a new {@link HidReferenceEntry}.
+ *
+ * @param owner the owner EObject
+ * @param reference the EReference
+ * @param hid the hierarchical ID as a string
+ */
+ public HidReferenceEntry(EObject owner, EReference reference, String hid) {
+ this.owner = owner;
+ this.reference = reference;
+ this.hid = hid;
+ }
- @Override
- public void resolve(DatabindContext context, URIHandler handler) {
- EObjects.setOrAdd(owner, reference, new HierarchicalId(hid));
- }
+ @Override
+ public void resolve(DatabindContext context, URIHandler handler) {
+ EObjects.setOrAdd(owner, reference, new HierarchicalId(hid));
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ReferenceDeserializerModifier.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ReferenceDeserializerModifier.java
index a6e83a7..3279a29 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ReferenceDeserializerModifier.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ReferenceDeserializerModifier.java
@@ -1,28 +1,35 @@
package tools.vitruv.framework.remote.common.json.deserializer;
-import org.eclipse.emfcloud.jackson.databind.deser.EcoreReferenceDeserializer;
-
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.type.ReferenceType;
-
+import org.eclipse.emfcloud.jackson.databind.deser.EcoreReferenceDeserializer;
import tools.vitruv.framework.remote.common.json.IdTransformation;
+/** A {@link BeanDeserializerModifier} that modifies reference deserializers to use. */
public class ReferenceDeserializerModifier extends BeanDeserializerModifier {
- private final transient IdTransformation transformation;
-
- public ReferenceDeserializerModifier(IdTransformation transformation) {
- this.transformation = transformation;
- }
+ private final transient IdTransformation transformation;
+
+ /**
+ * Creates a new ReferenceDeserializerModifier.
+ *
+ * @param transformation the id transformation to be used
+ */
+ public ReferenceDeserializerModifier(IdTransformation transformation) {
+ this.transformation = transformation;
+ }
- @Override
- public JsonDeserializer> modifyReferenceDeserializer(DeserializationConfig config, ReferenceType type,
- BeanDescription beanDesc, JsonDeserializer> deserializer) {
- if (deserializer instanceof EcoreReferenceDeserializer referenceDeserializer) {
- return new HierarichalIdDeserializer(referenceDeserializer, transformation);
- }
- return deserializer;
- }
+ @Override
+ public JsonDeserializer> modifyReferenceDeserializer(
+ DeserializationConfig config,
+ ReferenceType type,
+ BeanDescription beanDesc,
+ JsonDeserializer> deserializer) {
+ if (deserializer instanceof EcoreReferenceDeserializer referenceDeserializer) {
+ return new HierarichalIdDeserializer(referenceDeserializer, transformation);
+ }
+ return deserializer;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ResourceSetDeserializer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ResourceSetDeserializer.java
index 4b095e1..3b0cb37 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ResourceSetDeserializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/ResourceSetDeserializer.java
@@ -1,43 +1,50 @@
package tools.vitruv.framework.remote.common.json.deserializer;
-import java.io.IOException;
-import java.util.Map;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.ResourceSet;
-
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
-
+import java.io.IOException;
+import java.util.Map;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.ResourceSet;
import tools.vitruv.framework.remote.common.json.IdTransformation;
import tools.vitruv.framework.remote.common.json.JsonFieldName;
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.util.ResourceUtil;
+/** A deserializer for {@link ResourceSet}. */
public class ResourceSetDeserializer extends JsonDeserializer {
- private final IdTransformation transformation;
- private final JsonMapper mapper;
-
- public ResourceSetDeserializer(JsonMapper mapper, IdTransformation transformation) {
- this.transformation = transformation;
- this.mapper = mapper;
- }
+ private final IdTransformation transformation;
+ private final JsonMapper mapper;
+
+ /**
+ * Creates a new ResourceSetDeserializer.
+ *
+ * @param mapper The json mapper to be used.
+ * @param transformation the id transformation to be used
+ */
+ public ResourceSetDeserializer(JsonMapper mapper, IdTransformation transformation) {
+ this.transformation = transformation;
+ this.mapper = mapper;
+ }
+
+ @Override
+ public ResourceSet deserialize(JsonParser parser, DeserializationContext context)
+ throws IOException {
+ var rootNode = (ArrayNode) parser.getCodec().readTree(parser);
- @Override
- public ResourceSet deserialize(JsonParser parser, DeserializationContext context) throws IOException {
- var rootNode = (ArrayNode) parser.getCodec().readTree(parser);
-
- var resourceSet = ResourceUtil.createJsonResourceSet();
- for (var e : rootNode) {
- var resource = mapper.deserializeResource(e.get(JsonFieldName.CONTENT).toString(),
- transformation.toGlobal(URI.createURI(e.get(JsonFieldName.URI).asText())).toString(), resourceSet);
- if (!resource.getURI().toString().equals(JsonFieldName.TEMP_VALUE)) {
- resource.save(Map.of());
- }
- }
-
- return resourceSet;
- }
+ var resourceSet = ResourceUtil.createJsonResourceSet();
+ for (var e : rootNode) {
+ var resource =
+ mapper.deserializeResource(
+ e.get(JsonFieldName.CONTENT).toString(),
+ transformation.toGlobal(URI.createURI(e.get(JsonFieldName.URI).asText())).toString(),
+ resourceSet);
+ if (!resource.getURI().toString().equals(JsonFieldName.TEMP_VALUE)) {
+ resource.save(Map.of());
+ }
+ }
+ return resourceSet;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/VitruviusChangeDeserializer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/VitruviusChangeDeserializer.java
index 299f7d1..641c51a 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/VitruviusChangeDeserializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/deserializer/VitruviusChangeDeserializer.java
@@ -1,15 +1,13 @@
package tools.vitruv.framework.remote.common.json.deserializer;
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.TextNode;
-
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
import tools.vitruv.change.atomic.EChange;
import tools.vitruv.change.atomic.hid.HierarchicalId;
import tools.vitruv.change.composite.description.TransactionalChange;
@@ -22,40 +20,56 @@
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.util.ResourceUtil;
+/** A deserializer for {@link VitruviusChange}. */
public class VitruviusChangeDeserializer extends JsonDeserializer> {
- private final IdTransformation transformation;
- private final JsonMapper mapper;
-
- public VitruviusChangeDeserializer(JsonMapper mapper, IdTransformation transformation) {
- this.mapper = mapper;
- this.transformation = transformation;
- }
+ private final IdTransformation transformation;
+ private final JsonMapper mapper;
+
+ /**
+ * Creates a new VitruviusChangeDeserializer.
+ *
+ * @param mapper the json mapper to be used
+ * @param transformation the id transformation to be used
+ */
+ public VitruviusChangeDeserializer(JsonMapper mapper, IdTransformation transformation) {
+ this.mapper = mapper;
+ this.transformation = transformation;
+ }
- @Override
- public VitruviusChange> deserialize(JsonParser parser, DeserializationContext context) throws IOException {
- var rootNode = parser.getCodec().readTree(parser);
- var type = ChangeType.valueOf(((TextNode)rootNode.get(JsonFieldName.CHANGE_TYPE)).asText());
+ @Override
+ public VitruviusChange> deserialize(JsonParser parser, DeserializationContext context)
+ throws IOException {
+ var rootNode = parser.getCodec().readTree(parser);
+ var type = ChangeType.valueOf(((TextNode) rootNode.get(JsonFieldName.CHANGE_TYPE)).asText());
- VitruviusChange> change;
- if (type == ChangeType.TRANSACTIONAL) {
- var resourceNode = rootNode.get(JsonFieldName.E_CHANGES);
- var changesResource = mapper.deserializeResource(resourceNode.toString(), JsonFieldName.TEMP_VALUE, ResourceUtil.createJsonResourceSet());
- @SuppressWarnings("unchecked")
- List> changes = changesResource.getContents().stream().map(e -> (EChange) e).toList();
- transformation.allToGlobal(changes);
- change = VitruviusChangeFactory.getInstance().createTransactionalChange(changes);
- var interactions = mapper.deserializeArrayOf(rootNode.get(JsonFieldName.U_INTERACTIONS).toString(), UserInteractionBase.class);
- ((TransactionalChange>) change).setUserInteractions(interactions);
- } else if (type == ChangeType.COMPOSITE) {
- var changesNode = (ArrayNode) rootNode.get(JsonFieldName.V_CHANGES);
- var changes = new LinkedList>();
- for (var e : changesNode) {
- changes.add(mapper.deserialize(e, VitruviusChange.class));
- }
- change = VitruviusChangeFactory.getInstance().createCompositeChange(changes);
- } else {
- throw new UnsupportedOperationException("Change deserialization for type" + type + " not implemented!");
- }
- return change;
+ VitruviusChange> change;
+ if (type == ChangeType.TRANSACTIONAL) {
+ var resourceNode = rootNode.get(JsonFieldName.E_CHANGES);
+ var changesResource =
+ mapper.deserializeResource(
+ resourceNode.toString(),
+ JsonFieldName.TEMP_VALUE,
+ ResourceUtil.createJsonResourceSet());
+ @SuppressWarnings("unchecked")
+ List> changes =
+ changesResource.getContents().stream().map(e -> (EChange) e).toList();
+ transformation.allToGlobal(changes);
+ change = VitruviusChangeFactory.getInstance().createTransactionalChange(changes);
+ var interactions =
+ mapper.deserializeArrayOf(
+ rootNode.get(JsonFieldName.U_INTERACTIONS).toString(), UserInteractionBase.class);
+ ((TransactionalChange>) change).setUserInteractions(interactions);
+ } else if (type == ChangeType.COMPOSITE) {
+ var changesNode = (ArrayNode) rootNode.get(JsonFieldName.V_CHANGES);
+ var changes = new LinkedList>();
+ for (var e : changesNode) {
+ changes.add(mapper.deserialize(e, VitruviusChange.class));
+ }
+ change = VitruviusChangeFactory.getInstance().createCompositeChange(changes);
+ } else {
+ throw new UnsupportedOperationException(
+ "Change deserialization for type" + type + " not implemented!");
}
+ return change;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/HierarichalIdSerializer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/HierarichalIdSerializer.java
index 4af5b67..0f60b82 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/HierarichalIdSerializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/HierarichalIdSerializer.java
@@ -1,33 +1,39 @@
package tools.vitruv.framework.remote.common.json.serializer;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
-
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emfcloud.jackson.databind.ser.EcoreReferenceSerializer;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-
import tools.vitruv.change.atomic.hid.HierarchicalId;
import tools.vitruv.framework.remote.common.json.IdTransformation;
-public class HierarichalIdSerializer extends JsonSerializer{
- private final EcoreReferenceSerializer standardSerializer;
- private final IdTransformation transformation;
-
- public HierarichalIdSerializer(EcoreReferenceSerializer standardDeserializer, IdTransformation transformation) {
- this.standardSerializer = standardDeserializer;
- this.transformation = transformation;
- }
+/** A serializer for {@link HierarchicalId}. */
+public class HierarichalIdSerializer extends JsonSerializer {
+ private final EcoreReferenceSerializer standardSerializer;
+ private final IdTransformation transformation;
+
+ /**
+ * Creates a new HierarichalIdSerializer.
+ *
+ * @param standardDeserializer the standard deserializer
+ * @param transformation the id transformation to be used
+ */
+ public HierarichalIdSerializer(
+ EcoreReferenceSerializer standardDeserializer, IdTransformation transformation) {
+ this.standardSerializer = standardDeserializer;
+ this.transformation = transformation;
+ }
- @Override
- public void serialize(EObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- if (value instanceof HierarchicalId hid) {
- gen.writeString(transformation.toLocal(URI.createURI(hid.getId())).toString());
- } else {
- standardSerializer.serialize(value, gen, serializers);
- }
- }
+ @Override
+ public void serialize(EObject value, JsonGenerator gen, SerializerProvider serializers)
+ throws IOException {
+ if (value instanceof HierarchicalId hid) {
+ gen.writeString(transformation.toLocal(URI.createURI(hid.getId())).toString());
+ } else {
+ standardSerializer.serialize(value, gen, serializers);
+ }
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ReferenceSerializerModifier.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ReferenceSerializerModifier.java
index ec49a60..c2f005c 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ReferenceSerializerModifier.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ReferenceSerializerModifier.java
@@ -1,26 +1,31 @@
package tools.vitruv.framework.remote.common.json.serializer;
-import org.eclipse.emfcloud.jackson.databind.ser.EcoreReferenceSerializer;
-
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
-
+import org.eclipse.emfcloud.jackson.databind.ser.EcoreReferenceSerializer;
import tools.vitruv.framework.remote.common.json.IdTransformation;
+/** A {@link BeanSerializerModifier} that modifies reference serializers to use. */
public class ReferenceSerializerModifier extends BeanSerializerModifier {
- private final transient IdTransformation transformation;
-
- public ReferenceSerializerModifier(IdTransformation transformation) {
- this.transformation = transformation;
- }
+ private final transient IdTransformation transformation;
+
+ /**
+ * Creates a new ReferenceSerializerModifier.
+ *
+ * @param transformation the id transformation to be used
+ */
+ public ReferenceSerializerModifier(IdTransformation transformation) {
+ this.transformation = transformation;
+ }
- @Override
- public JsonSerializer> modifySerializer(SerializationConfig config, BeanDescription desc, JsonSerializer> serializer) {
- if (serializer instanceof EcoreReferenceSerializer referenceSerializer) {
- return new HierarichalIdSerializer(referenceSerializer, transformation);
- }
- return serializer;
- }
+ @Override
+ public JsonSerializer> modifySerializer(
+ SerializationConfig config, BeanDescription desc, JsonSerializer> serializer) {
+ if (serializer instanceof EcoreReferenceSerializer referenceSerializer) {
+ return new HierarichalIdSerializer(referenceSerializer, transformation);
+ }
+ return serializer;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ResourceSetSerializer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ResourceSetSerializer.java
index ddec8a8..a1547f9 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ResourceSetSerializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/ResourceSetSerializer.java
@@ -1,33 +1,38 @@
package tools.vitruv.framework.remote.common.json.serializer;
-import java.io.IOException;
-
-import org.eclipse.emf.ecore.resource.ResourceSet;
-
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
-
+import java.io.IOException;
+import org.eclipse.emf.ecore.resource.ResourceSet;
import tools.vitruv.framework.remote.common.json.IdTransformation;
import tools.vitruv.framework.remote.common.json.JsonFieldName;
+/** A serializer for {@link ResourceSet}. */
public class ResourceSetSerializer extends JsonSerializer {
- private final IdTransformation transformation;
-
- public ResourceSetSerializer(IdTransformation transformation) {
- this.transformation = transformation;
- }
+ private final IdTransformation transformation;
+
+ /**
+ * Creates a new ResourceSetSerializer.
+ *
+ * @param transformation the id transformation to be used
+ */
+ public ResourceSetSerializer(IdTransformation transformation) {
+ this.transformation = transformation;
+ }
- @Override
- public void serialize(ResourceSet resourceSet, JsonGenerator generator, SerializerProvider provider) throws IOException {
- generator.writeStartArray();
- var resources = resourceSet.getResources();
- for (var r : resources) {
- generator.writeStartObject();
- generator.writeObjectField(JsonFieldName.URI, transformation.toLocal(r.getURI()).toString());
- generator.writeObjectField(JsonFieldName.CONTENT, r);
- generator.writeEndObject();
- }
- generator.writeEndArray();
+ @Override
+ public void serialize(
+ ResourceSet resourceSet, JsonGenerator generator, SerializerProvider provider)
+ throws IOException {
+ generator.writeStartArray();
+ var resources = resourceSet.getResources();
+ for (var r : resources) {
+ generator.writeStartObject();
+ generator.writeObjectField(JsonFieldName.URI, transformation.toLocal(r.getURI()).toString());
+ generator.writeObjectField(JsonFieldName.CONTENT, r);
+ generator.writeEndObject();
}
+ generator.writeEndArray();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/VitruviusChangeSerializer.java b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/VitruviusChangeSerializer.java
index 1b1a25a..0ad4d96 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/VitruviusChangeSerializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/json/serializer/VitruviusChangeSerializer.java
@@ -1,13 +1,10 @@
package tools.vitruv.framework.remote.common.json.serializer;
-import java.io.IOException;
-
-import org.eclipse.emf.common.util.URI;
-
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
-
+import java.io.IOException;
+import org.eclipse.emf.common.util.URI;
import tools.vitruv.change.composite.description.CompositeChange;
import tools.vitruv.change.composite.description.TransactionalChange;
import tools.vitruv.change.composite.description.VitruviusChange;
@@ -15,27 +12,36 @@
import tools.vitruv.framework.remote.common.json.JsonFieldName;
import tools.vitruv.framework.remote.common.util.ResourceUtil;
+/** A serializer for {@link VitruviusChange}. */
@SuppressWarnings("rawtypes")
public class VitruviusChangeSerializer extends JsonSerializer {
- @Override
- public void serialize(VitruviusChange vitruviusChange, JsonGenerator generator, SerializerProvider provider) throws IOException {
- generator.writeStartObject();
- generator.writeStringField(JsonFieldName.CHANGE_TYPE, ChangeType.getChangeTypeOf(vitruviusChange).toString());
- if (vitruviusChange instanceof TransactionalChange> tc) {
- var changesResource = ResourceUtil.createResourceWith(URI.createURI(JsonFieldName.TEMP_VALUE), tc.getEChanges());
- generator.writeFieldName(JsonFieldName.E_CHANGES);
- generator.writeObject(changesResource);
- generator.writeObjectField(JsonFieldName.U_INTERACTIONS,tc.getUserInteractions());
- } else if (vitruviusChange instanceof CompositeChange, ?> cc) {
- var changes = cc.getChanges();
- generator.writeArrayFieldStart(JsonFieldName.V_CHANGES);
- for (var change : changes) {
- generator.writeObject(change);
- }
- generator.writeEndArray();
- } else {
- throw new UnsupportedOperationException("Change serialization of type " + vitruviusChange.getClass().getName() + " not implemented!");
- }
- generator.writeEndObject();
+ @Override
+ public void serialize(
+ VitruviusChange vitruviusChange, JsonGenerator generator, SerializerProvider provider)
+ throws IOException {
+ generator.writeStartObject();
+ generator.writeStringField(
+ JsonFieldName.CHANGE_TYPE, ChangeType.getChangeTypeOf(vitruviusChange).toString());
+ if (vitruviusChange instanceof TransactionalChange> tc) {
+ var changesResource =
+ ResourceUtil.createResourceWith(
+ URI.createURI(JsonFieldName.TEMP_VALUE), tc.getEChanges());
+ generator.writeFieldName(JsonFieldName.E_CHANGES);
+ generator.writeObject(changesResource);
+ generator.writeObjectField(JsonFieldName.U_INTERACTIONS, tc.getUserInteractions());
+ } else if (vitruviusChange instanceof CompositeChange, ?> cc) {
+ var changes = cc.getChanges();
+ generator.writeArrayFieldStart(JsonFieldName.V_CHANGES);
+ for (var change : changes) {
+ generator.writeObject(change);
+ }
+ generator.writeEndArray();
+ } else {
+ throw new UnsupportedOperationException(
+ "Change serialization of type "
+ + vitruviusChange.getClass().getName()
+ + " not implemented!");
}
+ generator.writeEndObject();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/ContentType.java b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/ContentType.java
index df580b4..415b342 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/ContentType.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/ContentType.java
@@ -1,10 +1,14 @@
package tools.vitruv.framework.remote.common.rest.constants;
+/** A class holding constants for content types used in REST communication. */
public final class ContentType {
- public static final String APPLICATION_JSON = "application/json";
- public static final String TEXT_PLAIN = "text/plain";
-
- private ContentType() throws InstantiationException {
- throw new InstantiationException("Cannot be instantiated");
- }
+ /** The content type for JSON data. */
+ public static final String APPLICATION_JSON = "application/json";
+
+ /** The content type for plain text data. */
+ public static final String TEXT_PLAIN = "text/plain";
+
+ private ContentType() throws InstantiationException {
+ throw new InstantiationException("Cannot be instantiated");
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/EndpointPath.java b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/EndpointPath.java
index 08518ca..1137e4c 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/EndpointPath.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/EndpointPath.java
@@ -1,14 +1,29 @@
package tools.vitruv.framework.remote.common.rest.constants;
+/** Constants for endpoint paths used in the Vitruvius remote framework. */
public final class EndpointPath {
- public static final String HEALTH = "/health";
- public static final String VIEW_TYPES = "/vsum/view/types";
- public static final String VIEW_SELECTOR = "/vsum/view/selector";
- public static final String VIEW = "/vsum/view";
- public static final String IS_VIEW_CLOSED = "/vsum/view/closed";
- public static final String IS_VIEW_OUTDATED = "/vsum/view/outdated";
-
- private EndpointPath() throws InstantiationException {
- throw new InstantiationException("Cannot be instantiated");
- }
+ /** The health check endpoint path. */
+ public static final String HEALTH = "/health";
+
+ /** The endpoint path for view types. */
+ public static final String VIEW_TYPES = "/vsum/view/types";
+
+ /** The endpoint path for view selectors. */
+ public static final String VIEW_SELECTOR = "/vsum/view/selector";
+
+ /** The endpoint path for views. */
+ public static final String VIEW = "/vsum/view";
+
+ /** The endpoint path to check if a view is closed. */
+ public static final String IS_VIEW_CLOSED = "/vsum/view/closed";
+
+ /** The endpoint path to check if a view is outdated. */
+ public static final String IS_VIEW_OUTDATED = "/vsum/view/outdated";
+
+ /** The endpoint path for deriving changes. */
+ public static final String CHANGE_DERIVING = "/vsum/view/derive-changes";
+
+ private EndpointPath() throws InstantiationException {
+ throw new InstantiationException("Cannot be instantiated");
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/Header.java b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/Header.java
index f05faea..758e6a0 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/Header.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/common/rest/constants/Header.java
@@ -1,12 +1,20 @@
package tools.vitruv.framework.remote.common.rest.constants;
+/** Constants for HTTP headers used in the Vitruv Remote Framework. */
public final class Header {
- public static final String CONTENT_TYPE = "Content-Type";
- public static final String VIEW_UUID = "View-UUID";
- public static final String SELECTOR_UUID = "Selector-UUID";
- public static final String VIEW_TYPE = "View-Type";
-
- private Header() throws InstantiationException {
- throw new InstantiationException("Cannot be instantiated");
- }
+ /** The Content-Type header key. */
+ public static final String CONTENT_TYPE = "Content-Type";
+
+ /** The View-UUID header key. */
+ public static final String VIEW_UUID = "View-UUID";
+
+ /** The Selector-UUID header key. */
+ public static final String SELECTOR_UUID = "Selector-UUID";
+
+ /** The View-Type header key. */
+ public static final String VIEW_TYPE = "View-Type";
+
+ private Header() throws InstantiationException {
+ throw new InstantiationException("Cannot be instantiated");
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/VirtualModelInitializer.java b/remote/src/main/java/tools/vitruv/framework/remote/server/VirtualModelInitializer.java
index a0bb6bf..53cb4ec 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/VirtualModelInitializer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/VirtualModelInitializer.java
@@ -2,16 +2,14 @@
import tools.vitruv.framework.vsum.VirtualModel;
-/**
- * Interface for virtual model initialization.
- */
+/** Interface for virtual model initialization. */
@FunctionalInterface
-public interface VirtualModelInitializer {
-
- /**
- * Initializes the virtual model and returns it.
- *
- * @return the initialized model.
- */
- VirtualModel init();
+public interface VirtualModelInitializer {
+
+ /**
+ * Initializes the virtual model and returns it.
+ *
+ * @return the initialized model.
+ */
+ VirtualModel init();
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/VitruvServer.java b/remote/src/main/java/tools/vitruv/framework/remote/server/VitruvServer.java
index f9526b1..ca530b4 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/VitruvServer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/VitruvServer.java
@@ -1,70 +1,69 @@
package tools.vitruv.framework.remote.server;
import java.io.IOException;
-
+import java.util.List;
import tools.vitruv.framework.remote.common.DefaultConnectionSettings;
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.server.http.java.VitruvJavaHttpServer;
+import tools.vitruv.framework.remote.server.rest.PathEndointCollector;
import tools.vitruv.framework.remote.server.rest.endpoints.EndpointsProvider;
import tools.vitruv.framework.vsum.VirtualModel;
/**
- * A Vitruvius server wraps a REST-based API around a {@link VirtualModel VSUM}. Therefore,
- * it takes a {@link VirtualModelInitializer} which is responsible to create an instance
- * of a {@link VirtualModel virtual model}. Once the server is started, the API can be used by the
- * Vitruvius client to perform remote actions on the VSUM.
+ * A Vitruvius server wraps a REST-based API around a {@link VirtualModel VSUM}. Therefore, it takes
+ * a {@link VirtualModelInitializer} which is responsible to create an instance of a {@link
+ * VirtualModel virtual model}. Once the server is started, the API can be used by the Vitruvius
+ * client to perform remote actions on the VSUM.
*/
public class VitruvServer {
- private final VitruvJavaHttpServer server;
+ private final VitruvJavaHttpServer server;
+
+ /**
+ * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}. Sets host
+ * name or IP address and port which are used to open the server.
+ *
+ * @param modelInitializer The initializer which creates an {@link VirtualModel}.
+ * @param port The port to open to server on.
+ * @param hostOrIp The host name or IP address to which the server is bound.
+ */
+ public VitruvServer(VirtualModelInitializer modelInitializer, int port, String hostOrIp)
+ throws IOException {
+ VirtualModel model = modelInitializer.init();
+ JsonMapper mapper = new JsonMapper(model.getFolder());
+ List endpoints = EndpointsProvider.getAllEndpoints(model, mapper);
- /**
- * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}.
- * Sets host name or IP address and port which are used to open the server.
- *
- * @param modelInitializer The initializer which creates an {@link VirtualModel}.
- * @param port The port to open to server on.
- * @param hostOrIp The host name or IP address to which the server is bound.
- */
- public VitruvServer(VirtualModelInitializer modelInitializer, int port, String hostOrIp) throws IOException {
- var model = modelInitializer.init();
- var mapper = new JsonMapper(model.getFolder());
- var endpoints = EndpointsProvider.getAllEndpoints(model, mapper);
+ this.server = new VitruvJavaHttpServer(hostOrIp, port, endpoints);
+ }
- this.server = new VitruvJavaHttpServer(hostOrIp, port, endpoints);
- }
-
- /**
- * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}.
- * Sets the port which is used to open the server on to the given one.
- *
- * @param modelInitializer The initializer which creates an {@link VirtualModel}.
- * @param port The port to open to server on.
- */
- public VitruvServer(VirtualModelInitializer modelInitializer, int port) throws IOException {
- this(modelInitializer, port, DefaultConnectionSettings.STD_HOST);
- }
+ /**
+ * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}. Sets the
+ * port which is used to open the server on to the given one.
+ *
+ * @param modelInitializer The initializer which creates an {@link VirtualModel}.
+ * @param port The port to open to server on.
+ */
+ public VitruvServer(VirtualModelInitializer modelInitializer, int port) throws IOException {
+ this(modelInitializer, port, DefaultConnectionSettings.STD_HOST);
+ }
- /**
- * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}.
- * Sets the port which is used to open the server on to 8080.
- *
- * @param modelInitializer The initializer which creates an {@link tools.vitruv.framework.vsum.internal.InternalVirtualModel}.
- */
- public VitruvServer(VirtualModelInitializer modelInitializer) throws IOException {
- this(modelInitializer, DefaultConnectionSettings.STD_PORT);
- }
+ /**
+ * Creates a new {@link VitruvServer} using the given {@link VirtualModelInitializer}. Sets the
+ * port which is used to open the server on to 8080.
+ *
+ * @param modelInitializer The initializer which creates an {@link
+ * tools.vitruv.framework.vsum.internal.InternalVirtualModel}.
+ */
+ public VitruvServer(VirtualModelInitializer modelInitializer) throws IOException {
+ this(modelInitializer, DefaultConnectionSettings.STD_PORT);
+ }
- /**
- * Starts the Vitruvius server.
- */
- public void start() {
- server.start();
- }
+ /** Starts the Vitruvius server. */
+ public void start() {
+ server.start();
+ }
- /**
- * Stops the Vitruvius server.
- */
- public void stop() {
- server.stop();
- }
+ /** Stops the Vitruvius server. */
+ public void stop() {
+ server.stop();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/exception/ServerHaltingException.java b/remote/src/main/java/tools/vitruv/framework/remote/server/exception/ServerHaltingException.java
index c874352..b605f0b 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/exception/ServerHaltingException.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/exception/ServerHaltingException.java
@@ -1,20 +1,32 @@
package tools.vitruv.framework.remote.server.exception;
/**
- * Represents an exception which should be thrown when the processing of a REST-request is halted due to an error.
- * An HTTP-status code must be provided, since this exception is caught by the
- * {@link tools.vitruv.framework.remote.server.VitruvServer Server} in order to create error response messages.
+ * Represents an exception which should be thrown when the processing of a REST-request is halted
+ * due to an error. An HTTP-status code must be provided, since this exception is caught by the
+ * {@link tools.vitruv.framework.remote.server.VitruvServer Server} in order to create error
+ * response messages.
*/
public class ServerHaltingException extends RuntimeException {
- private final int statusCode;
+ private final int statusCode;
- public ServerHaltingException(int statusCode, String msg) {
- super(msg);
- this.statusCode = statusCode;
- }
+ /**
+ * Creates a new {@link ServerHaltingException}.
+ *
+ * @param statusCode the HTTP status code representing the error
+ * @param msg the error message
+ */
+ public ServerHaltingException(int statusCode, String msg) {
+ super(msg);
+ this.statusCode = statusCode;
+ }
- public int getStatusCode() {
- return statusCode;
- }
+ /**
+ * Returns the HTTP status code representing the error.
+ *
+ * @return the HTTP status code
+ */
+ public int getStatusCode() {
+ return statusCode;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/exception/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/exception/package-info.java
index 75a10c7..af3f6cd 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/exception/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/exception/package-info.java
@@ -1,4 +1,2 @@
-/**
- * Defines exceptions for the Vitruvius server.
- */
+/** Defines exceptions for the Vitruvius server. */
package tools.vitruv.framework.remote.server.exception;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/HttpWrapper.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/HttpWrapper.java
index 3f5d425..1bb3dc1 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/HttpWrapper.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/HttpWrapper.java
@@ -2,51 +2,53 @@
import java.io.IOException;
-/**
- * This interface wraps an HTTP request/response from the underlying HTTP server implementation.
- */
+/** This interface wraps an HTTP request/response from the underlying HTTP server implementation. */
public interface HttpWrapper {
- /**
- * Returns a response header.
- *
- * @param header Name of the header.
- * @return The value of the header.
- */
- String getRequestHeader(String header);
- /**
- * Returns the request body converted to a String.
- *
- * @return The request body as String.
- * @throws IOException If the body cannot be read or if the conversion fails.
- */
- String getRequestBodyAsString() throws IOException;
-
- /**
- * Adds a value to the response header.
- *
- * @param header Name of the header.
- * @param value The value of the header to add.
- */
- void addResponseHeader(String header, String value);
- /**
- * Sets the content type of the response.
- *
- * @param type The content type.
- */
- void setContentType(String type);
- /**
- * Sends an HTTP response without a body.
- *
- * @param responseCode The status code of the response.
- * @throws IOException If the response cannot be sent.
- */
- void sendResponse(int responseCode) throws IOException;
- /**
- * Sends an HTTP response with a body.
- *
- * @param responseCode The status code of the response.
- * @param body The body of the response.
- * @throws IOException If the response cannot be sent.
- */
- void sendResponse(int responseCode, byte[] body) throws IOException;
+ /**
+ * Returns a response header.
+ *
+ * @param header Name of the header.
+ * @return The value of the header.
+ */
+ String getRequestHeader(String header);
+
+ /**
+ * Returns the request body converted to a String.
+ *
+ * @return The request body as String.
+ * @throws IOException If the body cannot be read or if the conversion fails.
+ */
+ String getRequestBodyAsString() throws IOException;
+
+ /**
+ * Adds a value to the response header.
+ *
+ * @param header Name of the header.
+ * @param value The value of the header to add.
+ */
+ void addResponseHeader(String header, String value);
+
+ /**
+ * Sets the content type of the response.
+ *
+ * @param type The content type.
+ */
+ void setContentType(String type);
+
+ /**
+ * Sends an HTTP response without a body.
+ *
+ * @param responseCode The status code of the response.
+ * @throws IOException If the response cannot be sent.
+ */
+ void sendResponse(int responseCode) throws IOException;
+
+ /**
+ * Sends an HTTP response with a body.
+ *
+ * @param responseCode The status code of the response.
+ * @param body The body of the response.
+ * @throws IOException If the response cannot be sent.
+ */
+ void sendResponse(int responseCode, byte[] body) throws IOException;
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/HttpExchangeWrapper.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/HttpExchangeWrapper.java
index 0bc9745..ad63796 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/HttpExchangeWrapper.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/HttpExchangeWrapper.java
@@ -1,55 +1,56 @@
package tools.vitruv.framework.remote.server.http.java;
import com.sun.net.httpserver.HttpExchange;
-
-import tools.vitruv.framework.remote.common.rest.constants.Header;
-import tools.vitruv.framework.remote.server.http.HttpWrapper;
-
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import tools.vitruv.framework.remote.common.rest.constants.Header;
+import tools.vitruv.framework.remote.server.http.HttpWrapper;
-/**
- * This is an implementation of the {@link HttpWrapper} for the Java built-in HTTP server.
- */
+/** This is an implementation of the {@link HttpWrapper} for the Java built-in HTTP server. */
class HttpExchangeWrapper implements HttpWrapper {
- private final HttpExchange exchange;
-
- HttpExchangeWrapper(HttpExchange exchange) {
- this.exchange = exchange;
- }
-
- @Override
- public void addResponseHeader(String header, String value) {
- exchange.getResponseHeaders().add(header, value);
- }
-
- @Override
- public void setContentType(String type) {
- exchange.getResponseHeaders().replace(Header.CONTENT_TYPE, List.of(type));
- }
-
- @Override
- public String getRequestHeader(String header) {
- return exchange.getRequestHeaders().getFirst(header);
- }
-
- @Override
- public String getRequestBodyAsString() throws IOException {
- return new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
- }
-
- @Override
- public void sendResponse(int responseCode) throws IOException {
- exchange.sendResponseHeaders(responseCode, -1);
- }
-
- @Override
- public void sendResponse(int responseCode, byte[] body) throws IOException {
- exchange.sendResponseHeaders(responseCode, body.length);
- var outputStream = exchange.getResponseBody();
- outputStream.write(body);
- outputStream.flush();
- outputStream.close();
- }
+ private final HttpExchange exchange;
+
+ /**
+ * Creates a new {@link HttpExchangeWrapper}.
+ *
+ * @param exchange The {@link HttpExchange} to wrap.
+ */
+ public HttpExchangeWrapper(HttpExchange exchange) {
+ this.exchange = exchange;
+ }
+
+ @Override
+ public void addResponseHeader(String header, String value) {
+ exchange.getResponseHeaders().add(header, value);
+ }
+
+ @Override
+ public void setContentType(String type) {
+ exchange.getResponseHeaders().replace(Header.CONTENT_TYPE, List.of(type));
+ }
+
+ @Override
+ public String getRequestHeader(String header) {
+ return exchange.getRequestHeaders().getFirst(header);
+ }
+
+ @Override
+ public String getRequestBodyAsString() throws IOException {
+ return new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public void sendResponse(int responseCode) throws IOException {
+ exchange.sendResponseHeaders(responseCode, -1);
+ }
+
+ @Override
+ public void sendResponse(int responseCode, byte[] body) throws IOException {
+ exchange.sendResponseHeaders(responseCode, body.length);
+ var outputStream = exchange.getResponseBody();
+ outputStream.write(body);
+ outputStream.flush();
+ outputStream.close();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/RequestHandler.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/RequestHandler.java
index 263f624..5672199 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/RequestHandler.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/RequestHandler.java
@@ -1,62 +1,67 @@
package tools.vitruv.framework.remote.server.http.java;
+import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_OK;
+
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
-
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
import tools.vitruv.framework.remote.server.rest.PathEndointCollector;
-import java.nio.charset.StandardCharsets;
-
-import static java.net.HttpURLConnection.*;
-
-import java.io.IOException;
-
-/**
- * Represents an {@link HttpHandler}.
- */
+/** Represents an {@link HttpHandler}. */
class RequestHandler implements HttpHandler {
- private PathEndointCollector endpoints;
+ private PathEndointCollector endpoints;
- RequestHandler(PathEndointCollector endpoints) {
- this.endpoints = endpoints;
- }
+ /**
+ * Creates a new {@link RequestHandler}.
+ *
+ * @param endpoints The endpoint collector providing the endpoints to handle requests.
+ */
+ RequestHandler(PathEndointCollector endpoints) {
+ this.endpoints = endpoints;
+ }
- /**
- * Handles the request when this end point is called.
- *
- * @param exchange An object encapsulating the HTTP request and response.
- */
- @Override
- public void handle(HttpExchange exchange) {
- var method = exchange.getRequestMethod();
- var wrapper = new HttpExchangeWrapper(exchange);
- try {
- var response = switch (method) {
- case "GET" -> endpoints.getEndpoint().process(wrapper);
- case "PUT" -> endpoints.putEndpoint().process(wrapper);
- case "POST" -> endpoints.postEndpoint().process(wrapper);
- case "PATCH" -> endpoints.patchEndpoint().process(wrapper);
- case "DELETE" -> endpoints.deleteEndpoint().process(wrapper);
- default -> throw new ServerHaltingException(HTTP_NOT_FOUND, "Request method not supported!");
- };
- if (response != null) {
- wrapper.sendResponse(HTTP_OK, response.getBytes(StandardCharsets.UTF_8));
- } else {
- wrapper.sendResponse(HTTP_OK);
- }
- } catch (Exception exception) {
- var statusCode = HTTP_INTERNAL_ERROR;
- if (exception instanceof ServerHaltingException haltingException) {
- statusCode = haltingException.getStatusCode();
- }
- wrapper.setContentType(ContentType.TEXT_PLAIN);
- try {
- wrapper.sendResponse(statusCode, exception.getMessage().getBytes(StandardCharsets.UTF_8));
- } catch (IOException e) {
- throw new IllegalStateException("Sending a response (" + statusCode + " " + exception.getMessage() + ") failed.", e);
- }
- }
+ /**
+ * Handles the request when this end point is called.
+ *
+ * @param exchange An object encapsulating the HTTP request and response.
+ */
+ @Override
+ public void handle(HttpExchange exchange) {
+ var method = exchange.getRequestMethod();
+ var wrapper = new HttpExchangeWrapper(exchange);
+ try {
+ var response =
+ switch (method) {
+ case "GET" -> endpoints.getEndpoint().process(wrapper);
+ case "PUT" -> endpoints.putEndpoint().process(wrapper);
+ case "POST" -> endpoints.postEndpoint().process(wrapper);
+ case "PATCH" -> endpoints.patchEndpoint().process(wrapper);
+ case "DELETE" -> endpoints.deleteEndpoint().process(wrapper);
+ default ->
+ throw new ServerHaltingException(HTTP_NOT_FOUND, "Request method not supported!");
+ };
+ if (response != null) {
+ wrapper.sendResponse(HTTP_OK, response.getBytes(StandardCharsets.UTF_8));
+ } else {
+ wrapper.sendResponse(HTTP_OK);
+ }
+ } catch (IOException | ServerHaltingException exception) {
+ var statusCode = HTTP_INTERNAL_ERROR;
+ if (exception instanceof ServerHaltingException haltingException) {
+ statusCode = haltingException.getStatusCode();
+ }
+ wrapper.setContentType(ContentType.TEXT_PLAIN);
+ try {
+ wrapper.sendResponse(statusCode, exception.getMessage().getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new IllegalStateException(
+ "Sending a response (" + statusCode + " " + exception.getMessage() + ") failed.", e);
+ }
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/VitruvJavaHttpServer.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/VitruvJavaHttpServer.java
index 0b067ac..0d8f47e 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/VitruvJavaHttpServer.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/VitruvJavaHttpServer.java
@@ -7,18 +7,24 @@
import tools.vitruv.framework.remote.server.rest.PathEndointCollector;
public class VitruvJavaHttpServer {
- private final HttpServer server;
+ private final HttpServer server;
- public VitruvJavaHttpServer(String host, int port, List endpoints) throws IOException {
- this.server = HttpServer.create(new InetSocketAddress(host, port), 0);
- endpoints.forEach(endp -> server.createContext(endp.path(), new RequestHandler(endp)));
- }
+ /**
+ * Creates a Vitruvius HTTP server on the given host and port, registering the given endpoints.
+ */
+ public VitruvJavaHttpServer(String host, int port, List endpoints)
+ throws IOException {
+ this.server = HttpServer.create(new InetSocketAddress(host, port), 0);
+ endpoints.forEach(endp -> server.createContext(endp.path(), new RequestHandler(endp)));
+ }
- public void start() {
- server.start();
- }
+ /** Starts the Vitruvius server. */
+ public void start() {
+ server.start();
+ }
- public void stop() {
- server.stop(0);
- }
+ /** Stops the Vitruvius server. */
+ public void stop() {
+ server.stop(0);
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/package-info.java
index 99a54fb..1c07497 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/java/package-info.java
@@ -1,4 +1,2 @@
-/**
- * This package provides the built-in Java HTTP server for Vitruvius.
- */
+/** This package provides the built-in Java HTTP server for Vitruvius. */
package tools.vitruv.framework.remote.server.http.java;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/http/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/http/package-info.java
index 64df053..8faf377 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/http/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/http/package-info.java
@@ -1,4 +1,2 @@
-/**
- * This package serves interfaces to wrap HTTP servers from the actual REST end points.
- */
+/** This package serves interfaces to wrap HTTP servers from the actual REST end points. */
package tools.vitruv.framework.remote.server.http;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/package-info.java
index 0fd8244..f451f88 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/package-info.java
@@ -1,4 +1,2 @@
-/**
- * This package contains the Vitruvius server implementation.
- */
+/** This package contains the Vitruvius server implementation. */
package tools.vitruv.framework.remote.server;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/DeleteEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/DeleteEndpoint.java
index c8e30e6..eced41c 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/DeleteEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/DeleteEndpoint.java
@@ -1,4 +1,4 @@
package tools.vitruv.framework.remote.server.rest;
-public interface DeleteEndpoint extends RestEndpoint {
-}
+/** Marker interface for REST endpoints that handle HTTP DELETE requests. */
+public interface DeleteEndpoint extends RestEndpoint {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/GetEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/GetEndpoint.java
index b3619b1..dcc48f2 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/GetEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/GetEndpoint.java
@@ -1,4 +1,4 @@
package tools.vitruv.framework.remote.server.rest;
-public interface GetEndpoint extends RestEndpoint {
-}
+/** Marker interface for REST endpoints that handle HTTP GET requests. */
+public interface GetEndpoint extends RestEndpoint {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PatchEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PatchEndpoint.java
index d4f45e8..f649d9d 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PatchEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PatchEndpoint.java
@@ -1,4 +1,4 @@
package tools.vitruv.framework.remote.server.rest;
-public interface PatchEndpoint extends RestEndpoint {
-}
+/** Marker interface for REST endpoints that handle HTTP PATCH requests. */
+public interface PatchEndpoint extends RestEndpoint {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PathEndointCollector.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PathEndointCollector.java
index b480e40..c1405ec 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PathEndointCollector.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PathEndointCollector.java
@@ -1,9 +1,10 @@
package tools.vitruv.framework.remote.server.rest;
+/** Collects all REST endpoints for a specific path. */
public record PathEndointCollector(
- String path,
- GetEndpoint getEndpoint,
- PostEndpoint postEndpoint,
- PutEndpoint putEndpoint,
- PatchEndpoint patchEndpoint,
- DeleteEndpoint deleteEndpoint) {}
+ String path,
+ GetEndpoint getEndpoint,
+ PostEndpoint postEndpoint,
+ PutEndpoint putEndpoint,
+ PatchEndpoint patchEndpoint,
+ DeleteEndpoint deleteEndpoint) {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PostEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PostEndpoint.java
index 58c32eb..813514d 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PostEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PostEndpoint.java
@@ -1,4 +1,4 @@
package tools.vitruv.framework.remote.server.rest;
-public interface PostEndpoint extends RestEndpoint {
-}
+/** Marker interface for REST endpoints that handle HTTP POST requests. */
+public interface PostEndpoint extends RestEndpoint {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PutEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PutEndpoint.java
index a79c984..f2e96fe 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PutEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/PutEndpoint.java
@@ -1,4 +1,4 @@
package tools.vitruv.framework.remote.server.rest;
-public interface PutEndpoint extends RestEndpoint {
-}
+/** Marker interface for REST endpoints that handle HTTP PUT requests. */
+public interface PutEndpoint extends RestEndpoint {}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/RestEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/RestEndpoint.java
index d1c3e10..90cefbd 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/RestEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/RestEndpoint.java
@@ -1,37 +1,40 @@
package tools.vitruv.framework.remote.server.rest;
+import static java.net.HttpURLConnection.HTTP_BAD_METHOD;
+import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
+
import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
-import static java.net.HttpURLConnection.*;
-
-/**
- * Represents an REST endpoint.
- */
+/** Represents an REST endpoint. */
public interface RestEndpoint {
- /**
- * Processes a given HTTP request.
- *
- * @param wrapper An object wrapping an HTTP request/response.
- * @throws ServerHaltingException If an internal error occurred.
- */
- String process(HttpWrapper wrapper) throws ServerHaltingException;
+ /**
+ * Processes a given HTTP request.
+ *
+ * @param wrapper An object wrapping an HTTP request/response.
+ * @throws ServerHaltingException If an internal error occurred.
+ */
+ String process(HttpWrapper wrapper) throws ServerHaltingException;
- /**
- * Halts the execution of the requested endpoint and returns the status code NOT FOUND with the given message.
- *
- * @param msg A message containing the reason of halting the execution.
- */
- default ServerHaltingException notFound(String msg) {
- return new ServerHaltingException(HTTP_BAD_METHOD, msg);
- }
+ /**
+ * Halts the execution of the requested endpoint and returns the status code NOT FOUND with the
+ * given message.
+ *
+ * @param msg A message containing the reason of halting the execution.
+ * @return A ServerHaltingException representing the NOT FOUND error.
+ */
+ default ServerHaltingException notFound(String msg) {
+ return new ServerHaltingException(HTTP_BAD_METHOD, msg);
+ }
- /**
- * Halts the execution of the requested endpoint and returns the status code INTERNAL SERVER ERROR with the given message.
- *
- * @param msg A message containing the reason of halting the execution.
- */
- default ServerHaltingException internalServerError(String msg) {
- return new ServerHaltingException(HTTP_INTERNAL_ERROR, msg);
- }
+ /**
+ * Halts the execution of the requested endpoint and returns the status code INTERNAL SERVER ERROR
+ * with the given message.
+ *
+ * @param msg A message containing the reason of halting the execution.
+ * @return A ServerHaltingException representing the INTERNAL SERVER ERROR.
+ */
+ default ServerHaltingException internalServerError(String msg) {
+ return new ServerHaltingException(HTTP_INTERNAL_ERROR, msg);
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/Cache.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/Cache.java
index 040dee8..1fedf6d 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/Cache.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/Cache.java
@@ -1,56 +1,108 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
+import com.google.common.collect.BiMap;
import java.util.HashMap;
import java.util.Map;
-
-import com.google.common.collect.BiMap;
import org.eclipse.emf.ecore.EObject;
import tools.vitruv.framework.views.View;
import tools.vitruv.framework.views.ViewSelector;
/**
- * A global cache holding {@link View}s, {@link ViewSelector}s and mappings of the form UUID {@literal <->} {@link EObject}.
+ * A global cache holding {@link View}s, {@link ViewSelector}s and mappings of the form UUID and the
+ * {@link EObject}.
*/
public class Cache {
- private Cache() throws InstantiationException {
- throw new InstantiationException("Cannot be instantiated");
- }
-
- private static final Map viewCache = new HashMap<>();
- private static final Map selectorCache = new HashMap<>();
- private static final Map> perSelectorUuidToEObjectMapping = new HashMap<>();
-
- public static void addView(String uuid, View view) {
- viewCache.put(uuid, view);
- }
-
- public static View getView(String uuid) {
- return viewCache.get(uuid);
- }
-
- public static View removeView(String uuid) {
- return viewCache.remove(uuid);
- }
-
- public static void addSelectorWithMapping(String selectorUuid, ViewSelector selector, BiMap mapping) {
- selectorCache.put(selectorUuid, selector);
- perSelectorUuidToEObjectMapping.put(selectorUuid, mapping);
- }
-
- public static ViewSelector getSelector(String selectorUuid) {
- return selectorCache.get(selectorUuid);
- }
-
- public static EObject getEObjectFromMapping(String selectorUuid, String objectUuid) {
- return perSelectorUuidToEObjectMapping.get(selectorUuid).get(objectUuid);
- }
-
- public static String getUuidFromMapping(String selectorUuid, EObject eObject) {
- return perSelectorUuidToEObjectMapping.get(selectorUuid).inverse().get(eObject);
- }
-
- public static void removeSelectorAndMapping(String selectorUuid) {
- perSelectorUuidToEObjectMapping.remove(selectorUuid);
- selectorCache.remove(selectorUuid);
- }
+ private Cache() throws InstantiationException {
+ throw new InstantiationException("Cannot be instantiated");
+ }
+
+ private static final Map viewCache = new HashMap<>();
+ private static final Map selectorCache = new HashMap<>();
+ private static final Map> perSelectorUuidToEObjectMapping =
+ new HashMap<>();
+
+ /**
+ * Adds a view to the cache with the given uuid.
+ *
+ * @param uuid The uuid of the view.
+ * @param view The view to add.
+ */
+ public static void addView(String uuid, View view) {
+ viewCache.put(uuid, view);
+ }
+
+ /**
+ * Retrieves a view from the cache with the given uuid.
+ *
+ * @param uuid The uuid of the view.
+ * @return The view with the given uuid.
+ */
+ public static View getView(String uuid) {
+ return viewCache.get(uuid);
+ }
+
+ /**
+ * Removes a view from the cache with the given uuid.
+ *
+ * @param uuid The uuid of the view.
+ * @return The removed view.
+ */
+ public static View removeView(String uuid) {
+ return viewCache.remove(uuid);
+ }
+
+ /**
+ * Adds a selector and its corresponding EObject mapping to the cache.
+ *
+ * @param selectorUuid The uuid of the selector.
+ * @param selector The selector to add.
+ * @param mapping The mapping of the form String and the EObject.
+ */
+ public static void addSelectorWithMapping(
+ String selectorUuid, ViewSelector selector, BiMap mapping) {
+ selectorCache.put(selectorUuid, selector);
+ perSelectorUuidToEObjectMapping.put(selectorUuid, mapping);
+ }
+
+ /**
+ * Retrieves a selector from the cache with the given uuid.
+ *
+ * @param selectorUuid The uuid of the selector.
+ * @return The selector with the given uuid.
+ */
+ public static ViewSelector getSelector(String selectorUuid) {
+ return selectorCache.get(selectorUuid);
+ }
+
+ /**
+ * Retrieves an EObject from the mapping for the given selector uuid and object uuid.
+ *
+ * @param selectorUuid The uuid of the selector.
+ * @param objectUuid The uuid of the object.
+ * @return The EObject with the given uuid.
+ */
+ public static EObject getEObjectFromMapping(String selectorUuid, String objectUuid) {
+ return perSelectorUuidToEObjectMapping.get(selectorUuid).get(objectUuid);
+ }
+
+ /**
+ * Retrieves an object uuid from the mapping for the given selector uuid and EObject.
+ *
+ * @param selectorUuid The uuid of the selector.
+ * @param eObject The EObject to get the uuid for.
+ * @return The uuid of the given EObject.
+ */
+ public static String getUuidFromMapping(String selectorUuid, EObject eObject) {
+ return perSelectorUuidToEObjectMapping.get(selectorUuid).inverse().get(eObject);
+ }
+
+ /**
+ * Removes a selector and its corresponding EObject mapping from the cache.
+ *
+ * @param selectorUuid The uuid of the selector.
+ */
+ public static void removeSelectorAndMapping(String selectorUuid) {
+ perSelectorUuidToEObjectMapping.remove(selectorUuid);
+ selectorCache.remove(selectorUuid);
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangeDerivingEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangeDerivingEndpoint.java
new file mode 100644
index 0000000..4656759
--- /dev/null
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangeDerivingEndpoint.java
@@ -0,0 +1,140 @@
+package tools.vitruv.framework.remote.server.rest.endpoints;
+
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.core.instrument.Timer;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import org.eclipse.emf.common.util.URI;
+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.ResourceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import tools.vitruv.change.atomic.hid.HierarchicalId;
+import tools.vitruv.change.atomic.root.InsertRootEObject;
+import tools.vitruv.change.composite.description.VitruviusChange;
+import tools.vitruv.change.composite.description.VitruviusChangeFactory;
+import tools.vitruv.framework.remote.common.json.JsonMapper;
+import tools.vitruv.framework.remote.common.rest.constants.Header;
+import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
+import tools.vitruv.framework.remote.server.http.HttpWrapper;
+import tools.vitruv.framework.remote.server.rest.PatchEndpoint;
+import tools.vitruv.framework.views.changederivation.DefaultStateBasedChangeResolutionStrategy;
+import tools.vitruv.framework.views.changederivation.StateBasedChangeResolutionStrategy;
+import tools.vitruv.framework.views.impl.ModifiableView;
+import tools.vitruv.framework.views.impl.ViewCreatingViewType;
+
+/**
+ * This endpoint applies {@link VitruviusChange}s to the VSUM that are derived from the new state
+ * given by the client.
+ */
+public class ChangeDerivingEndpoint implements PatchEndpoint {
+ private static final String ENDPOINT_METRIC_NAME = "vitruv.server.rest.deriving";
+ private final JsonMapper mapper;
+ private final StateBasedChangeResolutionStrategy resolutionStrategy =
+ new DefaultStateBasedChangeResolutionStrategy();
+ private final Logger logger = LoggerFactory.getLogger(ChangeDerivingEndpoint.class);
+
+ /**
+ * Creates a new ChangeDerivingEndpoint.
+ *
+ * @param mapper The JSON mapper to use.
+ */
+ public ChangeDerivingEndpoint(JsonMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String process(HttpWrapper wrapper) {
+ var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ throw notFound("View with given id not found!");
+ }
+
+ String body;
+ try {
+ body = wrapper.getRequestBodyAsString();
+ } catch (IOException e) {
+ throw internalServerError(e.getMessage());
+ }
+
+ ResourceSet resourceSet;
+ var desTimer = Timer.start(Metrics.globalRegistry);
+ try {
+ resourceSet = mapper.deserialize(body, ResourceSet.class);
+ desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "success"));
+ } catch (JsonProcessingException e) {
+ logger.warn("Failed to deserialize request body: {}", e.getMessage());
+ desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "failure"));
+ throw new ServerHaltingException(HTTP_BAD_REQUEST, e.getMessage());
+ }
+
+ var currentRessources =
+ view.getRootObjects().stream().map(EObject::eResource).distinct().toList();
+ Map resourceMap = new HashMap<>();
+ for (Resource r : currentRessources) {
+ resourceMap.put(r.getURI(), r);
+ }
+
+ var allChanges = new LinkedList>();
+ resourceSet
+ .getResources()
+ .forEach(
+ it -> {
+ var u = resourceMap.get(it.getURI());
+ var changes = findChanges(u, it);
+ if (!changes.getEChanges().isEmpty()) {
+ allChanges.add(changes);
+ }
+ });
+
+ if (allChanges.isEmpty()) {
+ logger.info("No changes detected.");
+ return "[]";
+ }
+
+ @SuppressWarnings("rawtypes")
+ VitruviusChange change;
+ change = VitruviusChangeFactory.getInstance().createCompositeChange(allChanges);
+
+ change
+ .getEChanges()
+ .forEach(
+ it -> {
+ if (it instanceof InsertRootEObject> echange) {
+ echange.setResource(new ResourceImpl(URI.createURI(echange.getUri())));
+ }
+ });
+
+ var type = (ViewCreatingViewType, ?>) view.getViewType();
+ var propTimer = Timer.start(Metrics.globalRegistry);
+ try {
+ type.commitViewChanges((ModifiableView) view, change);
+ propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "success"));
+ return mapper.serialize(change);
+ } catch (RuntimeException e) {
+ propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "failure"));
+ throw new ServerHaltingException(HTTP_CONFLICT, "Changes rejected: " + e.getMessage());
+ } catch (JsonProcessingException e) {
+ throw internalServerError(e.getMessage());
+ }
+ }
+
+ private VitruviusChange findChanges(Resource oldState, Resource newState) {
+ if (oldState == null) {
+ return resolutionStrategy.getChangeSequenceForCreated(newState);
+ } else if (newState == null) {
+ return resolutionStrategy.getChangeSequenceForDeleted(oldState);
+ } else {
+ return resolutionStrategy.getChangeSequenceBetween(newState, oldState);
+ }
+ }
+}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangePropagationEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangePropagationEndpoint.java
index b952c32..c8b8fc5 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangePropagationEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ChangePropagationEndpoint.java
@@ -1,78 +1,81 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.core.instrument.Timer;
+import java.io.IOException;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
import tools.vitruv.change.atomic.root.InsertRootEObject;
import tools.vitruv.change.composite.description.VitruviusChange;
+import tools.vitruv.framework.remote.common.json.JsonMapper;
+import tools.vitruv.framework.remote.common.rest.constants.Header;
import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.PatchEndpoint;
-import tools.vitruv.framework.remote.common.json.JsonMapper;
-import tools.vitruv.framework.remote.common.rest.constants.Header;
import tools.vitruv.framework.views.impl.ModifiableView;
import tools.vitruv.framework.views.impl.ViewCreatingViewType;
-import java.io.IOException;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
+/** This endpoint applies given {@link VitruviusChange}s to the VSUM. */
+public class ChangePropagationEndpoint implements PatchEndpoint {
+ private static final String ENDPOINT_METRIC_NAME = "vitruv.server.rest.propagation";
+ private final JsonMapper mapper;
-import com.fasterxml.jackson.core.JsonProcessingException;
+ /**
+ * Creates a new ChangePropagationEndpoint.
+ *
+ * @param mapper The JSON mapper to use.
+ */
+ public ChangePropagationEndpoint(JsonMapper mapper) {
+ this.mapper = mapper;
+ }
-import io.micrometer.core.instrument.Metrics;
-import io.micrometer.core.instrument.Timer;
+ @SuppressWarnings("unchecked")
+ @Override
+ public String process(HttpWrapper wrapper) {
+ var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ throw notFound("View with given id not found!");
+ }
-import static java.net.HttpURLConnection.*;
+ String body;
+ try {
+ body = wrapper.getRequestBodyAsString();
+ } catch (IOException e) {
+ throw internalServerError(e.getMessage());
+ }
-/**
- * This endpoint applies given {@link VitruviusChange}s to the VSUM.
- */
-public class ChangePropagationEndpoint implements PatchEndpoint {
- private static final String ENDPOINT_METRIC_NAME = "vitruv.server.rest.propagation";
- private final JsonMapper mapper;
-
- public ChangePropagationEndpoint(JsonMapper mapper) {
- this.mapper = mapper;
- }
+ @SuppressWarnings("rawtypes")
+ VitruviusChange change;
+ var desTimer = Timer.start(Metrics.globalRegistry);
+ try {
+ change = mapper.deserialize(body, VitruviusChange.class);
+ desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "success"));
+ } catch (JsonProcessingException e) {
+ desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "failure"));
+ throw new ServerHaltingException(HTTP_BAD_REQUEST, e.getMessage());
+ }
+ change
+ .getEChanges()
+ .forEach(
+ it -> {
+ if (it instanceof InsertRootEObject> echange) {
+ echange.setResource(new ResourceImpl(URI.createURI(echange.getUri())));
+ }
+ });
- @SuppressWarnings("unchecked")
- @Override
- public String process(HttpWrapper wrapper) {
- var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
- if (view == null) {
- throw notFound("View with given id not found!");
- }
-
- String body;
- try {
- body = wrapper.getRequestBodyAsString();
- } catch (IOException e) {
- throw internalServerError(e.getMessage());
- }
-
- @SuppressWarnings("rawtypes")
- VitruviusChange change;
- var desTimer = Timer.start(Metrics.globalRegistry);
- try {
- change = mapper.deserialize(body, VitruviusChange.class);
- desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "success"));
- } catch (JsonProcessingException e) {
- desTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "deserialization", "failure"));
- throw new ServerHaltingException(HTTP_BAD_REQUEST, e.getMessage());
- }
- change.getEChanges().forEach(it -> {
- if (it instanceof InsertRootEObject> echange) {
- echange.setResource(new ResourceImpl(URI.createURI(echange.getUri())));
- }
- });
-
- var type = (ViewCreatingViewType, ?>) view.getViewType();
- var propTimer = Timer.start(Metrics.globalRegistry);
- try {
- type.commitViewChanges((ModifiableView) view, change);
- propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "success"));
- } catch (RuntimeException e) {
- propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "failure"));
- throw new ServerHaltingException(HTTP_CONFLICT, "Changes rejected: " + e.getMessage());
- }
- return null;
+ var type = (ViewCreatingViewType, ?>) view.getViewType();
+ var propTimer = Timer.start(Metrics.globalRegistry);
+ try {
+ type.commitViewChanges((ModifiableView) view, change);
+ propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "success"));
+ } catch (RuntimeException e) {
+ propTimer.stop(Metrics.timer(ENDPOINT_METRIC_NAME, "propagation", "failure"));
+ throw new ServerHaltingException(HTTP_CONFLICT, "Changes rejected: " + e.getMessage());
}
+ return null;
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/CloseViewEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/CloseViewEndpoint.java
index 6700035..00173a1 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/CloseViewEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/CloseViewEndpoint.java
@@ -1,24 +1,23 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
+import tools.vitruv.framework.remote.common.rest.constants.Header;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.DeleteEndpoint;
-import tools.vitruv.framework.remote.common.rest.constants.Header;
+import tools.vitruv.framework.views.View;
-/**
- * This endpoint closes a {@link tools.vitruv.framework.views.View View}.
- */
+/** This endpoint closes a {@link tools.vitruv.framework.views.View View}. */
public class CloseViewEndpoint implements DeleteEndpoint {
- @Override
- public String process(HttpWrapper wrapper) {
- var view = Cache.removeView(wrapper.getRequestHeader(Header.VIEW_UUID));
- if (view == null) {
- throw notFound("View with given id not found!");
- }
- try {
- view.close();
- return null;
- } catch (Exception e) {
- throw internalServerError(e.getMessage());
- }
+ @Override
+ public String process(HttpWrapper wrapper) {
+ View view = Cache.removeView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ throw notFound("View with given id not found!");
+ }
+ try {
+ view.close();
+ return null;
+ } catch (Exception e) {
+ throw internalServerError(e.getMessage());
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/EndpointsProvider.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/EndpointsProvider.java
index aa998f4..2ad3a16 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/EndpointsProvider.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/EndpointsProvider.java
@@ -2,7 +2,6 @@
import java.util.ArrayList;
import java.util.List;
-
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.rest.constants.EndpointPath;
import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
@@ -15,96 +14,120 @@
import tools.vitruv.framework.remote.server.rest.PutEndpoint;
import tools.vitruv.framework.vsum.VirtualModel;
+/** Provides all REST endpoints for the Vitruv server. */
public class EndpointsProvider {
- public static List getAllEndpoints(VirtualModel virtualModel, JsonMapper mapper) {
- var defaultEndpoints = getDefaultEndpoints();
-
- List result = new ArrayList<>();
- result.add(new PathEndointCollector(
- EndpointPath.HEALTH,
- new HealthEndpoint(),
- defaultEndpoints.postEndpoint(),
- defaultEndpoints.putEndpoint(),
- defaultEndpoints.patchEndpoint(),
- defaultEndpoints.deleteEndpoint()
- ));
- result.add(new PathEndointCollector(
- EndpointPath.IS_VIEW_CLOSED,
- new IsViewClosedEndpoint(),
- defaultEndpoints.postEndpoint(),
- defaultEndpoints.putEndpoint(),
- defaultEndpoints.patchEndpoint(),
- defaultEndpoints.deleteEndpoint()
- ));
- result.add(new PathEndointCollector(
- EndpointPath.IS_VIEW_OUTDATED,
- new IsViewOutdatedEndpoint(),
- defaultEndpoints.postEndpoint(),
- defaultEndpoints.putEndpoint(),
- defaultEndpoints.patchEndpoint(),
- defaultEndpoints.deleteEndpoint()
- ));
- result.add(new PathEndointCollector(
- EndpointPath.VIEW,
- new UpdateViewEndpoint(mapper),
- new ViewEndpoint(mapper),
- defaultEndpoints.putEndpoint(),
- new ChangePropagationEndpoint(mapper),
- new CloseViewEndpoint()
- ));
- result.add(new PathEndointCollector(
- EndpointPath.VIEW_SELECTOR,
- new ViewSelectorEndpoint(virtualModel, mapper),
- defaultEndpoints.postEndpoint(),
- defaultEndpoints.putEndpoint(),
- defaultEndpoints.patchEndpoint(),
- defaultEndpoints.deleteEndpoint()
- ));
- result.add(new PathEndointCollector(
- EndpointPath.VIEW_TYPES,
- new ViewTypesEndpoint(virtualModel, mapper),
- defaultEndpoints.postEndpoint(),
- defaultEndpoints.putEndpoint(),
- defaultEndpoints.patchEndpoint(),
- defaultEndpoints.deleteEndpoint()
- ));
-
- return result;
- }
-
- private static PathEndointCollector getDefaultEndpoints() {
- var getEndpoint = new GetEndpoint() {
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- throw notFound("Get mapping for this request path not found!");
- }
+
+ /**
+ * Creates and returns all REST endpoints for the Vitruv server.
+ *
+ * @param virtualModel The virtual model to use.
+ * @param mapper The JSON mapper to use.
+ * @return A list of all REST endpoints.
+ */
+ public static List getAllEndpoints(
+ VirtualModel virtualModel, JsonMapper mapper) {
+ var defaultEndpoints = getDefaultEndpoints();
+
+ List result = new ArrayList<>();
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.HEALTH,
+ new HealthEndpoint(),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ defaultEndpoints.patchEndpoint(),
+ defaultEndpoints.deleteEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.IS_VIEW_CLOSED,
+ new IsViewClosedEndpoint(),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ defaultEndpoints.patchEndpoint(),
+ defaultEndpoints.deleteEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.IS_VIEW_OUTDATED,
+ new IsViewOutdatedEndpoint(),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ defaultEndpoints.patchEndpoint(),
+ defaultEndpoints.deleteEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.VIEW,
+ new UpdateViewEndpoint(mapper),
+ new ViewEndpoint(mapper),
+ defaultEndpoints.putEndpoint(),
+ new ChangePropagationEndpoint(mapper),
+ new CloseViewEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.VIEW_SELECTOR,
+ new ViewSelectorEndpoint(virtualModel, mapper),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ defaultEndpoints.patchEndpoint(),
+ defaultEndpoints.deleteEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.VIEW_TYPES,
+ new ViewTypesEndpoint(virtualModel, mapper),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ defaultEndpoints.patchEndpoint(),
+ defaultEndpoints.deleteEndpoint()));
+ result.add(
+ new PathEndointCollector(
+ EndpointPath.CHANGE_DERIVING,
+ defaultEndpoints.getEndpoint(),
+ defaultEndpoints.postEndpoint(),
+ defaultEndpoints.putEndpoint(),
+ new ChangeDerivingEndpoint(mapper),
+ defaultEndpoints.deleteEndpoint()));
+
+ return result;
+ }
+
+ private static PathEndointCollector getDefaultEndpoints() {
+ var getEndpoint =
+ new GetEndpoint() {
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ throw notFound("Get mapping for this request path not found!");
+ }
};
- var postEndpoint = new PostEndpoint() {
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- throw notFound("Post mapping for this request path not found!");
- }
+ var postEndpoint =
+ new PostEndpoint() {
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ throw notFound("Post mapping for this request path not found!");
+ }
};
- var patchEndpoint = new PatchEndpoint() {
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- throw notFound("Patch mapping for this request path not found!");
- }
+ var patchEndpoint =
+ new PatchEndpoint() {
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ throw notFound("Patch mapping for this request path not found!");
+ }
};
- var deleteEndpoint = new DeleteEndpoint() {
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- throw notFound("Delete mapping for this request path not found!");
- }
+ var deleteEndpoint =
+ new DeleteEndpoint() {
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ throw notFound("Delete mapping for this request path not found!");
+ }
};
- var putEndpoint = new PutEndpoint() {
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- throw notFound("Put mapping for this request path not found!");
- }
+ var putEndpoint =
+ new PutEndpoint() {
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ throw notFound("Put mapping for this request path not found!");
+ }
};
- return new PathEndointCollector("", getEndpoint, postEndpoint, putEndpoint, patchEndpoint, deleteEndpoint);
- }
-
- private EndpointsProvider() {}
+ return new PathEndointCollector(
+ "", getEndpoint, postEndpoint, putEndpoint, patchEndpoint, deleteEndpoint);
+ }
+
+ private EndpointsProvider() {}
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/HealthEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/HealthEndpoint.java
index f55868c..1d759c6 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/HealthEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/HealthEndpoint.java
@@ -1,16 +1,14 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
+import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.GetEndpoint;
-import tools.vitruv.framework.remote.common.rest.constants.ContentType;
-/**
- * This endpoint can be used to check, if the server is running.
- */
+/** This endpoint can be used to check, if the server is running. */
public class HealthEndpoint implements GetEndpoint {
- @Override
- public String process(HttpWrapper wrapper) {
- wrapper.setContentType(ContentType.TEXT_PLAIN);
- return "Vitruv server up and running!";
- }
+ @Override
+ public String process(HttpWrapper wrapper) {
+ wrapper.setContentType(ContentType.TEXT_PLAIN);
+ return "Vitruv server up and running!";
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewClosedEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewClosedEndpoint.java
index 01b2ee1..cfa5e3f 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewClosedEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewClosedEndpoint.java
@@ -1,24 +1,23 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
-import tools.vitruv.framework.remote.server.http.HttpWrapper;
-import tools.vitruv.framework.remote.server.rest.GetEndpoint;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.common.rest.constants.Header;
+import tools.vitruv.framework.remote.server.http.HttpWrapper;
+import tools.vitruv.framework.remote.server.rest.GetEndpoint;
+import tools.vitruv.framework.views.View;
-/**
- * This endpoint returns whether a {@link tools.vitruv.framework.views.View View} is closed.
- */
+/** This endpoint returns whether a {@link tools.vitruv.framework.views.View View} is closed. */
public class IsViewClosedEndpoint implements GetEndpoint {
- @Override
- public String process(HttpWrapper wrapper) {
- var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
- if (view == null) {
- return Boolean.TRUE.toString();
- }
- if (view.isClosed()) {
- Cache.removeView(wrapper.getRequestHeader(Header.VIEW_UUID));
- }
- wrapper.setContentType(ContentType.TEXT_PLAIN);
- return view.isClosed() ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+ @Override
+ public String process(HttpWrapper wrapper) {
+ View view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ return Boolean.TRUE.toString();
+ }
+ if (view.isClosed()) {
+ Cache.removeView(wrapper.getRequestHeader(Header.VIEW_UUID));
}
+ wrapper.setContentType(ContentType.TEXT_PLAIN);
+ return view.isClosed() ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewOutdatedEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewOutdatedEndpoint.java
index 9fbbc7a..224f621 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewOutdatedEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/IsViewOutdatedEndpoint.java
@@ -1,21 +1,20 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
-import tools.vitruv.framework.remote.server.http.HttpWrapper;
-import tools.vitruv.framework.remote.server.rest.GetEndpoint;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.common.rest.constants.Header;
+import tools.vitruv.framework.remote.server.http.HttpWrapper;
+import tools.vitruv.framework.remote.server.rest.GetEndpoint;
+import tools.vitruv.framework.views.View;
-/**
- * This view returns whether a {@link tools.vitruv.framework.views.View View} is outdated.
- */
+/** This view returns whether a {@link tools.vitruv.framework.views.View View} is outdated. */
public class IsViewOutdatedEndpoint implements GetEndpoint {
- @Override
- public String process(HttpWrapper wrapper) {
- var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
- if (view == null) {
- throw notFound("View with given id not found!");
- }
- wrapper.setContentType(ContentType.TEXT_PLAIN);
- return view.isOutdated() ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+ @Override
+ public String process(HttpWrapper wrapper) {
+ View view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ throw notFound("View with given id not found!");
}
+ wrapper.setContentType(ContentType.TEXT_PLAIN);
+ return view.isOutdated() ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/UpdateViewEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/UpdateViewEndpoint.java
index d861194..a782429 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/UpdateViewEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/UpdateViewEndpoint.java
@@ -1,49 +1,56 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
import com.fasterxml.jackson.core.JsonProcessingException;
-
import edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceCopier;
-
+import java.util.List;
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 tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.common.rest.constants.Header;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.GetEndpoint;
+import tools.vitruv.framework.views.View;
/**
- * This endpoint updates a {@link tools.vitruv.framework.views.View View} and returns the
- * updated {@link org.eclipse.emf.ecore.resource.Resource Resources}.
+ * This endpoint updates a {@link tools.vitruv.framework.views.View View} and returns the updated
+ * {@link org.eclipse.emf.ecore.resource.Resource Resources}.
*/
public class UpdateViewEndpoint implements GetEndpoint {
- private final JsonMapper mapper;
-
- public UpdateViewEndpoint(JsonMapper mapper) {
- this.mapper = mapper;
- }
-
- @Override
- public String process(HttpWrapper wrapper) {
- var view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
- if (view == null) {
- throw notFound("View with given id not found!");
- }
-
- view.update();
-
- // Get resources.
- var resources = view.getRootObjects().stream().map(EObject::eResource).distinct().toList();
- var set = new ResourceSetImpl();
- ResourceCopier.copyViewResources(resources, set);
-
- wrapper.setContentType(ContentType.APPLICATION_JSON);
-
- try {
- return mapper.serialize(set);
- } catch (JsonProcessingException e) {
- throw internalServerError(e.getMessage());
- }
+ private final JsonMapper mapper;
+
+ /**
+ * Creates a new UpdateViewEndpoint.
+ *
+ * @param mapper The JSON mapper to use.
+ */
+ public UpdateViewEndpoint(JsonMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public String process(HttpWrapper wrapper) {
+ View view = Cache.getView(wrapper.getRequestHeader(Header.VIEW_UUID));
+ if (view == null) {
+ throw notFound("View with given id not found!");
+ }
+
+ view.update();
+
+ // Get resources.
+ List resources =
+ view.getRootObjects().stream().map(EObject::eResource).distinct().toList();
+ ResourceSet set = new ResourceSetImpl();
+ ResourceCopier.copyViewResources(resources, set);
+
+ wrapper.setContentType(ContentType.APPLICATION_JSON);
+
+ try {
+ return mapper.serialize(set);
+ } catch (JsonProcessingException e) {
+ throw internalServerError(e.getMessage());
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewEndpoint.java
index 507ec0b..f80b375 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewEndpoint.java
@@ -1,68 +1,78 @@
package tools.vitruv.framework.remote.server.rest.endpoints;
+import edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceCopier;
import java.io.IOException;
+import java.util.List;
import java.util.UUID;
-
-import edu.kit.ipd.sdq.commons.util.org.eclipse.emf.ecore.resource.ResourceCopier;
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 tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.common.rest.constants.Header;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.PostEndpoint;
+import tools.vitruv.framework.views.View;
+import tools.vitruv.framework.views.ViewSelector;
/**
* This endpoint returns a serialized {@link tools.vitruv.framework.views.View View} for the given
* {@link tools.vitruv.framework.views.ViewType ViewType}.
*/
public class ViewEndpoint implements PostEndpoint {
- private final JsonMapper mapper;
-
- public ViewEndpoint(JsonMapper mapper) {
- this.mapper = mapper;
- }
+ private final JsonMapper mapper;
- @Override
- public String process(HttpWrapper wrapper) {
- var selectorUuid = wrapper.getRequestHeader(Header.SELECTOR_UUID);
- var selector = Cache.getSelector(selectorUuid);
+ /**
+ * Creates a new ViewEndpoint.
+ *
+ * @param mapper The JSON mapper to use.
+ */
+ public ViewEndpoint(JsonMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public String process(HttpWrapper wrapper) {
+ String selectorUuid = wrapper.getRequestHeader(Header.SELECTOR_UUID);
+ ViewSelector selector = Cache.getSelector(selectorUuid);
+
+ // Check if view type exists.
+ if (selector == null) {
+ throw notFound("Selector with UUID " + selectorUuid + " not found!");
+ }
- // Check if view type exists.
- if (selector == null) {
- throw notFound("Selector with UUID " + selectorUuid + " not found!");
- }
+ try {
+ String body = wrapper.getRequestBodyAsString();
+ List selection = mapper.deserializeArrayOf(body, String.class);
- try {
- var body = wrapper.getRequestBodyAsString();
- var selection = mapper.deserializeArrayOf(body, String.class);
-
- // Select elements using IDs sent from client.
- selection.forEach(it -> {
- var object = Cache.getEObjectFromMapping(selectorUuid, it);
- if (object != null) {
- selector.setSelected(object, true);
- }
- });
+ // Select elements using IDs sent from client.
+ selection.forEach(
+ it -> {
+ EObject object = Cache.getEObjectFromMapping(selectorUuid, it);
+ if (object != null) {
+ selector.setSelected(object, true);
+ }
+ });
- // Create and cache view.
- var uuid = UUID.randomUUID().toString();
- var view = selector.createView();
- Cache.addView(uuid, view);
- Cache.removeSelectorAndMapping(selectorUuid);
+ // Create and cache view.
+ String uuid = UUID.randomUUID().toString();
+ View view = selector.createView();
+ Cache.addView(uuid, view);
+ Cache.removeSelectorAndMapping(selectorUuid);
- // Get resources.
- var resources = view.getRootObjects().stream().map(EObject::eResource).distinct().toList();
- var set = new ResourceSetImpl();
- ResourceCopier.copyViewResources(resources, set);
+ // Get resources.
+ List resources =
+ view.getRootObjects().stream().map(EObject::eResource).distinct().toList();
+ ResourceSet set = new ResourceSetImpl();
+ ResourceCopier.copyViewResources(resources, set);
- wrapper.setContentType(ContentType.APPLICATION_JSON);
- wrapper.addResponseHeader(Header.VIEW_UUID, uuid);
+ wrapper.setContentType(ContentType.APPLICATION_JSON);
+ wrapper.addResponseHeader(Header.VIEW_UUID, uuid);
- return mapper.serialize(set);
- } catch (IOException e) {
- throw internalServerError(e.getMessage());
- }
+ return mapper.serialize(set);
+ } catch (IOException e) {
+ throw internalServerError(e.getMessage());
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewSelectorEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewSelectorEndpoint.java
index 90bd4e2..2369eae 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewSelectorEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewSelectorEndpoint.java
@@ -2,69 +2,82 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.HashBiMap;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emfcloud.jackson.resource.JsonResource;
-
import tools.vitruv.framework.remote.common.json.JsonFieldName;
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
import tools.vitruv.framework.remote.common.rest.constants.Header;
-import tools.vitruv.framework.remote.common.util.*;
+import tools.vitruv.framework.remote.common.util.ResourceUtil;
import tools.vitruv.framework.remote.server.exception.ServerHaltingException;
import tools.vitruv.framework.remote.server.http.HttpWrapper;
import tools.vitruv.framework.remote.server.rest.GetEndpoint;
+import tools.vitruv.framework.views.ViewSelector;
+import tools.vitruv.framework.views.ViewType;
import tools.vitruv.framework.vsum.VirtualModel;
-import java.util.UUID;
-
+/** This endpoint creates a view selector for a given view type. */
public class ViewSelectorEndpoint implements GetEndpoint {
- private final VirtualModel model;
- private final JsonMapper mapper;
+ private final VirtualModel model;
+ private final JsonMapper mapper;
- public ViewSelectorEndpoint(VirtualModel model, JsonMapper mapper) {
- this.model = model;
- this.mapper = mapper;
- }
+ /**
+ * Creates a new ViewSelectorEndpoint.
+ *
+ * @param model The virtual model to create selectors from.
+ * @param mapper The JSON mapper to use.
+ */
+ public ViewSelectorEndpoint(VirtualModel model, JsonMapper mapper) {
+ this.model = model;
+ this.mapper = mapper;
+ }
- @Override
- public String process(HttpWrapper wrapper) throws ServerHaltingException {
- var viewTypeName = wrapper.getRequestHeader(Header.VIEW_TYPE);
- var types = model.getViewTypes();
- var viewType = types.stream().filter(it -> it.getName().equals(viewTypeName)).findFirst().orElse(null);
+ @Override
+ public String process(HttpWrapper wrapper) throws ServerHaltingException {
+ String viewTypeName = wrapper.getRequestHeader(Header.VIEW_TYPE);
+ Collection> types = model.getViewTypes();
+ ViewType> viewType =
+ types.stream().filter(it -> it.getName().equals(viewTypeName)).findFirst().orElse(null);
- // Check if view type exists.
- if (viewType == null) {
- throw notFound("View Type with name " + viewTypeName + " not found!");
- }
+ // Check if view type exists.
+ if (viewType == null) {
+ throw notFound("View Type with name " + viewTypeName + " not found!");
+ }
- // Generate selector UUID.
- var selectorUuid = UUID.randomUUID().toString();
+ // Generate selector UUID.
+ String selectorUuid = UUID.randomUUID().toString();
- var selector = model.createSelector(viewType);
- var originalSelection = selector.getSelectableElements().stream().toList();
- var copiedSelection = EcoreUtil.copyAll(originalSelection).stream().toList();
+ ViewSelector selector = model.createSelector(viewType);
+ List originalSelection = selector.getSelectableElements().stream().toList();
+ List copiedSelection = EcoreUtil.copyAll(originalSelection).stream().toList();
- // Wrap selection in resource for serialization.
- var resource = (JsonResource) ResourceUtil.createResourceWith(URI.createURI(JsonFieldName.TEMP_VALUE), copiedSelection);
+ // Wrap selection in resource for serialization.
+ JsonResource resource =
+ (JsonResource)
+ ResourceUtil.createResourceWith(
+ URI.createURI(JsonFieldName.TEMP_VALUE), copiedSelection);
- // Create EObject to UUID mapping.
- HashBiMap mapping = HashBiMap.create();
- for (int i = 0; i < originalSelection.size(); i++) {
- var objectUuid = UUID.randomUUID().toString();
- mapping.put(objectUuid, originalSelection.get(i));
- resource.setID(copiedSelection.get(i), objectUuid);
- }
- Cache.addSelectorWithMapping(selectorUuid, selector, mapping);
+ // Create EObject to UUID mapping.
+ HashBiMap mapping = HashBiMap.create();
+ for (int i = 0; i < originalSelection.size(); i++) {
+ var objectUuid = UUID.randomUUID().toString();
+ mapping.put(objectUuid, originalSelection.get(i));
+ resource.setID(copiedSelection.get(i), objectUuid);
+ }
+ Cache.addSelectorWithMapping(selectorUuid, selector, mapping);
- wrapper.setContentType(ContentType.APPLICATION_JSON);
- wrapper.addResponseHeader(Header.SELECTOR_UUID, selectorUuid);
+ wrapper.setContentType(ContentType.APPLICATION_JSON);
+ wrapper.addResponseHeader(Header.SELECTOR_UUID, selectorUuid);
- try {
- return mapper.serialize(resource);
- } catch (JsonProcessingException e) {
- throw internalServerError(e.getMessage());
- }
+ try {
+ return mapper.serialize(resource);
+ } catch (JsonProcessingException e) {
+ throw internalServerError(e.getMessage());
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewTypesEndpoint.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewTypesEndpoint.java
index 36671df..4385928 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewTypesEndpoint.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/ViewTypesEndpoint.java
@@ -3,35 +3,39 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.Collection;
import java.util.List;
-import tools.vitruv.framework.remote.server.http.HttpWrapper;
-import tools.vitruv.framework.remote.server.rest.GetEndpoint;
import tools.vitruv.framework.remote.common.json.JsonMapper;
import tools.vitruv.framework.remote.common.rest.constants.ContentType;
+import tools.vitruv.framework.remote.server.http.HttpWrapper;
+import tools.vitruv.framework.remote.server.rest.GetEndpoint;
import tools.vitruv.framework.views.ViewType;
import tools.vitruv.framework.vsum.VirtualModel;
-/**
- * This end point returns a list of names of all registered {@link ViewType}s in the VSUM.
- */
+/** This end point returns a list of names of all registered {@link ViewType}s in the VSUM. */
public class ViewTypesEndpoint implements GetEndpoint {
- private final VirtualModel model;
- private final JsonMapper mapper;
+ private final VirtualModel model;
+ private final JsonMapper mapper;
- public ViewTypesEndpoint(VirtualModel model, JsonMapper mapper) {
- this.model = model;
- this.mapper = mapper;
- }
+ /**
+ * Creates a new ViewTypesEndpoint.
+ *
+ * @param model The virtual model containing the view types.
+ * @param mapper The JSON mapper to serialize the response.
+ */
+ public ViewTypesEndpoint(VirtualModel model, JsonMapper mapper) {
+ this.model = model;
+ this.mapper = mapper;
+ }
- @Override
- public String process(HttpWrapper wrapper) {
- Collection> types = model.getViewTypes();
- List names = types.stream().map(ViewType::getName).toList();
+ @Override
+ public String process(HttpWrapper wrapper) {
+ Collection> types = model.getViewTypes();
+ List names = types.stream().map(ViewType::getName).toList();
- wrapper.setContentType(ContentType.APPLICATION_JSON);
- try {
- return mapper.serialize(names);
- } catch (JsonProcessingException e) {
- throw internalServerError(e.getMessage());
- }
+ wrapper.setContentType(ContentType.APPLICATION_JSON);
+ try {
+ return mapper.serialize(names);
+ } catch (JsonProcessingException e) {
+ throw internalServerError(e.getMessage());
}
+ }
}
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/package-info.java
index 0763334..2ec7933 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/endpoints/package-info.java
@@ -1,4 +1,2 @@
-/**
- * This package implements the REST API end points for the Vitruvius server.
- */
+/** This package implements the REST API end points for the Vitruvius server. */
package tools.vitruv.framework.remote.server.rest.endpoints;
diff --git a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/package-info.java b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/package-info.java
index 1277b73..adfa4f4 100644
--- a/remote/src/main/java/tools/vitruv/framework/remote/server/rest/package-info.java
+++ b/remote/src/main/java/tools/vitruv/framework/remote/server/rest/package-info.java
@@ -1,4 +1,5 @@
/**
- * This package defines interfaces for REST API end points. They are independent of the underlying HTTP server.
+ * This package defines interfaces for REST API end points. They are independent of the underlying
+ * HTTP server.
*/
package tools.vitruv.framework.remote.server.rest;
diff --git a/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvApmControllerTest.java b/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvApmControllerTest.java
index e6a650e..cfa62da 100644
--- a/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvApmControllerTest.java
+++ b/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvApmControllerTest.java
@@ -1,11 +1,12 @@
package tools.vitruv.framework.remote.common.apm;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.nio.file.Paths;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -74,6 +75,9 @@ void testEnableMultipleTimesDoesNotCreateNewInstance() throws Exception {
VitruvStepMeterRegistry secondInstance = getActiveRegistry();
// The same instance should be used
- assertSame(firstInstance, secondInstance, "Registry instance should be the same when enabling multiple times");
+ assertSame(
+ firstInstance,
+ secondInstance,
+ "Registry instance should be the same when enabling multiple times");
}
}
diff --git a/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistryTest.java b/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistryTest.java
index fd671a4..76f2997 100644
--- a/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistryTest.java
+++ b/remote/src/test/java/tools/vitruv/framework/remote/common/apm/VitruvStepMeterRegistryTest.java
@@ -1,27 +1,30 @@
package tools.vitruv.framework.remote.common.apm;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.step.StepRegistryConfig;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
class VitruvStepMeterRegistryTest {
private VitruvStepMeterRegistry registry;
private Path tempFile;
private StepRegistryConfig mockConfig;
-
+
@BeforeEach
void setUp() {
try {
@@ -43,7 +46,7 @@ void tearDown() {
fail("Failed to delete temp file: " + e.getMessage());
}
}
-
+
@Test
void testMetricsAreWrittenToFile() {
Timer timer = Timer.builder("test.timer").register(registry);
@@ -71,8 +74,10 @@ void testMultipleMetricsAreWrittenToFile() {
try {
String fileContent = Files.readString(tempFile);
- assertTrue(fileContent.contains("test.timer1"), "Metric test.timer1 should be present in the file");
- assertTrue(fileContent.contains("test.timer2"), "Metric test.timer2 should be present in the file");
+ assertTrue(
+ fileContent.contains("test.timer1"), "Metric test.timer1 should be present in the file");
+ assertTrue(
+ fileContent.contains("test.timer2"), "Metric test.timer2 should be present in the file");
} catch (IOException e) {
fail("Failed to read temp file: " + e.getMessage());
}
@@ -104,7 +109,10 @@ void testFileWritingErrorHandling() {
try {
String fileContent = Files.readString(tempFile);
- assertEquals("Pre-existing content", fileContent, "File content should remain unchanged due to error handling");
+ assertEquals(
+ "Pre-existing content",
+ fileContent,
+ "File content should remain unchanged due to error handling");
} catch (IOException e) {
fail("Failed to read temp file: " + e.getMessage());
}
@@ -115,12 +123,15 @@ void testTimersAreClearedAfterPublishing() {
Timer timer = registry.timer("test.timer");
timer.record(Duration.ofMillis(100));
- assertFalse(registry.getMeters().isEmpty(), "There should be at least one recorded metric before publishing.");
+ assertFalse(
+ registry.getMeters().isEmpty(),
+ "There should be at least one recorded metric before publishing.");
registry.publish();
- boolean hasRemainingMetrics = registry.getMeters().stream()
- .anyMatch(meter -> meter.getId().getName().equals("test.timer"));
+ boolean hasRemainingMetrics =
+ registry.getMeters().stream()
+ .anyMatch(meter -> meter.getId().getName().equals("test.timer"));
assertTrue(hasRemainingMetrics, "Timer should still be registered.");
}