Commit 10b2be93 authored by Simon Barner's avatar Simon Barner
Browse files

Add the following methods to IAllocationService:

 - setSourceModelType(), getSourceModelType()
 - setTargetModelType(), getTargetModelType()
 - addCoveredModelType(), getCoveredModelTypes()
 - addAdmissibleAllocationTablePair(), getAdmissibleAllocationTables()

They are used to centralize information about admissible source/target model types that is used in both AllocationTableEditor and AllocationTableCollectionCompositorBase specializations.

refs 2950
parent e9ca43be
AllocationTableEditor.java 75629eea8a869b102cccafee73b0db1730df5651 YELLOW
AllocationTableEditor.java b9ac726199785ade9f79df1f927db7a27236152e YELLOW
AllocationTableEditorUtils.java 3f53fc3ce279be40ca18d6d63f3f7f830ec4eb86 RED
ModelListenerEditorBase.java 6145b0682ffc82fee4c09ab51530506e79f286ad YELLOW
ModelListenerEditorBase.java 622ed9ea90668f665f73f99fb4eec215ba10105d YELLOW
......@@ -20,6 +20,7 @@ import static org.conqat.lib.commons.reflect.ReflectionUtils.isInstanceOfAny;
import static org.eclipse.jface.dialogs.MessageDialog.openConfirm;
import static org.eclipse.jface.viewers.AbstractTreeViewer.ALL_LEVELS;
import static org.fortiss.af3.allocation.utils.AllocationUtils.checkAllocationEntryType;
import static org.fortiss.af3.allocation.utils.AllocationUtils.getAllocationTableType;
import static org.fortiss.tooling.common.util.LambdaUtils.asStream;
import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirst;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstChildWithType;
......@@ -69,12 +70,6 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** {@link AllocationEntry} type to be edited in this {@link AllocationTableEditor}. */
private Class<? extends AllocationEntry> allocationEntryType;
/** Type of source models used to edit the given {@link AllocationTable}. */
private Class<? extends IProjectRootElement> sourceModelType;
/** Type of target models used to edit the given {@link AllocationTable}. */
private Class<? extends IProjectRootElement> targetModelType;
/**
* Type of source model entities used to create {@link AllocationEntry}s for the given
* {@link AllocationTable}.
......@@ -106,17 +101,36 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** Constructor. */
protected AllocationTableEditor(Class<? extends AllocationEntry> allocationEntryType,
Class<? extends IProjectRootElement> sourceModelType,
Class<? extends IProjectRootElement> targetModelType,
ViewElementFilter sourceViewElementFilter, ViewElementFilter targetViewElementFilter) {
checkAllocationEntryType(allocationEntryType);
this.allocationEntryType = allocationEntryType;
this.sourceModelType = sourceModelType;
this.targetModelType = targetModelType;
this.sourceViewElementFilter = sourceViewElementFilter;
this.targetViewElementFilter = targetViewElementFilter;
}
/** Constructor. */
protected AllocationTableEditor(Class<? extends AllocationEntry> allocationEntryType) {
this(allocationEntryType, null, null);
}
/**
* Checks the configuration of this AllocationTableEditor.
*
* @throws RuntimeException
* in case of error.
*/
private void checkConfiguration() {
checkAllocationEntryType(allocationEntryType);
final IAllocationService as = IAllocationService.getInstance();
if(getSourceModelType() == null) {
throw new RuntimeException("Source model type must be set.");
}
if(getTargetModelType() == null) {
throw new RuntimeException("Target model type must be set.");
}
if(as.getSourceEntityTypes(allocationEntryType).isEmpty()) {
throw new RuntimeException("List of source entity types must not be empty.");
}
......@@ -124,16 +138,6 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
if(as.getTargetEntityTypes(allocationEntryType).isEmpty()) {
throw new RuntimeException("List of target entity types must not be empty.");
}
this.sourceViewElementFilter = sourceViewElementFilter;
this.targetViewElementFilter = targetViewElementFilter;
}
/** Constructor. */
protected AllocationTableEditor(Class<? extends AllocationEntry> allocationEntryType,
Class<? extends IProjectRootElement> sourceModelType,
Class<? extends IProjectRootElement> targetModelType) {
this(allocationEntryType, sourceModelType, targetModelType, null, null);
}
/********************* Getters *********************/
......@@ -143,6 +147,18 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
return allocationEntryType;
}
/** Returns the source model type. */
private Class<? extends IProjectRootElement> getSourceModelType() {
return IAllocationService.getInstance().getSourceModelType(
getAllocationTableType(editedObject.getClass()));
}
/** Returns the target model type. */
private Class<? extends IProjectRootElement> getTargetModelType() {
return IAllocationService.getInstance().getTargetModelType(
getAllocationTableType(editedObject.getClass()));
}
/** Returns {@link #sourceEntityType}. */
public Class<? extends IModelElement> getSourceEntityType() {
return sourceEntityType;
......@@ -167,7 +183,7 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** {@inheritDoc} */
@Override
protected boolean isEditedModel(Object object) {
return isInstanceOfAny(object, sourceModelType, targetModelType);
return isInstanceOfAny(object, getSourceModelType(), getTargetModelType());
}
/** {@inheritDoc} */
......@@ -184,6 +200,9 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** Performs a refresh for the given root element. */
protected void refresh(IProjectRootElement model) {
Class<? extends IProjectRootElement> sourceModelType = getSourceModelType();
Class<? extends IProjectRootElement> targetModelType = getTargetModelType();
if(sourceModelType.isAssignableFrom(model.getClass())) {
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(sourceModelType), editedObject.getSourceView());
......@@ -213,6 +232,9 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** {@inheritDoc} */
@Override
protected void renameModel(IProjectRootElement model) {
Class<? extends IProjectRootElement> sourceModelType = getSourceModelType();
Class<? extends IProjectRootElement> targetModelType = getTargetModelType();
if(sourceModelType.isAssignableFrom(model.getClass())) {
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(sourceModelType), editedObject.getSourceView());
......@@ -324,7 +346,9 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
/** {@inheritDoc} */
@Override
public void createPartControl(Composite parent) {
checkConfiguration();
super.createPartControl(parent);
gui = new AllocationTableEditorGUI(parent, SWT.NONE);
treeViewerManager = new TreeViewerManager<>(this, gui.getTreeViewer());
......@@ -346,13 +370,13 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
setupViewPointSelectionComboBox(gui.getComboViewerSource(), editedObject::setSourceView,
editedObject::getSourceView);
updateViewPointSelectionComboBox(gui.getComboViewerSource(), getModels(sourceModelType),
editedObject.getSourceView());
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(getSourceModelType()), editedObject.getSourceView());
setupViewPointSelectionComboBox(gui.getComboViewerTarget(), editedObject::setTargetView,
editedObject::getTargetView);
updateViewPointSelectionComboBox(gui.getComboViewerTarget(), getModels(targetModelType),
editedObject.getTargetView());
updateViewPointSelectionComboBox(gui.getComboViewerTarget(),
getModels(getTargetModelType()), editedObject.getTargetView());
gui.getCheckboxShowSourceModelHierarchy().addSelectionListener(
new SourceModelHierarchyCheckBoxSelectionListener());
......@@ -545,9 +569,14 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
Collection<Class<? extends IModelElement>> entityTypes, IHierarchicElement model,
Consumer<Class<? extends IModelElement>> setter) {
List<Class<? extends IModelElement>> usedEntityTypes =
entityTypes.stream().filter(t -> getFirstChildWithType(model, t) != null)
.collect(Collectors.toList());
List<Class<? extends IModelElement>> usedEntityTypes;
if(model == null) {
usedEntityTypes = emptyList();
} else {
final Predicate<Class<? extends IModelElement>> hasEntity =
t -> getFirstChildWithType(model, t) != null;
usedEntityTypes = entityTypes.stream().filter(hasEntity).collect(Collectors.toList());
}
final Combo combo = comboViewer.getCombo();
combo.setEnabled(usedEntityTypes.size() > 1);
......
AF3AllocationActivator.java db64a468f2e3079907f0c82be9c675ef3932f786 GREEN
IAllocationService.java 4853e774088f8b2b3e80c99028dcc13bc7fd561d YELLOW
IAllocationService.java d978593a040eea44d81391f734069f1f13cf90cf YELLOW
......@@ -19,7 +19,9 @@ import java.util.Collection;
import org.fortiss.af3.allocation.internal.AllocationService;
import org.fortiss.af3.allocation.model.AllocationEntry;
import org.fortiss.af3.allocation.model.AllocationTable;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
/**
* The allocation service allows to configure admissible allocations (i.e., additional constraints
......@@ -60,4 +62,54 @@ public interface IAllocationService {
*/
Collection<Class<? extends IModelElement>> getTargetEntityTypes(
Class<? extends AllocationEntry> allocationEntryType);
/** Registers the source model type with the given {@link AllocationTable} specialization. */
public void setSourceModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> sourceModelType);
/** Registers the target model type with the given {@link AllocationTable} specialization. */
public void setTargetModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> targetModelType);
/**
* Returns the source model type that has been registered with the given {@link AllocationTable}
* specialization ({@code null} if none has been registered yet).
*/
Class<? extends IProjectRootElement> getSourceModelType(
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).
*/
Class<? extends IProjectRootElement> getTargetModelType(
Class<? extends AllocationTable> allocationTableType);
/**
* Registers a target model type that is covered by the given {@link AllocationTable}
* specialization (in addition to its source/target model type.
*/
public void addCoveredModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> targetModelType);
/**
* Returns the target model types that are covered by the given {@link AllocationTable}
* specialization (in addition to its source/target model type).
*/
public Collection<Class<? extends IProjectRootElement>> getCoveredModelTypes(
Class<? extends AllocationTable> allocationTableType);
/**
* Registers a pair of {@link AllocationTable} types that can exist together despite overlapping
* source or target model types.
*/
public void addAdmissibleAllocationTablePair(Class<? extends AllocationTable> atType1,
Class<? extends AllocationTable> atType2);
/**
* For the given {@link AllocationTable} types, returns the {@link AllocationTable}s that can
* exist together with it despite overlapping source or target model types.
*/
public Collection<Class<? extends AllocationTable>> getAdmissibleAllocationTables(
Class<? extends AllocationTable> allocationTableType);
}
AllocationTableCollectionCompositorBase.java 2aff2eb8218e0be0a36d3c0b50578b985a87a6fd GREEN
AllocationTableCollectionCompositorBase.java c4e96374d921ea1f5651656163a5c0e0bc91b7e1 YELLOW
AllocationTableFileProjectCompositor.java 473e902ccb0611539df5f9eb38d7f61357290f57 GREEN
......@@ -15,14 +15,18 @@
+--------------------------------------------------------------------------*/
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 org.eclipse.emf.ecore.EObject;
import org.fortiss.af3.allocation.IAllocationService;
import org.fortiss.af3.allocation.model.AllocationTable;
import org.fortiss.af3.allocation.model.AllocationTableCollection;
import org.fortiss.tooling.base.compose.ModelElementCompositorBase;
import org.fortiss.tooling.kernel.extension.data.IElementCompositionContext;
import org.fortiss.tooling.kernel.extension.data.Prototype;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
/**
* Base compositor for adding {@link AllocationTable} specializations to
......@@ -80,8 +84,71 @@ public abstract class AllocationTableCollectionCompositorBase extends
public boolean canCompose(AllocationTableCollection container, EObject contained,
IElementCompositionContext context) {
return (maxAllocationTableInstances == 0 || getNumberOfAllocationTables(container) < maxAllocationTableInstances) &&
allocationTableType.isAssignableFrom(contained.getClass());
// Check type
if(!allocationTableType.isAssignableFrom(contained.getClass())) {
return false;
}
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) {
return false;
}
final Class<? extends IProjectRootElement> targetModelType =
as.getTargetModelType(allocationTableType);
if(getRootElement(container, targetModelType) == null) {
return false;
}
// Check if maximum number of instances has already been added
if(maxAllocationTableInstances != 0 &&
getNumberOfAllocationTables(container) >= maxAllocationTableInstances) {
return false;
}
// Check if source or target model has not already been occupied by another allocation table
for(AllocationTable at : container.getAllocationTables()) {
Class<? extends AllocationTable> atType = getAllocationTableType(at.getClass());
// Skip check for allocation tables of the same type (only relevant if
// maxAllocationTableInstances != 1)
if(allocationTableType.isAssignableFrom(atType)) {
continue;
}
// Skip check also for registered exceptions
if(as.getAdmissibleAllocationTables(allocationTableType).contains(atType)) {
continue;
}
// 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)) {
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;
}
}
for(Class<? extends IProjectRootElement> coveredModelType : as
.getCoveredModelTypes(allocationTableType)) {
if(coveredModelType.isAssignableFrom(sourceViewType) ||
coveredModelType.isAssignableFrom(targetViewType)) {
return false;
}
}
}
return true;
}
/** {@inheritDoc} */
......
......@@ -20,13 +20,16 @@ import static java.util.Collections.emptyList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import org.fortiss.af3.allocation.IAllocationService;
import org.fortiss.af3.allocation.model.AllocationEntry;
import org.fortiss.af3.allocation.model.AllocationTable;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
import org.fortiss.tooling.kernel.introspection.IIntrospectionItem;
import org.fortiss.tooling.kernel.introspection.IIntrospectiveKernelService;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
import org.fortiss.tooling.kernel.service.IKernelIntrospectionSystemService;
/**
......@@ -49,6 +52,47 @@ public final class AllocationService implements IAllocationService, IIntrospecti
/** Maps an {@link AllocationEntry} to the list of admissible target element types. */
private EntityTypeMap targetEntityTypeMap = new EntityTypeMap();
/** Maps an {@link AllocationTable} type to a source model type. */
private Map<Class<? extends AllocationTable>, Class<? extends IProjectRootElement>> sourceModelTypeMap =
new HashMap<Class<? extends AllocationTable>, Class<? extends IProjectRootElement>>();
/** Maps an {@link AllocationTable} type to a target model type. */
private Map<Class<? extends AllocationTable>, Class<? extends IProjectRootElement>> targetModelTypeMap =
new HashMap<Class<? extends AllocationTable>, Class<? extends IProjectRootElement>>();
/**
* Type used to map {@link AllocationTable}s to model types are covered by it in addition to
* their source and target model types.
*/
private class CoveredModelTypeMap
extends
HashMap<Class<? extends AllocationTable>, LinkedHashSet<Class<? extends IProjectRootElement>>> {
// Nothing to do
}
/**
* Maps {@link AllocationTable}s to model types are covered by it in addition to their
* source and target model types.
*/
private CoveredModelTypeMap coveredModelTypeMap = new CoveredModelTypeMap();
/**
* Type used to map a given {@link AllocationTable} to {@link AllocationTable}s that may exist
* together with it despite overlapping source/target model types.
*/
private class AdmissibleAllocationTableTypeMap
extends
HashMap<Class<? extends AllocationTable>, LinkedHashSet<Class<? extends AllocationTable>>> {
// Nothing to do
}
/**
* Maps a given {@link AllocationTable} to {@link AllocationTable}s that may exist
* together with it despite overlapping source/target model types.
*/
private AdmissibleAllocationTableTypeMap admissibleAllocationTableTypeMap =
new AdmissibleAllocationTableTypeMap();
/** The singleton instance. */
private static final AllocationService INSTANCE = new AllocationService();
......@@ -106,14 +150,119 @@ public final class AllocationService implements IAllocationService, IIntrospecti
@Override
public Collection<Class<? extends IModelElement>> getSourceEntityTypes(
Class<? extends AllocationEntry> allocationEntryType) {
return sourceEntityTypeMap.get(allocationEntryType);
final LinkedHashSet<Class<? extends IModelElement>> rval =
sourceEntityTypeMap.get(allocationEntryType);
return rval != null ? rval : emptyList();
}
/** {@inheritDoc} */
@Override
public Collection<Class<? extends IModelElement>> getTargetEntityTypes(
Class<? extends AllocationEntry> allocationEntryType) {
return targetEntityTypeMap.get(allocationEntryType);
final LinkedHashSet<Class<? extends IModelElement>> rval =
targetEntityTypeMap.get(allocationEntryType);
return rval != null ? rval : emptyList();
}
/** {@inheritDoc} */
@Override
public 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);
}
/** {@inheritDoc} */
@Override
public 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 Class<? extends IProjectRootElement> getSourceModelType(
Class<? extends AllocationTable> allocationTableType) {
final Class<? extends IProjectRootElement> rval =
sourceModelTypeMap.get(allocationTableType);
return rval;
}
/** {@inheritDoc} */
@Override
public Class<? extends IProjectRootElement> getTargetModelType(
Class<? extends AllocationTable> allocationTableType) {
return targetModelTypeMap.get(allocationTableType);
}
/** {@inheritDoc} */
@Override
public void addCoveredModelType(Class<? extends AllocationTable> allocationTableType,
Class<? extends IProjectRootElement> targetModelType) {
LinkedHashSet<Class<? extends IProjectRootElement>> coveredModelTypes =
coveredModelTypeMap.get(allocationTableType);
if(coveredModelTypes == null) {
coveredModelTypes = new LinkedHashSet<Class<? extends IProjectRootElement>>();
coveredModelTypeMap.put(allocationTableType, coveredModelTypes);
}
coveredModelTypes.add(targetModelType);
}
/** {@inheritDoc} */
@Override
public Collection<Class<? extends IProjectRootElement>> getCoveredModelTypes(
Class<? extends AllocationTable> allocationTableType) {
final LinkedHashSet<Class<? extends IProjectRootElement>> rval =
coveredModelTypeMap.get(allocationTableType);
return rval != null ? rval : emptyList();
}
/** Helper to implement {@link #addAdmissibleAllocationTablePair(Class, Class)}. */
private void addAdmissibleAllocationTablePairInternal(Class<? extends AllocationTable> atType1,
Class<? extends AllocationTable> atType2) {
LinkedHashSet<Class<? extends AllocationTable>> allocationTableTypes =
admissibleAllocationTableTypeMap.get(atType1);
if(allocationTableTypes == null) {
allocationTableTypes = new LinkedHashSet<Class<? extends AllocationTable>>();
admissibleAllocationTableTypeMap.put(atType1, allocationTableTypes);
}
allocationTableTypes.add(atType2);
}
/**
* Registers a pair of {@link AllocationTable} types that can exist together despite overlapping
* source or target model types.
*/
@Override
public void addAdmissibleAllocationTablePair(Class<? extends AllocationTable> atType1,
Class<? extends AllocationTable> atType2) {
addAdmissibleAllocationTablePairInternal(atType1, atType2);
addAdmissibleAllocationTablePairInternal(atType2, atType1);
}
/**
* For the given {@link AllocationTable} types, returns the {@link AllocationTable}s that can
* exist together with it despite overlapping source or target model types.
*/
@Override
public Collection<Class<? extends AllocationTable>> getAdmissibleAllocationTables(
Class<? extends AllocationTable> allocationTableType) {
final LinkedHashSet<Class<? extends AllocationTable>> rval =
admissibleAllocationTableTypeMap.get(allocationTableType);
return rval != null ? rval : emptyList();
}
// ////////////// Implementation of IIntrospectiveKernelService ////////////////
......
AllocationModelElementFactory.java 0d13ccc9da944dd9a25db262eb1fa47d1a9582e9 GREEN
AllocationUtils.java 931599c5dfd7e875de59459ad8d01b0278a24ef5 GREEN
AllocationUtils.java 09a83514c72d30ff1f2c42fd286a9db9691d37a0 YELLOW
......@@ -307,4 +307,16 @@ public class AllocationUtils {
" must implement either IUniDirectional or IBidirectional.");
}
}
/** Returns the interface defining the type an {@link AllocationTable} implementation. */
@SuppressWarnings("unchecked")
public static <T> Class<T> getAllocationTableType(Class<? extends T> allocationTableImplType) {
for(Class<?> iFace : allocationTableImplType.getInterfaces()) {
if(AllocationTable.class.isAssignableFrom(iFace)) {
return (Class<T>)iFace;
}
}
return null;
}