Commit a0d6404e authored by Simon Barner's avatar Simon Barner
Browse files

Allow more than one source and/or target view per allocation table type

Issue-Ref: 3735
Issue-Url: https://af3-developer.fortiss.org/issues/3735

Signed-off-by: Simon Barner's avatarSimon Barner <barner@fortiss.org>
parent b183c7cb
AllocationTableEditor.java 2887c438b6dbd629f4eb795e68ffd540da6f4c16 GREEN
AllocationTableEditor.java babff48c09090a77d65a20d1c712b67abe8b5df3 YELLOW
ArchitectureParameterEditorBase.java b36b2e55fa5ca5c5e18a4f0a7a4cfa3d63f6cf24 YELLOW
ArchitectureParameterTableEditorBase.java c5af213271a7a4e9d7d3bc18ab82879ef4030213 YELLOW
ModelListenerEditorBase.java 0393577edf52d2cf97e060df93e2d79ea71d9481 GREEN
ModelListenerEditorBase.java 0d0b5bc9c4385061cc69d30f7d9bcd19d5837324 YELLOW
ParameterTableEditor.java 435231b3020dca1e20189a132439cc666cc72eb6 GREEN
......@@ -18,6 +18,7 @@ package org.fortiss.af3.allocation.ui.editor;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Stream.concat;
import static org.conqat.ide.commons.ui.selection.SelectionUtils.checkAndPickFirstSafe;
import static org.conqat.lib.commons.reflect.ReflectionUtils.isInstanceOfAny;
import static org.eclipse.jface.dialogs.MessageDialog.openConfirm;
......@@ -203,11 +204,11 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
}
final IAllocationService as = IAllocationService.getInstance();
if(getSourceModelType() == null) {
if(getSourceModelTypes().isEmpty()) {
throw new RuntimeException("Source model type must be set.");
}
if(getTargetModelType() == null) {
if(getTargetModelTypes().isEmpty()) {
throw new RuntimeException("Target model type must be set.");
}
......@@ -227,16 +228,22 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
return allocationEntryType;
}
/** Returns the source model type. */
private Class<? extends IProjectRootElement> getSourceModelType() {
return IAllocationService.getInstance()
.getSourceModelType(getAllocationTableType(getEditedObject().getClass()));
/** Returns the source model types. */
private Collection<Class<? extends IProjectRootElement>> getSourceModelTypes() {
IAllocationService as = IAllocationService.getInstance();
Class<? extends AllocationTable> allocationTableType =
getAllocationTableType(getEditedObject().getClass());
return as.getSourceModelTypes(allocationTableType);
}
/** Returns the target model type. */
private Class<? extends IProjectRootElement> getTargetModelType() {
return IAllocationService.getInstance()
.getTargetModelType(getAllocationTableType(getEditedObject().getClass()));
/** Returns the target model types. */
private Collection<Class<? extends IProjectRootElement>> getTargetModelTypes() {
IAllocationService as = IAllocationService.getInstance();
Class<? extends AllocationTable> allocationTableType =
getAllocationTableType(getEditedObject().getClass());
return as.getTargetModelTypes(allocationTableType);
}
/** Returns {@link #sourceEntityType}. */
......@@ -292,16 +299,20 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
/** {@inheritDoc} */
@Override
protected boolean isEditedModel(Object object) {
return isInstanceOfAny(object, getSourceModelType(), getTargetModelType());
Stream<Class<? extends IProjectRootElement>> modelTypes =
concat(getSourceModelTypes().stream(), getTargetModelTypes().stream());
return isInstanceOfAny(object, modelTypes.toArray(Class[]::new));
}
/** Performs a refresh for the given {@link IProjectRootElement}. */
protected void refresh(IProjectRootElement model) {
if(model != null) {
Class<? extends IProjectRootElement> sourceModelType = getSourceModelType();
Class<? extends IProjectRootElement> targetModelType = getTargetModelType();
Collection<Class<? extends IProjectRootElement>> sourceModelTypes =
getSourceModelTypes();
Collection<Class<? extends IProjectRootElement>> targetModelTypes =
getTargetModelTypes();
updateModelSelectionComboBox(gui.getComboViewerSource(), getModels(sourceModelType),
updateModelSelectionComboBox(gui.getComboViewerSource(), getModels(sourceModelTypes),
getEditedObject().getSourceView());
// Update available source entity types and super-ordinate elements (that might have
......@@ -313,7 +324,7 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
updateSuperOrdinateElementComboBox(gui.getComboViewerSourceSuperOrdinateElement(),
getSourceSuperOrdinateElements(), this::setSourceSuperOrdinateElement);
updateModelSelectionComboBox(gui.getComboViewerTarget(), getModels(targetModelType),
updateModelSelectionComboBox(gui.getComboViewerTarget(), getModels(targetModelTypes),
getEditedObject().getTargetView());
// Update available target entity types and super-ordinate elements (that might have
......@@ -347,12 +358,12 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
protected void comboViewerOpened(ComboViewer viewer) {
if(viewer == gui.getComboViewerSource()) {
updateModelSelectionComboBox(gui.getComboViewerSource(),
getModels(getSourceModelType()), getEditedObject().getSourceView());
getModels(getSourceModelTypes()), getEditedObject().getSourceView());
gui.getComboViewerSource().refresh();
} else if(viewer == gui.getComboViewerTarget()) {
updateModelSelectionComboBox(gui.getComboViewerTarget(),
getModels(getTargetModelType()), getEditedObject().getTargetView());
getModels(getTargetModelTypes()), getEditedObject().getTargetView());
gui.getComboViewerTarget().refresh();
}
}
......@@ -532,28 +543,28 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
final IAllocationService as = IAllocationService.getInstance();
IProjectRootElement sourceView = null;
IProjectRootElement targetView = null;
List<IProjectRootElement> sourceModels = emptyList();
List<IProjectRootElement> targetModels = emptyList();
Collection<IProjectRootElement> sourceModels = emptyList();
Collection<IProjectRootElement> targetModels = emptyList();
if(getEditedObject() != null) {
targetView = getEditedObject().getTargetView();
targetModels = getModels(getTargetModelType());
targetModels = getModels(getTargetModelTypes());
if(targetView == null && !targetModels.isEmpty()) {
// Set target view if there is none yet, and the at is at least one available.
//
// This must be performed before setting the source view, in order to make the
// special case for the available source view elements in getModels() work
// correctly.
targetView = targetModels.get(0);
targetView = targetModels.iterator().next();
final IProjectRootElement view = targetView;
runAsCommand(getEditedObject(), () -> {
getEditedObject().setTargetView(view);
});
}
sourceView = getEditedObject().getSourceView();
sourceModels = getModels(getSourceModelType());
sourceModels = getModels(getSourceModelTypes());
if(sourceView == null && !sourceModels.isEmpty()) {
// Set source view if there is none yet, and the at is at least one available.
sourceView = sourceModels.get(0);
sourceView = sourceModels.iterator().next();
final IProjectRootElement view = sourceView;
runAsCommand(getEditedObject(), () -> {
getEditedObject().setSourceView(view);
......@@ -875,12 +886,12 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
/********************* Binding to underlying model *********************/
/**
* Returns the {@link List} of models (i.e., {@link IProjectRootElement}s) of the given type;
* Returns the {@link List} of models (i.e., {@link IProjectRootElement}s) of are of any of the
* given types;
*/
@SuppressWarnings("unchecked")
private List<IProjectRootElement> getModels(Class<? extends IProjectRootElement> type) {
List<? extends IProjectRootElement> models = getRootElements(getEditedObject(), type);
if(uniqueSourceView && type == getSourceModelType()) {
private Collection<IProjectRootElement>
getModels(Collection<Class<? extends IProjectRootElement>> types) {
if(uniqueSourceView && types.containsAll(getSourceModelTypes())) {
for(AllocationTableCollection atc : getRootElements(getEditedObject(),
AllocationTableCollection.class)) {
......@@ -893,7 +904,8 @@ public abstract class AllocationTableEditor<T extends AllocationTable>
}
}
}
return (List<IProjectRootElement>)models;
return getRootElements(getEditedObject(), types);
}
/** Determines the list of model elements offered for a given {@code modelView}. */
......
......@@ -25,6 +25,7 @@ import static org.fortiss.tooling.kernel.model.FortissToolingKernelPackage.Liter
import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirst;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.runAsCommand;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
......@@ -296,7 +297,7 @@ public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEdit
* Initially selected model.
*/
protected void updateModelSelectionComboBox(ComboViewer comboViewer,
List<IProjectRootElement> models, IProjectRootElement selectedModel) {
Collection<IProjectRootElement> models, IProjectRootElement selectedModel) {
comboViewer.setInput(models);
......
AF3AllocationActivator.java fa98bbdbd34d9d3c76f7f2827f2f456105c90fa6 GREEN
IAllocationService.java 0989c3704c85b26176b042cee6aff118a55cb4f1 GREEN
IAllocationService.java 3a1ad21ee49e014e5ce82537686308eab6dc1fe3 YELLOW
......@@ -128,18 +128,18 @@ public interface IAllocationService {
getTargetEntityTypes(Class<? extends AllocationEntry> allocationEntryType);
/**
* Returns the source model type that has been registered with the given {@link AllocationTable}
* specialization ({@code null} if none has been registered yet).
* Returns the (possibly empty) list of source model types that are registered with the given
* {@link AllocationTable} specialization.
*/
Class<? extends IProjectRootElement>
getSourceModelType(Class<? extends AllocationTable> allocationTableType);
Collection<Class<? extends IProjectRootElement>>
getSourceModelTypes(Class<? extends AllocationTable> allocationTableType);
/**
* Returns the source model type that has been registered with the given {@link AllocationTable}
* specialization ({@code null} if none has been registered yet).
* Returns the (possibly empty) list of target model types that are registered with the given
* {@link AllocationTable} specialization.
*/
Class<? extends IProjectRootElement>
getTargetModelType(Class<? extends AllocationTable> allocationTableType);
Collection<Class<? extends IProjectRootElement>>
getTargetModelTypes(Class<? extends AllocationTable> allocationTableType);
/**
* Registers a model type that is covered by the given {@link AllocationTable}
......
AllocationTableCollectionCompositorBase.java 2bdeb1897a8f0f79e1c0f2faad74ff6098ce53a2 GREEN
AllocationTableCollectionCompositorBase.java 6630ee4a803e13e7707013120f856c3b49c6a845 YELLOW
AllocationTableCollectionFileProjectCompositor.java acae4d3f3f3b07d4c1d235dfc224c83a50b8e3d8 GREEN
ParameterTableCompositorBase.java 7164f1e3be098024652f8df7515984021d914062 YELLOW
......@@ -17,7 +17,9 @@ package org.fortiss.af3.allocation.compose;
import static org.fortiss.af3.allocation.utils.AllocationUtils.getAllocationTableType;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getRootElement;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getRootElements;
import java.util.Collection;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.af3.allocation.IAllocationService;
......@@ -80,6 +82,23 @@ public abstract class AllocationTableCollectionCompositorBase
return pickInstanceOf(allocationTableType, atCollection.getAllocationTables()).size();
}
/**
* Predicate whether any of the {@link IProjectRootElement}s of @codes types1} is assignable
* from any the {@link IProjectRootElement}s of {@code types2}.
*/
private boolean isAnyRootElementAssignable(
Collection<Class<? extends IProjectRootElement>> types1,
Collection<Class<? extends IProjectRootElement>> types2) {
for(Class<?> t1 : types1) {
for(Class<?> t2 : types2) {
if(t1.isAssignableFrom(t2)) {
return true;
}
}
}
return false;
}
/** {@inheritDoc} */
@Override
public boolean canCompose(AllocationTableCollection container, EObject contained,
......@@ -92,14 +111,14 @@ public abstract class AllocationTableCollectionCompositorBase
IAllocationService as = IAllocationService.getInstance();
// Check if project contains required source and target models
final Class<? extends IProjectRootElement> sourceModelType =
as.getSourceModelType(allocationTableType);
if(getRootElement(container, sourceModelType) == null) {
final Collection<Class<? extends IProjectRootElement>> sourceModelTypes =
as.getSourceModelTypes(allocationTableType);
if(getRootElements(container, sourceModelTypes).isEmpty()) {
return false;
}
final Class<? extends IProjectRootElement> targetModelType =
as.getTargetModelType(allocationTableType);
if(getRootElement(container, targetModelType) == null) {
final Collection<Class<? extends IProjectRootElement>> targetModelTypes =
as.getTargetModelTypes(allocationTableType);
if(getRootElements(container, targetModelTypes).isEmpty()) {
return false;
}
......@@ -123,33 +142,34 @@ public abstract class AllocationTableCollectionCompositorBase
}
// Check if source/target view of existing allocation table causes an overlap
final Class<? extends IProjectRootElement> sourceViewType =
as.getSourceModelType(atType);
final Class<? extends IProjectRootElement> targetViewType =
as.getTargetModelType(atType);
if(sourceModelType.isAssignableFrom(sourceViewType) ||
targetModelType.isAssignableFrom(targetViewType)) {
final Collection<Class<? extends IProjectRootElement>> sourceViewTypes =
as.getSourceModelTypes(atType);
final Collection<Class<? extends IProjectRootElement>> targetViewTypes =
as.getTargetModelTypes(atType);
if(isAnyRootElementAssignable(sourceModelTypes, sourceViewTypes) ||
isAnyRootElementAssignable(targetModelTypes, targetViewTypes)) {
return false;
}
// Check for overlaps due to model types that are additionally covered
for(Class<? extends IProjectRootElement> coveredModelType : as
.getCoveredModelTypes(atType)) {
if(coveredModelType.isAssignableFrom(sourceModelType) ||
coveredModelType.isAssignableFrom(targetModelType)) {
return false;
}
Collection<Class<? extends IProjectRootElement>> atTypeCoveredModelTypes =
as.getCoveredModelTypes(atType);
if(isAnyRootElementAssignable(atTypeCoveredModelTypes, sourceModelTypes) ||
isAnyRootElementAssignable(as.getCoveredModelTypes(atType), targetModelTypes)) {
return false;
}
for(Class<? extends IProjectRootElement> coveredModelType : as
.getCoveredModelTypes(allocationTableType)) {
if(coveredModelType.isAssignableFrom(sourceViewType) ||
coveredModelType.isAssignableFrom(targetViewType)) {
return false;
}
Collection<Class<? extends IProjectRootElement>> allocationTableTypeCoveredModelTypes =
as.getCoveredModelTypes(allocationTableType);
if(isAnyRootElementAssignable(allocationTableTypeCoveredModelTypes, sourceModelTypes) ||
isAnyRootElementAssignable(allocationTableTypeCoveredModelTypes,
targetModelTypes)) {
return false;
}
}
return true;
}
/** {@inheritDoc} */
......
AllocationService.java 35c2bf4a9f6bed8a565875896e9adfbbca7586d6 YELLOW
AllocationService.java dd5172144e4ce2b575debadc9ae0991a254e373d YELLOW
......@@ -51,13 +51,13 @@ public final class AllocationService implements IAllocationService, IIntrospecti
private EMFTypeToTypeSetMap<AllocationEntry, IModelElement> targetEntityTypeMap =
new EMFTypeToTypeSetMap<AllocationEntry, IModelElement>();
/** Maps an {@link AllocationTable} type to a source model type. */
private EMFTypeToTypeMap<AllocationTable, IProjectRootElement> sourceModelTypeMap =
new EMFTypeToTypeMap<AllocationTable, IProjectRootElement>();
/** Maps an {@link AllocationTable} type to the list of admissible source model types. */
private EMFTypeToTypeSetMap<AllocationTable, IProjectRootElement> sourceModelTypeMap =
new EMFTypeToTypeSetMap<AllocationTable, IProjectRootElement>();
/** Maps an {@link AllocationTable} type to a target model type. */
private EMFTypeToTypeMap<AllocationTable, IProjectRootElement> targetModelTypeMap =
new EMFTypeToTypeMap<AllocationTable, IProjectRootElement>();
/** Maps an {@link AllocationTable} type to the list of admissible target model type. */
private EMFTypeToTypeSetMap<AllocationTable, IProjectRootElement> targetModelTypeMap =
new EMFTypeToTypeSetMap<AllocationTable, IProjectRootElement>();
/**
* Maps {@link AllocationTable}s to model types are covered by it in addition to their
......@@ -145,36 +145,15 @@ public final class AllocationService implements IAllocationService, IIntrospecti
public void addAllocationTableType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> sourceModelType,
Class<? extends IProjectRootElement> targetModelType, boolean isInternal) {
setSourceModelType(allocationTableType, sourceModelType);
setTargetModelType(allocationTableType, targetModelType);
sourceModelTypeMap.addTypeSetEntry(allocationTableType, sourceModelType);
targetModelTypeMap.addTypeSetEntry(allocationTableType, targetModelType);
if(isInternal) {
internalAllocationTableTypeMap.put(allocationTableType, null);
}
}
/** Registers the source model type with the given {@link AllocationTable} specialization. */
private void setSourceModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> sourceModelType) {
if(getSourceModelType(allocationTableType) != null) {
throw new RuntimeException("Duplicated source model type registration for " +
allocationTableType.getName() + ".");
}
sourceModelTypeMap.put(allocationTableType, sourceModelType);
}
/** Registers the target model type with the given {@link AllocationTable} specialization. */
private void setTargetModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> targetModelType) {
if(getTargetModelType(allocationTableType) != null) {
throw new RuntimeException("Duplicated target model type registration for " +
allocationTableType.getName() + ".");
}
targetModelTypeMap.put(allocationTableType, targetModelType);
}
/** {@inheritDoc} */
@Override
public <T extends AllocationTable & IAllocationType, E extends AllocationEntry & IAllocationType>
......@@ -247,18 +226,16 @@ public final class AllocationService implements IAllocationService, IIntrospecti
/** {@inheritDoc} */
@Override
public Class<? extends IProjectRootElement>
getSourceModelType(Class<? extends AllocationTable> allocationTableType) {
final Class<? extends IProjectRootElement> rval =
sourceModelTypeMap.get(allocationTableType);
return rval;
public Collection<Class<? extends IProjectRootElement>>
getSourceModelTypes(Class<? extends AllocationTable> allocationTableType) {
return sourceModelTypeMap.getTargetTypes(allocationTableType);
}
/** {@inheritDoc} */
@Override
public Class<? extends IProjectRootElement>
getTargetModelType(Class<? extends AllocationTable> allocationTableType) {
return targetModelTypeMap.get(allocationTableType);
public Collection<Class<? extends IProjectRootElement>>
getTargetModelTypes(Class<? extends AllocationTable> allocationTableType) {
return targetModelTypeMap.getTargetTypes(allocationTableType);
}
/** {@inheritDoc} */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment