blob: 790b4663550901bef2f20fb35e99632d03e0ff7f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2019 Chalmers | University of Gothenburg, rt-labs and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
* Chalmers | University of Gothenburg - additional features, updated API
*******************************************************************************/
package org.eclipse.capra.core.adapters;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.capra.core.handlers.IArtifactHandler;
import org.eclipse.capra.core.helpers.ArtifactHelper;
import org.eclipse.capra.core.helpers.ExtensionPointHelper;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
/**
* Implements standard functionality for the methods defined in the
* {@link TraceMetaModelAdapter}.
*/
public abstract class AbstractMetaModelAdapter implements TraceMetaModelAdapter {
private List<Connection> getInternalElementsTransitive(EObject element, EObject traceModel,
List<Object> accumulator, List<String> selectedRelationshipTypes, int currentDepth, int maximumDepth,
List<Connection> existingTraces) {
List<Connection> directElements = getInternalElements(element, traceModel, selectedRelationshipTypes, true,
maximumDepth, existingTraces);
List<Connection> allElements = new ArrayList<>();
int currDepth = currentDepth + 1;
for (Connection connection : directElements) {
if (!accumulator.contains(connection.getTlink())) {
allElements.add(connection);
accumulator.add(connection.getTlink());
for (EObject e : connection.getTargets()) {
if (maximumDepth == 0 || currDepth < (maximumDepth + 2)) {
allElements.addAll(getInternalElementsTransitive(e, traceModel, accumulator,
selectedRelationshipTypes, currDepth, maximumDepth, existingTraces));
}
}
}
}
return allElements;
}
/**
* Used to get internal links connected to a selected element.
*
* @param element the selected element
* @param traceModel the current trace model
* @param selectedRelationshipTypes the selected relationship types from the
* filter, if the user has selected any
* @param maximumDepth The maximum depth the transitivity should
* go. 0 means show all the links
* @param existingTraces The trace links that have been created
* manually by the user, these are obtained
* from the trace model
*/
@Override
public List<Connection> getInternalElementsTransitive(EObject element, EObject traceModel,
List<String> selectedRelationshipTypes, int maximumDepth, List<Connection> existingTraces) {
List<Object> accumulator = new ArrayList<>();
return getInternalElementsTransitive(element, traceModel, accumulator, selectedRelationshipTypes, 0,
maximumDepth, existingTraces);
}
@SuppressWarnings("unchecked")
@Override
public List<Connection> getInternalElements(EObject element, EObject traceModel,
List<String> selectedRelationshipTypes, boolean traceLinksTransitive, int transitivityDepth,
List<Connection> existingTraces) {
List<Connection> allElements = new ArrayList<>();
List<Connection> directElements;
if (traceLinksTransitive) {
directElements = getTransitivelyConnectedElements(element, traceModel, selectedRelationshipTypes,
transitivityDepth);
} else {
directElements = getConnectedElements(element, traceModel, selectedRelationshipTypes);
}
List<Integer> hashCodes = new ArrayList<>();
for (Connection conn : existingTraces) {
int connectionHash = conn.getOrigin().hashCode() + conn.getTlink().hashCode();
for (EObject targ : conn.getTargets()) {
connectionHash += targ.hashCode();
}
hashCodes.add(connectionHash);
}
ResourceSet resourceSet = new ResourceSetImpl();
TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().orElseThrow();
EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
ArtifactHelper artifactHelper = new ArtifactHelper(artifactModel);
for (Connection conn : directElements) {
int connectionHash = conn.getOrigin().hashCode() + conn.getTlink().hashCode();
for (EObject targ : conn.getTargets()) {
connectionHash += targ.hashCode();
}
if (!hashCodes.contains(connectionHash)) {
allElements.add(conn);
}
// get internal links from source
Object origin = artifactHelper.unwrapWrapper(conn.getOrigin());
IArtifactHandler<?> originHandler = artifactHelper.getHandler(origin).orElseThrow();
if (originHandler != null) {
allElements.addAll(originHandler.addInternalLinks(conn.getOrigin(), selectedRelationshipTypes));
}
// get internal links from targets
for (EObject o : conn.getTargets()) {
Object originalObject = artifactHelper.unwrapWrapper(o);
IArtifactHandler<?> handler = artifactHelper.getHandler(originalObject).orElseThrow();
if (handler != null) {
allElements.addAll(handler.addInternalLinks(o, selectedRelationshipTypes));
}
}
}
// show internal links even when no Capra links are present
if (directElements.isEmpty()) {
Object originalObject = artifactHelper.unwrapWrapper(element);
IArtifactHandler<?> handler = artifactHelper.getHandler(originalObject).orElseThrow();
if (handler != null) {
allElements.addAll(handler.addInternalLinks(element, selectedRelationshipTypes));
}
}
if (element.getClass().getPackage().toString().contains("org.eclipse.eatop")) {
IArtifactHandler<Object> handler = (IArtifactHandler<Object>) artifactHelper.getHandler(element)
.orElseThrow();
allElements.addAll(handler.addInternalLinks(element, selectedRelationshipTypes));
}
return allElements;
}
@Override
public boolean isThereAnInternalTraceBetween(EObject first, EObject second) {
ResourceSet resourceSet = new ResourceSetImpl();
TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().orElseThrow();
EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
ArtifactHelper artifactHelper = new ArtifactHelper(artifactModel);
IArtifactHandler<?> handlerFirstElement = artifactHelper.getHandler(first).orElseThrow();
IArtifactHandler<?> handlerSecondElement = artifactHelper.getHandler(second).orElseThrow();
return handlerFirstElement.isThereAnInternalTraceBetween(first, second)
|| handlerSecondElement.isThereAnInternalTraceBetween(first, second);
}
}