| /******************************************************************************* |
| * 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); |
| } |
| |
| |
| |
| } |