EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][de.uka.ipd.sdq.dsexplore.designdecisions.alternativecomponents]

COVERAGE SUMMARY FOR SOURCE FILE [AlternativeComponent.java]

nameclass, %method, %block, %line, %
AlternativeComponent.java0%   (0/1)0%   (0/12)0%   (0/606)0%   (0/129)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AlternativeComponent0%   (0/1)0%   (0/12)0%   (0/606)0%   (0/129)
<static initializer> 0%   (0/1)0%   (0/8)0%   (0/3)
AlternativeComponent (): void 0%   (0/1)0%   (0/6)0%   (0/3)
applyChange (AssemblyContext, RepositoryComponent): void 0%   (0/1)0%   (0/25)0%   (0/7)
createAssembledComponentDecisionsInstances (PCMInstance, Map): List 0%   (0/1)0%   (0/54)0%   (0/9)
createDesignDecision (PCMInstance, Map$Entry): AssembledComponentDegree 0%   (0/1)0%   (0/18)0%   (0/4)
findAlternatives (List, List, System): Map 0%   (0/1)0%   (0/36)0%   (0/7)
findProvidedConnectors (AssemblyContext, System, Map): List 0%   (0/1)0%   (0/80)0%   (0/14)
findRequiredConnectors (AssemblyContext, System, Map): List 0%   (0/1)0%   (0/80)0%   (0/14)
findRoleMappingFor (AssemblyContext, RepositoryComponent, System): ComponentR... 0%   (0/1)0%   (0/191)0%   (0/47)
generateDesignDecisions (PCMInstance): List 0%   (0/1)0%   (0/54)0%   (0/9)
getAlternatives (AssemblyContext, List, System): Map 0%   (0/1)0%   (0/52)0%   (0/11)
getInstance (): AlternativeComponent 0%   (0/1)0%   (0/2)0%   (0/1)

1package de.uka.ipd.sdq.dsexplore.designdecisions.alternativecomponents;
2 
3import java.util.ArrayList;
4import java.util.Comparator;
5import java.util.IdentityHashMap;
6import java.util.List;
7import java.util.Map;
8import java.util.TreeMap;
9import java.util.Map.Entry;
10 
11import org.apache.log4j.Logger;
12import org.eclipse.emf.common.util.EList;
13 
14import de.uka.ipd.sdq.dsexplore.helper.EMFHelper;
15import de.uka.ipd.sdq.dsexplore.helper.EntityComparator;
16import de.uka.ipd.sdq.pcm.core.composition.AssemblyConnector;
17import de.uka.ipd.sdq.pcm.core.composition.AssemblyContext;
18import de.uka.ipd.sdq.pcm.core.composition.Connector;
19import de.uka.ipd.sdq.pcm.core.composition.ProvidedDelegationConnector;
20import de.uka.ipd.sdq.pcm.core.composition.RequiredDelegationConnector;
21import de.uka.ipd.sdq.pcm.core.entity.Entity;
22import de.uka.ipd.sdq.pcm.designdecision.AssembledComponentDegree;
23import de.uka.ipd.sdq.pcm.designdecision.impl.designdecisionFactoryImpl;
24import de.uka.ipd.sdq.pcm.repository.OperationProvidedRole;
25import de.uka.ipd.sdq.pcm.repository.OperationRequiredRole;
26import de.uka.ipd.sdq.pcm.repository.ProvidedRole;
27import de.uka.ipd.sdq.pcm.repository.Repository;
28import de.uka.ipd.sdq.pcm.repository.RepositoryComponent;
29import de.uka.ipd.sdq.pcm.repository.RequiredRole;
30import de.uka.ipd.sdq.pcm.system.System;
31import de.uka.ipd.sdq.pcmsolver.models.PCMInstance;
32 
33//Singleton
34/**
35 * TODO: Currently, components must have the same provided _and_ required roles, otherwise, an erroneous system is created.   
36 */
37public class AlternativeComponent  {
38 
39        private static Logger logger = Logger.getLogger("de.uka.ipd.sdq.dsexplore");
40        
41 
42        /** Model files will get the suffix here plus the generation number**/
43        //private static String modelFilesSuffix = "-AC";
44        
45        //Repository lastRepository = null;
46        
47        Map<AssemblyContext, Map<RepositoryComponent, ComponentReplacer>> alternativeMap = null;
48        
49        //EvolutionGraphNode rootNode = null;
50        
51        private static AlternativeComponent instance = new AlternativeComponent();
52 
53        private AlternativeComponent() {
54                
55        }
56        
57        public static AlternativeComponent getInstance(){
58                return AlternativeComponent.instance;
59        }
60 
61        /**
62         * @see de.uka.ipd.sdq.dsexplore.newcandidates.INewCandidates#generateNewCandidates(de.uka.ipd.sdq.dsexplore.analysis.IAnalysisResult)
63         */
64        public List<AssembledComponentDegree> generateDesignDecisions(PCMInstance pcmInstance) {
65                
66                //Retrieve all components from all repositories
67                
68                List<Repository> repositories = pcmInstance.getRepositories();
69                
70                System s = pcmInstance.getSystem();
71 
72                List<RepositoryComponent> repoComponents = new ArrayList<RepositoryComponent>(15);
73                for (Repository repository : repositories) {
74                        repoComponents.addAll(repository.getComponents__Repository());
75                }
76                 
77 
78                alternativeMap = findAlternatives(repoComponents,s.getAssemblyContexts__ComposedStructure(),s);
79                logger.debug("I have a mapping for " + alternativeMap.size()
80                                + " AssemblyContexts with the following alternatives:");
81 
82                return createAssembledComponentDecisionsInstances(pcmInstance, alternativeMap);
83        }
84 
85        /**
86         * Creates a an {@link AssembledComponentDecision} for each alternative found. 
87         * Calls createDesignDecision for each alternative to be generated. 
88         * @param pcmInstance The current solution the new ones will base on
89         * @param alternativeMap2 The Map containing all replacement options
90         * @return A list of design decisions
91         */
92        private List<AssembledComponentDegree> createAssembledComponentDecisionsInstances(
93                        PCMInstance pcmInstance,
94                        Map<AssemblyContext, Map<RepositoryComponent, ComponentReplacer>> alternativeMap2) {
95                
96                List<AssembledComponentDegree> l = new ArrayList<AssembledComponentDegree>();
97                
98 
99                for (Map.Entry<AssemblyContext, Map<RepositoryComponent, ComponentReplacer>> mapping : alternativeMap2
100                                .entrySet()) {
101                        logger.debug("Assembly context " + mapping.getKey().getEntityName()
102                                        + " has " + mapping.getValue().size() + " fitting component(s).");
103                        
104                        //only save design decision if there are at least two components
105                        if (mapping.getValue().size() > 1){
106                                AssembledComponentDegree inst = createDesignDecision(pcmInstance, mapping); 
107                                l.add(inst);
108                        }
109                        
110                }
111                return l;
112        }
113        
114        /**
115         * Creates a {@link AssembledComponentDecision} for the given Entry. 
116         * The design decisions has the domain of all {@link RepositoryComponent}s 
117         * that are alternatives for the given {@link AssemblyContext}.  
118         * @param pcmInstance
119         * @param mappingEntry
120         * @return
121         */
122        private AssembledComponentDegree createDesignDecision(
123                        PCMInstance pcmInstance,
124                        Entry<AssemblyContext, Map<RepositoryComponent, ComponentReplacer>> mappingEntry) {
125                AssembledComponentDegree decision = designdecisionFactoryImpl.eINSTANCE.createAssembledComponentDegree();
126                
127                //Set domain to be all alternative components, i.e. all RepositoryComponents in the mapping. 
128                decision.getClassDesignOptions().addAll(mappingEntry.getValue().keySet());
129                
130                decision.setPrimaryChanged(mappingEntry.getKey());
131        
132                return decision;
133        }
134 
135 
136        /**
137         * Set the given {@link RepositoryComponent} as the encapsulated component of the given {@link AssemblyContext}
138         * 
139         * Fixes assembly connectors and delegation connectors that point to the 
140         * changed assembly so that they point to the new required and provided roles.
141         * 
142         * To do so, the right previously build component replacer is retrieved from {@link AlternativeComponent#alternativeMap}
143         * and replace is invoked, which applies the change.    
144         *
145         * @param changedAssemblyContext
146         * @param newComponent
147         * @param currentComponent
148         */
149        public void applyChange(AssemblyContext changedAssemblyContext, RepositoryComponent newComponent) {
150                
151                //call AlternativeComponent.generateDesigndecisions first to initialize.
152                if (this.alternativeMap == null){
153                        throw new RuntimeException("The AlternativeComponent operator has not properly been initialized. Check previous Exceptions or contact the developers.");
154                }
155                changedAssemblyContext.setEncapsulatedComponent__AssemblyContext(newComponent);
156                
157                Map<RepositoryComponent, ComponentReplacer> map =  this.alternativeMap.get(changedAssemblyContext);
158                ComponentReplacer componentReplacer = map.get(newComponent);
159                componentReplacer.replace();
160        }
161 
162        private Map<AssemblyContext, Map<RepositoryComponent, ComponentReplacer>> findAlternatives(
163                        List<RepositoryComponent> repoComponents,
164                        List<AssemblyContext> assemblyContexts, System s) {
165                
166                // Use IdentityHashMap to compare BasicComponents only by reference
167                // identity, i.e. two BasicComponents are only equal if they are the
168                // same object.
169                Comparator<Entity> c = new EntityComparator();
170 
171                Map<AssemblyContext, Map<RepositoryComponent,ComponentReplacer>> alternativeMap = new TreeMap<AssemblyContext, Map<RepositoryComponent,ComponentReplacer>>(c);
172 
173                for (AssemblyContext assemblyContext : assemblyContexts) {
174                        Map<RepositoryComponent,ComponentReplacer> map = getAlternatives(assemblyContext, repoComponents, s);
175                        if (map.size() > 0) {
176                                alternativeMap.put(assemblyContext, map);
177                        }
178                }
179 
180                return alternativeMap;
181        }
182 
183        /**
184         * Finds alternatives for a specific assembled component. To do so, this checks for each {@link RepositoryComponent} in the given {@link Repository}
185         * whether it fits in the given {@link AssemblyContext}.
186         * @param assemblyContext 
187         * @param repoComponents
188         * @param s 
189         * @return a Map of alternative {@link RepositoryComponent} with the {@link ComponentReplacer} that can put them in the {@link AssemblyContext}, which is possibly empty if no alternatives are found. 
190         */
191        private Map<RepositoryComponent, ComponentReplacer> getAlternatives(
192                        AssemblyContext assemblyContext, List<RepositoryComponent> repoComponents, System s) {
193 
194                Comparator<Entity> c = new EntityComparator();
195                Map<RepositoryComponent, ComponentReplacer> map = new TreeMap<RepositoryComponent, ComponentReplacer>(c);
196                for (RepositoryComponent repoComponent : repoComponents) {
197                        
198                        //if compatible, this returns not null
199                        ComponentReplacer p = findRoleMappingFor(assemblyContext, repoComponent, s);
200                
201                        if (p != null) {
202                                map.put(repoComponent,p);
203                                logger.debug("Found an alternative: "
204                                                + assemblyContext.getEntityName()
205                                                + " can encapsulate the component "
206                                                + repoComponent.getEntityName() + ".");
207                        } /*else {
208                                logger.debug(repoComponent.getEntityName()
209                                                + " is no alternative for "
210                                                + assembledComponent.getEntityName());
211                        }*/
212                }
213                return map;
214        }
215 
216        /**
217         * Checks provided and required interfaces and returns whether the
218         * interfaces are compatible so that the alternativeComponent can replace
219         * the assembledComponent. 
220         * 
221         * At the same time, this already finds out how to replace the 
222         * {@link RepositoryComponent} alternativeComponent if needed. Builds 
223         * a {@link ComponentReplacer} that stores all information how to replace the components.  
224         * 
225         * Returns null if the {@link RepositoryComponent} alternativeComponent cannot 
226         * be assembled in the given {@link AssemblyContext} assemblyContext. 
227         * 
228         * Current notion of compatible: allows the alternative to provide more and
229         * require less. TODO: Allow super interfaces and sub interfaces where
230         * appropriate
231         * @param assemblyContext 
232         * 
233         * @param assembledComponent
234         * @param alternativeComponent
235         * @param s 
236         * @return a map if alternativeComponent has compatible interfaces to replace
237         *         assembledComponent, null otherwise.
238         */
239        private ComponentReplacer findRoleMappingFor(AssemblyContext assemblyContext, 
240                        RepositoryComponent alternativeComponent, System s) {
241                
242                RepositoryComponent assembledComponent = assemblyContext.getEncapsulatedComponent__AssemblyContext();
243 
244                //logger.debug("isAlternativeFor(..) called");
245 
246                // first check whether the two parameters are the same component, if
247                // yes, return false.
248                //if (checkIdentity(assembledComponent, alternativeComponent))
249                //        return null;
250                //TODO: in the case above, we could save the whole calculation. But for now, leave it like this. 
251 
252                // check whether they have compatible interfaces
253                /*
254                 * TODO Assumption: An interface is always used in the same way and
255                 * fully defines whether two components are exchangeable.
256                 */
257 
258                /*
259                 * TODO Assumption: Note that I allow that a component can require the
260                 * same interface multiple times. Two components are only alternatives
261                 * to each other, if they provide the same interfaces equally often. For
262                 * provided interfaces, there just needs to be one matching interface
263                 */
264                ComponentReplacer cr = new ComponentReplacer();
265 
266                // Start with provided interfaces. Alternative component
267                EList<ProvidedRole> altprl = alternativeComponent
268                                .getProvidedRoles_InterfaceProvidingEntity();
269                EList<ProvidedRole> assprl = assembledComponent
270                                .getProvidedRoles_InterfaceProvidingEntity();
271 
272                Map<OperationProvidedRole, OperationProvidedRole> providedMapping = new IdentityHashMap<OperationProvidedRole, OperationProvidedRole>();
273                for (ProvidedRole asspr : assprl) {
274                        if (asspr instanceof OperationProvidedRole){
275                                OperationProvidedRole assembledOperationProvidedRole =  (OperationProvidedRole) asspr;
276                                for (ProvidedRole altpr : altprl) {
277                                        if (altpr instanceof OperationProvidedRole){
278                                                OperationProvidedRole alternativeOperationProvidedRole =  (OperationProvidedRole) altpr;
279                                                //         TODO: Allow derived interfaces at the alternativeComponent
280/*                                                logger.debug("Interface "
281                                                        + altpr.getProvidedInterface__ProvidedRole()
282                                                        + " and Interface "
283                                                        + asspr.getProvidedInterface__ProvidedRole());*/
284                                
285                                                if (EMFHelper.checkIdentity(alternativeOperationProvidedRole.getProvidedInterface__OperationProvidedRole(),
286                                                                assembledOperationProvidedRole.getProvidedInterface__OperationProvidedRole())) {
287                                                        providedMapping.put(assembledOperationProvidedRole, alternativeOperationProvidedRole);
288 
289                                                        break;
290                                                }
291                                        }
292                                }
293                        }
294                }
295 
296                // If not all provided interfaces of the assembled component are
297                // provided by the alternative, return false.
298                if (providedMapping.size() != assprl.size()) {
299/*                        logger.debug("The provided interfaces of "
300                                        + assembledComponent.getEntityName() + " and "
301                                        + alternativeComponent.getEntityName() + " do not match.");
302                        logger.debug("Mapping size: " + providedMapping.size()
303                                        + ", provided role list size: " + altprl.size());*/
304                        return null;
305                } else {
306                        
307                        //find connector that points to this assembly context
308                        List<ConnectorAdjuster> cas = findProvidedConnectors(assemblyContext, s, providedMapping);
309 
310                        //add to list
311                        cr.addAllConnectorAdjuster(cas);
312                }
313                
314                logger.debug("These two have matching provided interfaces:" + assembledComponent.getEntityName()+ " and "+alternativeComponent.getEntityName());
315 
316                // Now look at the required interfaces. alternativeComponent must not
317                // require
318                // more than assembled component requires.
319                // TODO: Allow super interfaces at the alternative component
320                EList<RequiredRole> altrrl = alternativeComponent
321                                .getRequiredRoles_InterfaceRequiringEntity();
322                EList<RequiredRole> assrrl = assembledComponent
323                                .getRequiredRoles_InterfaceRequiringEntity();
324 
325                Map<OperationRequiredRole, OperationRequiredRole> requiredMapping = new IdentityHashMap<OperationRequiredRole, OperationRequiredRole>();
326                // Outer loop is alternative, because it must require no more and must
327                // be completely checked.
328                for (RequiredRole altrr : altrrl) {
329                        if (altrr instanceof OperationRequiredRole){
330                                OperationRequiredRole alternativeOperationRequiredRole = (OperationRequiredRole)altrr;
331                                boolean foundMatch = false;
332                                for (RequiredRole assrr : assrrl) {
333                                        if (assrr instanceof OperationRequiredRole){
334                                                OperationRequiredRole assembledOperationRequiredRole = (OperationRequiredRole)assrr;
335                                                // TODO: Allow derived interfaces at the alternativeComponent
336                                                // TODO: Rather use same ImplementationComponentType?
337                                                if (EMFHelper.checkIdentity(alternativeOperationRequiredRole.getRequiredInterface__OperationRequiredRole(),
338                                                                assembledOperationRequiredRole.getRequiredInterface__OperationRequiredRole())) {
339                                                        requiredMapping.put(assembledOperationRequiredRole, alternativeOperationRequiredRole);
340                                                        foundMatch = true;
341                                                        break;
342                                                }
343                                        }
344                                }
345                                // break loop and return false when noticing that one role
346                                // cannot be fit.
347                                if (!foundMatch){
348                                        return null;
349                                }
350                        }
351                }
352 
353                // If not all required interfaces of the alternative component are
354                // required by the assembled one, return false.
355                //TODO: This should be unreachable... but maybe leave it to be sure.  
356                if (requiredMapping.size() != altrrl.size()) {
357/*                        logger.debug("The required interfaces of "
358                                        + assembledComponent.getEntityName() + " and "
359                                        + alternativeComponent.getEntityName() + " do not match.");
360                        logger.debug("Mapping size: " + requiredMapping.size()
361                                        + ", required role list size: " + altrrl.size());*/
362                        return null;
363                } else {
364                        
365                        //find connector that points to this assembly context
366                        List<ConnectorAdjuster> cas = findRequiredConnectors(assemblyContext, s, requiredMapping);
367 
368                        //add to list
369                        cr.addAllConnectorAdjuster(cas);
370                }
371                logger.debug("These two have matching required interfaces:" + assembledComponent.getEntityName()+ " and "+alternativeComponent.getEntityName());
372 
373                return cr;
374        }
375 
376        /**
377         * Finds out how the Connectors to the {@link AssemblyContext} assemblyContext have to be adjusted on the required side in order
378         * to put another {@link RepositoryComponent} (given by its roles) there. The mapping requiredMapping already 
379         * contains a mapping of the {@link RequiredRole}s of the currently assembledComponent to the {@link RequiredRole}s of the
380         * {@link RepositoryComponent} to be assembled. 
381         * 
382         *  The results for each connector are stored in a {@link ConnectorAdjuster} object, which can fix the connector references if needed. 
383         *  A List of {@link ConnectorAdjuster} is returned with a {@link ConnectorAdjuster} for each connector pointing to or coming from this {@link AssemblyContext}. 
384         * @param assemblyContext
385         * @param assembledComponent
386         * @param s
387         * @param providedMapping
388         * @return a List of {@link ConnectorAdjuster}
389         */
390        private List<ConnectorAdjuster> findRequiredConnectors(
391                        AssemblyContext assemblyContext,
392                        System s, Map<OperationRequiredRole, OperationRequiredRole> requiredMapping) {
393                List<ConnectorAdjuster> result = new ArrayList<ConnectorAdjuster>();
394                
395                for (Connector conn : s.getConnectors__ComposedStructure()) {
396                        if (conn instanceof AssemblyConnector) {
397                                AssemblyConnector assemblyConnector = (AssemblyConnector) conn;
398                                if (EMFHelper.checkIdentity(assemblyConnector.getRequiringAssemblyContext_AssemblyConnector(), assemblyContext)){
399                                        OperationRequiredRole role = requiredMapping.get(assemblyConnector.getRequiredRole_AssemblyConnector());
400                                        result.add(new OutgoingAssemblyConnectorAdjuster(assemblyConnector, role));
401                                }
402                        }
403                }
404                
405                for (Connector conn : s.getConnectors__ComposedStructure()) {
406                        if (conn instanceof RequiredDelegationConnector) {
407                                RequiredDelegationConnector requiredDelegationConnector = (RequiredDelegationConnector) conn;
408                                if (EMFHelper.checkIdentity(requiredDelegationConnector.getInnerRequiredRole_RequiredDelegationConnector(), assemblyContext)){
409                                        OperationRequiredRole role = requiredMapping.get(requiredDelegationConnector.getInnerRequiredRole_RequiredDelegationConnector());
410                                        result.add(new RequiredDelegationConnectorAdjuster(requiredDelegationConnector, role));
411                                }
412                        }
413                }
414                
415                return result;
416        }
417 
418        /**
419         * Finds out how the Connectors to the {@link AssemblyContext} assemblyContext have to be adjusted on the provided side in order
420         * to put another {@link RepositoryComponent} (given by its roles) there. The mapping providedMapping already 
421         * contains a mapping of the {@link ProvidedRole}s of the currently assembledComponent to the {@link ProvidedRole}s of the
422         * {@link RepositoryComponent} to be assembled. 
423         * 
424         *  The results for each connector are stored in a {@link ConnectorAdjuster} object, which can fix the connector references if needed. 
425         *  A List of {@link ConnectorAdjuster} is returned with a {@link ConnectorAdjuster} for each connector pointing to or coming from this {@link AssemblyContext}. 
426         * @param assemblyContext
427         * @param assembledComponent
428         * @param s
429         * @param providedMapping
430         * @return a List of {@link ConnectorAdjuster}
431         */
432        private List<ConnectorAdjuster> findProvidedConnectors(
433                        AssemblyContext assemblyContext, System s, Map<OperationProvidedRole, OperationProvidedRole> providedMapping) {
434                List<ConnectorAdjuster> result = new ArrayList<ConnectorAdjuster>();
435                
436                for (Connector conn : s.getConnectors__ComposedStructure()) {
437                        if (conn instanceof AssemblyConnector) {
438                                AssemblyConnector assemblyConnector = (AssemblyConnector) conn;
439                                if (EMFHelper.checkIdentity(assemblyConnector.getProvidingAssemblyContext_AssemblyConnector(), assemblyContext)){
440                                        OperationProvidedRole role = providedMapping.get(assemblyConnector.getProvidedRole_AssemblyConnector());
441                                        result.add(new IncomingAssemblyConnectorAdjuster(assemblyConnector, role));
442                                }
443                        }
444                }
445                
446                for (Connector conn : s.getConnectors__ComposedStructure()) {
447                        if (conn instanceof ProvidedDelegationConnector) {
448                                ProvidedDelegationConnector providedDelegationConnector = (ProvidedDelegationConnector) conn;
449                                if (EMFHelper.checkIdentity(providedDelegationConnector.getAssemblyContext_ProvidedDelegationConnector(), assemblyContext)){
450                                        OperationProvidedRole role = providedMapping.get(providedDelegationConnector.getInnerProvidedRole_ProvidedDelegationConnector());
451                                        result.add(new ProvidedDelegationConnectorReplacer(providedDelegationConnector, role));
452                                }
453                        }
454                }
455                
456                return result;
457        }
458 
459 
460 
461 
462 
463}

[all classes][de.uka.ipd.sdq.dsexplore.designdecisions.alternativecomponents]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov