| 1 | /** |
| 2 | * |
| 3 | */ |
| 4 | package de.fzi.se.accuracy.jobs; |
| 5 | |
| 6 | import java.util.ArrayList; |
| 7 | import java.util.List; |
| 8 | |
| 9 | import org.apache.log4j.Logger; |
| 10 | import org.eclipse.core.runtime.IProgressMonitor; |
| 11 | |
| 12 | import de.fzi.se.accuracy.transformation.AbstractAccuracyInfluenceSEFFTransformationStrategy; |
| 13 | import de.fzi.se.accuracy.transformation.AccuracyInfluenceSEFFTransformationStrategyAsSpecified; |
| 14 | import de.fzi.se.accuracy.transformation.AccuracyInfluenceSEFFTransformationStrategyMaximum; |
| 15 | import de.fzi.se.accuracy.transformation.AccuracyInfluenceSEFFTransformationStrategyMinimum; |
| 16 | import de.uka.ipd.sdq.pcm.allocation.Allocation; |
| 17 | import de.uka.ipd.sdq.pcm.allocation.AllocationContext; |
| 18 | import de.uka.ipd.sdq.pcm.core.composition.AssemblyContext; |
| 19 | import de.uka.ipd.sdq.pcm.core.composition.ComposedStructure; |
| 20 | import de.uka.ipd.sdq.pcm.repository.BasicComponent; |
| 21 | import de.uka.ipd.sdq.pcm.repository.RepositoryComponent; |
| 22 | import de.uka.ipd.sdq.pcm.seff.ServiceEffectSpecification; |
| 23 | import de.uka.ipd.sdq.workflow.IBlackboardInteractingJob; |
| 24 | import de.uka.ipd.sdq.workflow.OrderPreservingBlackboardCompositeJob; |
| 25 | import de.uka.ipd.sdq.workflow.exceptions.JobFailedException; |
| 26 | import de.uka.ipd.sdq.workflow.exceptions.UserCanceledException; |
| 27 | import de.uka.ipd.sdq.workflow.mdsd.blackboard.MDSDBlackboard; |
| 28 | import de.uka.ipd.sdq.workflow.pcm.blackboard.PCMResourceSetPartition; |
| 29 | import de.uka.ipd.sdq.workflow.pcm.configurations.AbstractPCMWorkflowRunConfiguration; |
| 30 | import de.uka.ipd.sdq.workflow.pcm.jobs.LoadPCMModelsIntoBlackboardJob; |
| 31 | |
| 32 | /**Job executing transformations of PCM models for the accuracy analysis. |
| 33 | * As it modifies the PCM models, it should only be invoked after a working copy of the models is created. |
| 34 | * @author groenda |
| 35 | * |
| 36 | */ |
| 37 | public class TransformPCMForAccuracyInfluenceAnalysisJob extends OrderPreservingBlackboardCompositeJob<MDSDBlackboard> implements |
| 38 | IBlackboardInteractingJob<MDSDBlackboard> { |
| 39 | |
| 40 | /** Logger for this class. */ |
| 41 | private static final Logger logger = Logger.getLogger(TransformPCMForAccuracyInfluenceAnalysisJob.class); |
| 42 | |
| 43 | /** Workflow configuration used by this job.*/ |
| 44 | private AbstractPCMWorkflowRunConfiguration configuration; |
| 45 | |
| 46 | public TransformPCMForAccuracyInfluenceAnalysisJob(AbstractPCMWorkflowRunConfiguration configuration) { |
| 47 | super(); |
| 48 | this.configuration = configuration; |
| 49 | } |
| 50 | |
| 51 | @Override |
| 52 | public void execute(IProgressMonitor monitor) throws JobFailedException, |
| 53 | UserCanceledException { |
| 54 | if (!configuration.isAccuracyInfluenceAnalysisEnabled()) { |
| 55 | throw new IllegalArgumentException("The transformation job on PCM models for the accuracy analysis may only be run if the accuracy influence analysis is enabled."); |
| 56 | } |
| 57 | PCMResourceSetPartition pcmPartition = (PCMResourceSetPartition) this |
| 58 | .getBlackboard().getPartition( |
| 59 | LoadPCMModelsIntoBlackboardJob.PCM_MODELS_PARTITION_ID); |
| 60 | // discover all SEFFs potentially used in the system |
| 61 | Allocation allocation = pcmPartition.getAllocation(); |
| 62 | List<ServiceEffectSpecification> allocatedSEFFs = new ArrayList<ServiceEffectSpecification>(); |
| 63 | for (AllocationContext allocationContext: allocation.getAllocationContexts_Allocation()) { |
| 64 | AssemblyContext outmostAssemblyContext = allocationContext.getAssemblyContext_AllocationContext(); |
| 65 | List<ServiceEffectSpecification> assembledSEFFs = discoverSEFFs(outmostAssemblyContext); |
| 66 | addElementsToList(allocatedSEFFs, assembledSEFFs); |
| 67 | } |
| 68 | |
| 69 | // modify SEFFs according to AccuracyInfluenceAnalysisState |
| 70 | AbstractAccuracyInfluenceSEFFTransformationStrategy accuracyInfluenceSEFFtransformator; |
| 71 | switch (configuration.getAccuracyInfluenceAnalysisState()) { |
| 72 | case MINIMUM: |
| 73 | accuracyInfluenceSEFFtransformator = new AccuracyInfluenceSEFFTransformationStrategyMinimum(pcmPartition); |
| 74 | break; |
| 75 | case AS_SPECIFIED: |
| 76 | accuracyInfluenceSEFFtransformator = new AccuracyInfluenceSEFFTransformationStrategyAsSpecified(pcmPartition); |
| 77 | break; |
| 78 | case MAXIMUM: |
| 79 | accuracyInfluenceSEFFtransformator = new AccuracyInfluenceSEFFTransformationStrategyMaximum(pcmPartition); |
| 80 | break; |
| 81 | default: |
| 82 | String msg = "The handling of the accuracy influence strategy " |
| 83 | + configuration.getAccuracyInformationModelFile() |
| 84 | + " provided in the configuration is not implemented."; |
| 85 | logger.fatal(msg); |
| 86 | throw new IllegalArgumentException(msg); |
| 87 | } |
| 88 | for (ServiceEffectSpecification seff : allocatedSEFFs) { |
| 89 | accuracyInfluenceSEFFtransformator.doSwitch(seff); |
| 90 | } |
| 91 | if (configuration.getAccuracyInfluenceIssueReceivingJob() == null) { |
| 92 | logger.warn("No job was specified to receive issues occured during accuracy influence analysis. There will be no notifications about warnings or errors."); |
| 93 | } else { |
| 94 | configuration.getAccuracyInfluenceIssueReceivingJob().addIssues(accuracyInfluenceSEFFtransformator.getIssues()); |
| 95 | } |
| 96 | |
| 97 | } |
| 98 | |
| 99 | /**Discovers all SEFFs which are used in an assembly context. |
| 100 | * @param outmostAssemblyContext |
| 101 | * @return List of discovered SEFFs. |
| 102 | */ |
| 103 | private List<ServiceEffectSpecification> discoverSEFFs( |
| 104 | AssemblyContext assemblyContext) { |
| 105 | // see Validation.emf::FromAllocationToSEFF for a graphical overview of the used nodes and references |
| 106 | List<ServiceEffectSpecification> composedSEFFs = new ArrayList<ServiceEffectSpecification>(); |
| 107 | RepositoryComponent repositoryComponent = assemblyContext.getEncapsulatedComponent__AssemblyContext(); |
| 108 | if (repositoryComponent instanceof ComposedStructure) { |
| 109 | ComposedStructure composedStructure = (ComposedStructure) repositoryComponent; |
| 110 | for (AssemblyContext composedComponentsContext: composedStructure.getAssemblyContexts__ComposedStructure()) { |
| 111 | List<ServiceEffectSpecification> assembledSEFFs = discoverSEFFs(composedComponentsContext); |
| 112 | addElementsToList(composedSEFFs, assembledSEFFs); |
| 113 | } |
| 114 | } else if (repositoryComponent instanceof BasicComponent) { |
| 115 | BasicComponent basicComponent = (BasicComponent) repositoryComponent; |
| 116 | addElementsToList(composedSEFFs, basicComponent.getServiceEffectSpecifications__BasicComponent()); |
| 117 | } else { |
| 118 | logger.warn("Could not process the provided repository component " + repositoryComponent.getEntityName() + " with id " + repositoryComponent.getId() + ". The component type is not supported by the implementation."); |
| 119 | } |
| 120 | return composedSEFFs; |
| 121 | } |
| 122 | |
| 123 | /**Adds a list of SEFFs to another list. |
| 124 | * Existing SEFFs are not added twice to the list. |
| 125 | * @param target The list which will receive the SEFFs of source. |
| 126 | * @param source The SEFFs to add. |
| 127 | */ |
| 128 | public static <T> void addElementsToList(List<T> target, final List<T> source) { |
| 129 | for (T t : source) { |
| 130 | if (!target.contains(t)) { |
| 131 | //TODO: Check if comparison works. Should do the job as only obj == obj2 should be excluded from the list |
| 132 | target.add(t); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | } |