blob: 057282e4dd6954863d068a93df5ef31972ed8823 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Parasoft.
*
* 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
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Janusz Studzizba - initial API and implementation
* Dariusz Oszczedlowski - initial API and implementation
* Magdalena Gniewek - initial API and implementation
* Michal Wlodarczyk - initial API and implementation
*******************************************************************************/
package org.eclipse.opencert.impactanalysis;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.view.CDOQuery;
import org.eclipse.opencert.apm.assuranceassets.assuranceasset.AssuranceAssetEvent;
import org.eclipse.opencert.apm.assuranceassets.assuranceasset.EventKind;
import org.eclipse.opencert.infra.general.general.ChangeEffectKind;
import org.eclipse.opencert.evm.evidspec.evidence.Artefact;
import org.eclipse.opencert.impactanalysis.eventcreators.ChangeDrivenEventsCreatorsFactory;
import org.eclipse.opencert.impactanalysis.eventcreators.IChangeDrivenEventsCreator;
import org.eclipse.opencert.impactanalysis.relations.ArtefactRelationType;
import org.eclipse.opencert.impactanalysis.relations.IArtefactRelationImpact;
import org.eclipse.opencert.impactanalysis.relations.RelationVisitationRecord;
import org.eclipse.opencert.impactanalysis.relations.traverse.DirectAndBaseRelationsTraverser;
import org.eclipse.opencert.impactanalysis.relations.traverse.DirectArtefactsRelationsTraverser;
import org.eclipse.opencert.impactanalysis.relations.traverse.IArtefactsRelationsTraverser;
import org.eclipse.opencert.storage.cdo.CDOStorageUtil;
import org.eclipse.opencert.storage.cdo.executors.SessionNotClosingInTransactionExecutor;
import org.eclipse.opencert.storage.cdo.property.IOpencertClientConfigurationAdapter;
import org.eclipse.opencert.storage.cdo.property.OpencertPropertiesReader;
import org.eclipse.opencert.storage.cdo.session.ICDOSessionProvider;
import org.eclipse.opencert.storage.cdo.session.SimpleCDOSessionProvider;
public class ImpactAnalyser
{
private final ICDOSessionProvider cdoSessionProvider;
public ImpactAnalyser(IOpencertClientConfigurationAdapter clientConfigurationAdapter)
{
cdoSessionProvider = new SimpleCDOSessionProvider(clientConfigurationAdapter);
}
public ImpactAnalyser(ICDOSessionProvider icdoSessionProvider)
{
cdoSessionProvider = icdoSessionProvider;
}
public List<IArtefactRelationImpact> listArtefactsRelationImpacts(final List<ImpactSource> impactSources)
{
final List<IArtefactRelationImpact> artefactsRelationImpacts = new ArrayList<IArtefactRelationImpact>();
final Set<RelationVisitationRecord> artefactRelVisitationRecords = new HashSet<>();
new SessionNotClosingInTransactionExecutor(cdoSessionProvider)
{
@Override
public void executeInTransaction(CDOTransaction cdoTransaction)
{
for (ImpactSource impactSource : impactSources) {
recurseAllImpactedArtefactRelations(
impactSource.getImpactingArtefactCdoId(),
null,
impactSource.getImpactingEventKind(),
artefactsRelationImpacts, artefactRelVisitationRecords, cdoTransaction, 0);
}
}
}.executeReadOnlyOperation();
return artefactsRelationImpacts;
}
public String visualizeArtefactsRelationImpacts(List<IArtefactRelationImpact> artefactsRelationImpacts)
{
return visualizeArtefactsRelationImpacts(artefactsRelationImpacts, "\t", "\n");
}
public String visualizeArtefactsRelationImpacts(List<IArtefactRelationImpact> artefactsRelationImpacts, String indendationString, String nextLineString)
{
StringBuilder stringBuilder = new StringBuilder();
for (IArtefactRelationImpact artefactsRelationImpact : artefactsRelationImpacts) {
for (int nr = 0; nr < artefactsRelationImpact.getRecursionDepth(); nr++) {
stringBuilder.append(indendationString);
}
stringBuilder.append(artefactsRelationImpact.toString());
stringBuilder.append(nextLineString);
}
return stringBuilder.toString();
}
public void close()
{
cdoSessionProvider.close();
}
public void executeArtefactsRelationImpacts(final List<IArtefactRelationImpact> artefactsRelationImpacts)
{
new SessionNotClosingInTransactionExecutor(cdoSessionProvider)
{
@Override
public void executeInTransaction(CDOTransaction cdoTransaction)
{
for (IArtefactRelationImpact artefactsRelationImpact : artefactsRelationImpacts) {
//we execute only these two types
if (!ArtefactRelationType.DIRECT_EVIDENCE_RELATION.equals(artefactsRelationImpact.getArtefactRelationType())
&& !ArtefactRelationType.BASELINE_TO_EVIDENCE_VIA_MAP_RELATION.equals(artefactsRelationImpact.getArtefactRelationType())) {
continue;
}
ChangeEffectKind impactedChangeEffectKind = artefactsRelationImpact.getImpactedChangeEffectKind();
IChangeDrivenEventsCreator changeDrivenEventsCreator = ChangeDrivenEventsCreatorsFactory.
getProperChangeDrivenEventsCreator(impactedChangeEffectKind);
//none found, abort
if (changeDrivenEventsCreator == null) {
continue;
}
AssuranceAssetEvent newEvent = changeDrivenEventsCreator.produceEvent(artefactsRelationImpact, impactedChangeEffectKind);
Artefact impactedArtefact = queryForArtefact(artefactsRelationImpact.getImpactedArtefactCDOId(), cdoTransaction);
if (impactedArtefact == null) {
throw new RuntimeException("IA execution called for impactedArtefact which doesn't exist in database");
}
impactedArtefact.getLifecycleEvent().add(newEvent);
}
}
}.executeReadWriteOperation();
}
private void recurseAllImpactedArtefactRelations(
Long impactSourceCdoId,
IArtefactRelationImpact sourceArtefactRelationImpact,
EventKind impactingEventKind,
List<IArtefactRelationImpact> artefactsRelationImpacts,
Set<RelationVisitationRecord> artefactRelVisitationRecords,
CDOTransaction cdoTransaction,
int recursionDepth)
{
final boolean isImpactAnalysisViaBaselineElementsEnabled = OpencertPropertiesReader.getInstance().isImpactAnalysisViaBaselineElementsEnabled();
IArtefactsRelationsTraverser relationsTraverser = isImpactAnalysisViaBaselineElementsEnabled ?
new DirectAndBaseRelationsTraverser() :
new DirectArtefactsRelationsTraverser();
List<IArtefactRelationImpact> artefactRelationImpacts =
relationsTraverser.generateArtefactRelationImpactsList(cdoTransaction, impactSourceCdoId, sourceArtefactRelationImpact, recursionDepth,
impactingEventKind);
for (IArtefactRelationImpact artefactRelationImpact : artefactRelationImpacts) {
EventKind newImpactingEventKind = null;
newImpactingEventKind = artefactRelationImpact.generateNewEventBasedOnChangeEffectKindOrForwardCurrent(impactingEventKind);
if (newImpactingEventKind == null) {
continue;
}
//check and skip if already visited this relation WITH THIS EXACT impactedChangeEffectKind
//this skips cycles
RelationVisitationRecord artefactRelVisitationRecord = new RelationVisitationRecord(artefactRelationImpact);
if (artefactRelVisitationRecords.contains(artefactRelVisitationRecord)) {
continue;
}
artefactRelVisitationRecords.add(artefactRelVisitationRecord);
artefactsRelationImpacts.add(artefactRelationImpact);
recurseAllImpactedArtefactRelations(artefactRelationImpact.getImpactedArtefactCDOId(), artefactRelationImpact,
newImpactingEventKind, artefactsRelationImpacts, artefactRelVisitationRecords,
cdoTransaction, recursionDepth + 1);
}
}
private Artefact queryForArtefact(
Long impactingArtefactCdoId,
CDOTransaction cdoTransaction)
{
CDOQuery query = cdoTransaction.createQuery("sql", "select * from evidence_artefact where cdo_id = "
+ impactingArtefactCdoId + CDOStorageUtil.getMandatoryCDOQuerySuffix());
return query.getResultValue(Artefact.class);
}
}