source: trunk/autoquest-plugin-uml/src/main/java/de/ugoe/cs/autoquest/plugin/uml/UMLUtils.java @ 1926

Last change on this file since 1926 was 1926, checked in by sherbold, 9 years ago
  • UMLUtils now add real values to test cases based on the observations in the event sequence
  • test updated
  • Property svn:mime-type set to text/plain
File size: 58.5 KB
RevLine 
[1604]1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.plugin.uml;
16
[1926]17import java.io.StringWriter;
18import java.util.ArrayList;
[1604]19import java.util.Collection;
[1763]20import java.util.Collections;
21import java.util.Comparator;
[1604]22import java.util.HashMap;
[1898]23import java.util.HashSet;
[1604]24import java.util.Iterator;
[1763]25import java.util.LinkedHashMap;
[1604]26import java.util.LinkedList;
27import java.util.List;
28import java.util.Map;
29import java.util.Map.Entry;
[1898]30import java.util.logging.Level;
31import java.util.Set;
32import java.util.TreeSet;
[1604]33
[1926]34import javax.xml.transform.Transformer;
35import javax.xml.transform.TransformerException;
36import javax.xml.transform.TransformerFactory;
37import javax.xml.transform.TransformerFactoryConfigurationError;
38import javax.xml.transform.dom.DOMSource;
39import javax.xml.transform.stream.StreamResult;
40
[1604]41import org.eclipse.emf.common.util.EList;
[1926]42import org.eclipse.emf.common.util.URI;
[1763]43import org.eclipse.uml2.uml.Activity;
44import org.eclipse.uml2.uml.ActivityEdge;
45import org.eclipse.uml2.uml.ActivityNode;
[1898]46import org.eclipse.uml2.uml.CallConcurrencyKind;
[1926]47import org.eclipse.uml2.uml.CallEvent;
[1763]48import org.eclipse.uml2.uml.CallOperationAction;
[1604]49import org.eclipse.uml2.uml.Comment;
[1752]50import org.eclipse.uml2.uml.Component;
51import org.eclipse.uml2.uml.Connector;
52import org.eclipse.uml2.uml.ConnectorEnd;
[1908]53import org.eclipse.uml2.uml.DataType;
[1835]54import org.eclipse.uml2.uml.Element;
[1908]55import org.eclipse.uml2.uml.Expression;
56import org.eclipse.uml2.uml.InstanceSpecification;
57import org.eclipse.uml2.uml.InstanceValue;
[1624]58import org.eclipse.uml2.uml.Interaction;
[1643]59import org.eclipse.uml2.uml.InteractionFragment;
[1752]60import org.eclipse.uml2.uml.Interface;
[1624]61import org.eclipse.uml2.uml.Lifeline;
[1908]62import org.eclipse.uml2.uml.LiteralBoolean;
63import org.eclipse.uml2.uml.LiteralInteger;
64import org.eclipse.uml2.uml.LiteralReal;
65import org.eclipse.uml2.uml.LiteralString;
[1624]66import org.eclipse.uml2.uml.Message;
67import org.eclipse.uml2.uml.MessageOccurrenceSpecification;
[1752]68import org.eclipse.uml2.uml.MessageSort;
[1624]69import org.eclipse.uml2.uml.Model;
70import org.eclipse.uml2.uml.Operation;
[1896]71import org.eclipse.uml2.uml.Package;
[1908]72import org.eclipse.uml2.uml.Parameter;
73import org.eclipse.uml2.uml.ParameterDirectionKind;
[1752]74import org.eclipse.uml2.uml.Port;
[1908]75import org.eclipse.uml2.uml.PrimitiveType;
[1759]76import org.eclipse.uml2.uml.Profile;
[1761]77import org.eclipse.uml2.uml.Property;
[1604]78import org.eclipse.uml2.uml.Region;
[1926]79import org.eclipse.uml2.uml.Relationship;
[1908]80import org.eclipse.uml2.uml.Slot;
[1604]81import org.eclipse.uml2.uml.StateMachine;
[1759]82import org.eclipse.uml2.uml.Stereotype;
[1604]83import org.eclipse.uml2.uml.Transition;
[1926]84import org.eclipse.uml2.uml.Trigger;
85import org.eclipse.uml2.uml.Type;
[1624]86import org.eclipse.uml2.uml.UMLPackage;
[1604]87import org.eclipse.uml2.uml.Vertex;
[1926]88import org.w3c.dom.Attr;
89import org.w3c.dom.Node;
90import org.w3c.dom.NodeList;
[1604]91
92import de.ugoe.cs.autoquest.eventcore.Event;
[1926]93import de.ugoe.cs.autoquest.plugin.http.SOAPUtils;
[1604]94import de.ugoe.cs.autoquest.plugin.http.eventcore.SOAPEventType;
[1643]95import de.ugoe.cs.autoquest.plugin.http.eventcore.SimpleSOAPEventType;
[1604]96import de.ugoe.cs.autoquest.plugin.uml.eventcore.UMLTransitionType;
[1763]97import de.ugoe.cs.autoquest.usageprofiles.IStochasticProcess;
[1926]98import de.ugoe.cs.util.StringTools;
[1898]99import de.ugoe.cs.util.console.Console;
[1604]100
101/**
102 * <p>
[1624]103 * Utilities for working with UML.
[1604]104 * </p>
105 *
106 * @author Steffen Herbold
107 */
108public class UMLUtils {
109
[1900]110    /**
[1926]111     * In case a multiplicity is defined as *, this value defines the highest one that can be picked
112     */
113    final static int MAX_MULTIPLICITY = 10;
114
115    final public static URI UML_PRIMITIVE_TYPES_URI = URI
116        .createURI("pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml", true);
117
118    /**
[1900]119     * <p>
120     * Method for checking if the information in a usage journal can be mapped to the SUT model. In
121     * case this is not possible, the violations are reported.
122     * </p>
123     *
124     * @param sequences
125     *            sequences of the usage journal
126     * @param model
127     *            SUT model that is validated
128     * @param testContextName
129     *            name of the test context to be used; if null, the first test context found is used
130     * @return number of violations
131     */
132    public static int validateModelWithLog(Collection<List<Event>> sequences,
133                                           Model model,
134                                           String testContextName)
135    {
[1898]136        final Profile utpProfile = model.getAppliedProfile("utp");
137        final Stereotype utpTestComponent = (Stereotype) utpProfile.getOwnedMember("TestComponent");
138        final Stereotype utpSUT = (Stereotype) utpProfile.getOwnedMember("SUT");
139        final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext");
140
[1900]141        int violationCount = 0;
[1898]142        Component testContext = fetchTestContext(model, utpTestContext, testContextName);
143        if (testContext == null) {
[1900]144            violationCount++;
145            if (testContextName == null) {
[1898]146                Console.traceln(Level.SEVERE, "Could not find any TestContext in the model.");
[1900]147
[1898]148            }
[1900]149            else {
150                Console.traceln(Level.SEVERE, "Could not find TestContext in the model: " +
151                    testContextName);
152            }
153            Console
154                .traceln(Level.SEVERE,
155                         "Hint: Check if you have applied the TestContext stereotype correctly in the model.");
156            Console.traceln(Level.SEVERE, "Aborting");
157            return violationCount;
[1898]158        }
[1900]159
[1898]160        // Create list of unique methods calls
161        HashMap<String, Set<String>> calledMethods = new HashMap<>();
[1900]162        for (List<Event> sequence : sequences) {
163            for (Event event : sequence) {
[1926]164                String serviceName = SOAPUtils.getServiceNameFromEvent(event);
165                String calledMethod = SOAPUtils.getCalledMethodFromEvent(event);
166                if (serviceName != null) {
[1916]167                    Set<String> curCalledMethods = calledMethods.get(serviceName);
[1900]168                    if (curCalledMethods == null) {
[1898]169                        curCalledMethods = new TreeSet<>();
[1916]170                        calledMethods.put(serviceName, curCalledMethods);
[1898]171                    }
[1916]172                    curCalledMethods.add(calledMethod);
[1898]173                }
174            }
175        }
[1900]176
177        Console.traceln(Level.INFO,
178                        "Found the following services and operations in the usage data: ");
179        for (Entry<String, Set<String>> entry : calledMethods.entrySet()) {
[1908]180            Console.traceln(Level.INFO, "\tService \"" + entry.getKey() + "\": ");
[1926]181            for (String method : entry.getValue()) {
182                Console.traceln(Level.INFO, "\t\t" + method);
[1898]183            }
184        }
[1900]185
[1898]186        // fetch all SUTs and TestComponents
187        HashMap<String, Property> properties = new HashMap<>();
188        for (Property property : testContext.getAllAttributes()) {
189            if (property.getAppliedStereotypes().contains(utpSUT)) {
[1900]190                properties.put(property.getName(), property);
[1898]191            }
192            else if (property.getType().getAppliedStereotypes().contains(utpTestComponent)) {
[1900]193                properties.put(property.getName(), property);
[1898]194            }
195        }
196        Console.traceln(Level.INFO, "Found the following services in the TestConfiguration:");
[1900]197        for (Entry<String, Property> entry : properties.entrySet()) {
[1898]198            Console.traceln(Level.INFO, "\t" + entry.getKey());
199        }
[1900]200
201        for (Entry<String, Set<String>> entry : calledMethods.entrySet()) {
[1898]202            String serviceName = entry.getKey();
203            Console.traceln(Level.INFO, "Checking service: " + serviceName);
204            Set<String> methodNames = entry.getValue();
205            Property property = properties.get(serviceName);
[1900]206            if (property == null) {
207                violationCount++;
208                Console.traceln(Level.SEVERE, "\tCould not find property for service: " +
209                    serviceName);
210                Console
211                    .traceln(Level.SEVERE,
212                             "\tHint: Check service name map and/or model if the service is present and spelled correctly.");
213                Console
214                    .traceln(Level.SEVERE,
215                             "\tHint: Check if the SUT/TestComponent stereotype has been applied correctly in this TestContext.");
216            }
217            else {
[1898]218                Set<Interface> interfaces = getRealizedInterfacesFromProperty(property);
[1900]219                if (interfaces.isEmpty()) {
220                    violationCount++;
221                    Console
222                        .traceln(Level.SEVERE,
223                                 "\tCould not find any interfaces implementing the property for service: " +
224                                     serviceName);
225                    Console
226                        .traceln(Level.SEVERE,
227                                 "\tHint: Check if the property correctly realizes the interfaces in the model.");
228                }
229                else {
230                    Console.traceln(Level.INFO,
231                                    "\tFound the following realized interfaces for the service \"" +
232                                        serviceName + "\": ");
[1926]233                    for (Interface intface : interfaces) {
[1908]234                        Console.traceln(Level.INFO, "\t" + intface.getName());
[1926]235                        for (Operation operation : intface.getAllOperations()) {
[1908]236                            Console.traceln(Level.INFO, "\t\t" + operation.getName());
[1898]237                        }
238                    }
[1900]239                    for (String methodName : methodNames) {
240                        boolean methodFound = false;
241                        for (Interface intface : interfaces) {
[1898]242                            if (getOperationFromName(intface.getOperations(), methodName) != null) {
243                                // interface found
[1900]244                                Console.traceln(Level.INFO, "\tMethod " + methodName +
245                                    " found in interface " + intface.getName());
[1898]246                                methodFound = true;
247                            }
248                        }
[1900]249                        if (!methodFound) {
250                            violationCount++;
251                            Console.traceln(Level.SEVERE, "\tCould not find operation: " +
252                                methodName);
[1898]253                        }
254                    }
255                }
256            }
257        }
[1900]258        return violationCount;
[1898]259    }
[1900]260
[1624]261    /**
262     * <p>
263     * Creates a sequence of events with {@link UMLTransitionType} as event type from a given
[1926]264     * sequence of events with the {@link SOAPEventType} or {@link SimpleSOAPEventType}, by matching
265     * the sequences to a state machine.
[1624]266     * </p>
267     *
268     * @param sequence
269     *            SOAP sequences
270     * @param stateMachine
271     *            the state machine
272     * @return create UML sequences
273     */
274    public static List<Event> createUMLTransitionSequence(List<Event> sequence,
275                                                          StateMachine stateMachine)
276    {
[1926]277        System.out.println("foo");
[1624]278        List<List<Transition>> matchingSequences =
279            determineMatchingTransitionSequences(sequence, stateMachine);
[1926]280        System.out.println(matchingSequences.size());
[1604]281
282        if (matchingSequences.size() != 1) {
283            throw new RuntimeException("no unique match found; " + matchingSequences.size() +
284                " matches");
285        }
286        List<Event> umlEventSequence = new LinkedList<>();
287        for (Transition transition : matchingSequences.get(0)) {
288            umlEventSequence.add(new Event(new UMLTransitionType(transition)));
289        }
290        return umlEventSequence;
291    }
[1624]292
293    /**
294     * <p>
295     * Uses a sequences of events with the {@link UMLTransitionType} to determine the transition
296     * probabilities for the state machine.
297     * </p>
298     *
299     * @param sequences
300     *            UML sequences
301     * @param stateMachine
302     *            state machine to be converted to a usage profile
303     */
304    public static void convertStateMachineToUsageProfile(Collection<List<Event>> sequences,
305                                                         StateMachine stateMachine)
306    {
[1604]307        // create state->outgoings hashmap
[1624]308        Map<Vertex, Map<Transition, Integer>> stateMap = new HashMap<>();
309        for (Region region : stateMachine.getRegions()) {
310            for (Vertex state : region.getSubvertices()) {
311                stateMap.put(state, new HashMap<Transition, Integer>());
[1604]312            }
313        }
[1624]314
[1604]315        // create counters for each transition
[1624]316        for (List<Event> sequence : sequences) {
317            for (Event event : sequence) {
318                if (event.getType() instanceof UMLTransitionType) {
[1604]319                    Transition transition = ((UMLTransitionType) event.getType()).getTransition();
[1624]320                    Map<Transition, Integer> transitionMap = stateMap.get(transition.getSource());
[1604]321                    Integer value = transitionMap.get(transition);
[1624]322                    if (value == null) {
[1604]323                        value = 0;
324                    }
[1624]325                    transitionMap.put(transition, value + 1);
[1604]326                }
[1624]327                else {
328                    throw new RuntimeException(
329                                               "Wrong event type. Only UMLTransitionType supported but was: " +
330                                                   event.getType().getClass().getName());
331                }
[1604]332            }
333        }
334
335        // calculate probabilities
[1624]336        for (Region region : stateMachine.getRegions()) {
337            for (Vertex state : region.getSubvertices()) {
338                Map<Transition, Integer> transitionMap = stateMap.get(state);
[1604]339                int totalCount = 0;
[1624]340                for (Entry<Transition, Integer> entry : transitionMap.entrySet()) {
[1604]341                    totalCount += entry.getValue();
342                }
[1624]343                if (totalCount != 0) {
344                    for (Transition transition : state.getOutgoings()) {
[1604]345                        double prob = 0.0d;
[1624]346                        if (transitionMap.containsKey(transition)) {
347                            prob = ((double) transitionMap.get(transition)) / totalCount;
[1604]348                        }
349                        Comment comment = transition.createOwnedComment();
[1624]350                        comment.setBody("" + prob);
[1604]351                    }
[1624]352                }
353                else {
[1604]354                    // system has never been in this state, all transitions equally likely
355                    int numOutgoings = state.getOutgoings().size();
[1624]356                    for (Transition transition : state.getOutgoings()) {
[1604]357                        Comment comment = transition.createOwnedComment();
[1624]358                        comment.setBody("" + (1.0d / numOutgoings));
[1604]359                    }
360                }
361            }
362        }
363    }
[1624]364
365    /**
366     * <p>
367     * Determines all matching {@link Transition} sequences in a state machine for a given sequence
368     * of SOAP events.
369     * </p>
370     *
371     * @param sequence
372     *            SOAP sequence
373     * @param stateMachine
374     *            the state machine
375     * @return all matching {@link Transition} sequences
376     */
377    public static List<List<Transition>> determineMatchingTransitionSequences(List<Event> sequence,
378                                                                              StateMachine stateMachine)
379    {
[1604]380        EList<Region> regions = stateMachine.getRegions();
381        EList<Vertex> states = null;
382        for (Region region : regions) {
383            if (states == null) {
384                states = region.getSubvertices();
385            }
386            else {
387                states.addAll(region.getSubvertices());
388            }
389        }
390        List<Transition> allTransitions = new LinkedList<>();
391        for (Vertex state : states) {
392            allTransitions.addAll(state.getOutgoings());
393        }
394
395        List<List<Transition>> matchingSequences = null;
396        List<Transition> currentTransitions = null;
397
398        // first, we try to find a single unique transition that we can match using the method name
399        for (Iterator<Event> eventIterator = sequence.iterator(); eventIterator.hasNext();) {
400            Event event = eventIterator.next();
[1926]401            System.out.println(event);
402            System.out.println(matchingSequences);
403            if (matchingSequences == null) {
404                matchingSequences = new LinkedList<>();
405                List<Transition> initialMatches = matchTransitions(allTransitions, event);
406                for (Transition transition : initialMatches) {
407                    List<Transition> candidate = new LinkedList<>();
408                    candidate.add(transition);
409                    matchingSequences.add(candidate);
[1604]410                }
[1926]411                currentTransitions = initialMatches;
412            }
413            else {
414                List<List<Transition>> nextMatchingSequences = new LinkedList<>();
415                List<Transition> nextCurrentTransitions = new LinkedList<>();
416                Iterator<Transition> currentTransitionIterator = currentTransitions.iterator();
417                Iterator<List<Transition>> currentMatchingSequencesIterator =
418                    matchingSequences.iterator();
419                while (currentTransitionIterator.hasNext()) {
420                    Transition currentTransition = currentTransitionIterator.next();
421                    List<Transition> currentMatch = currentMatchingSequencesIterator.next();
[1604]422
[1926]423                    List<Transition> matches =
424                        matchTransitions(currentTransition.getTarget().getOutgoings(), event);
425                    if (matches.isEmpty()) {
426                        throw new RuntimeException("no matches found");
[1604]427                    }
[1926]428                    for (Transition matchingTransition : matches) {
429                        List<Transition> candidate = new LinkedList<>(currentMatch);
430                        candidate.add(matchingTransition);
431                        nextMatchingSequences.add(candidate);
432                        nextCurrentTransitions.add(matchingTransition);
433                    }
[1604]434                }
[1926]435                matchingSequences = nextMatchingSequences;
436                currentTransitions = nextCurrentTransitions;
[1604]437            }
438        }
439        return matchingSequences;
440    }
[1624]441
442    /**
443     * <p>
[1633]444     * Extends a given model with an interaction that represents an observed sequence.
[1624]445     * </p>
[1633]446     *
447     * @param sequence
448     *            sequence that is added as sequence diagram
449     * @param model
450     *            UML model to which the interaction is added
451     * @param interactionName
452     *            name of the interaction
[1896]453     * @param testContextName
[1897]454     *            Name of the test context that should be used. If this value is null, the first
455     *            test context found is used.
[1624]456     */
[1633]457    public static void createInteractionFromEventSequence(List<Event> sequence,
458                                                          Model model,
[1896]459                                                          String interactionName,
460                                                          String testContextName)
[1604]461    {
[1759]462        final Profile utpProfile = model.getAppliedProfile("utp");
463        final Stereotype utpTestCase = (Stereotype) utpProfile.getOwnedMember("TestCase");
[1763]464        final Stereotype utpTestComponent = (Stereotype) utpProfile.getOwnedMember("TestComponent");
465        final Stereotype utpSUT = (Stereotype) utpProfile.getOwnedMember("SUT");
[1896]466        final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext");
467
[1926]468        // add UML Primitive types
469        // final UMLResource umlRes = (UMLResource)
470        // model.eResource().getResourceSet().getResource(UML_PRIMITIVE_TYPES_URI, true);
471        // model = (Model) umlRes.getContents().get(0);
472
[1896]473        Component testContext = fetchTestContext(model, utpTestContext, testContextName);
[1897]474        if (testContext == null) {
[1896]475            throw new RuntimeException("Could not find any test context in the model");
476        }
[1897]477
[1759]478        Operation operation = testContext.createOwnedOperation(interactionName, null, null);
479        operation.applyStereotype(utpTestCase);
480
[1624]481        Interaction interaction =
[1759]482            (Interaction) testContext.createPackagedElement(interactionName + "_Impl",
483                                                            UMLPackage.Literals.INTERACTION);
[1761]484        operation.getMethods().add(interaction);
[1835]485
[1763]486        // create lifelines
487        Lifeline userLifeline = null;
[1900]488
[1763]489        for (Property property : testContext.getAllAttributes()) {
490            if (property.getAppliedStereotypes().contains(utpSUT)) {
[1835]491                String serviceName = property.getName();
[1763]492                Lifeline targetLifeline = interaction.createLifeline(serviceName);
493                targetLifeline.setRepresents(property);
[1761]494            }
[1763]495            else if (property.getType().getAppliedStereotypes().contains(utpTestComponent)) {
[1900]496                if (userLifeline != null) {
497                    throw new RuntimeException(
498                                               "TestContext must only have one TestComponent for the application of usage-based testing.");
[1897]499                }
[1763]500                userLifeline = interaction.createLifeline(property.getName());
501                userLifeline.setRepresents(property);
[1897]502            }
[1761]503        }
[1900]504        if (userLifeline == null) {
[1897]505            throw new RuntimeException("No TestComponent found, could not create user lifeline.");
506        }
[1900]507        if (interaction.getLifelines().size() < 2) {
[1897]508            throw new RuntimeException("Fewer than two lifelines created. No SUT found.");
509        }
[1900]510
[1624]511        int i = 0;
512        for (Event event : sequence) {
[1633]513            if (!(event.equals(Event.STARTEVENT) || event.equals(Event.ENDEVENT))) {
[1926]514                String serviceName = SOAPUtils.getServiceNameFromEvent(event);
515                String methodName = SOAPUtils.getCalledMethodFromEvent(event);
516                String clientName = SOAPUtils.getClientNameFromEvent(event);
517                String prefix = interactionName + ":" + i + ":" + methodName + "_";
[1835]518                // determine lifelines
519                Lifeline msgTargetLifeline;
520                Lifeline msgSourceLifeline;
[1926]521
[1913]522                msgSourceLifeline = interaction.getLifeline(clientName);
523                msgTargetLifeline = interaction.getLifeline(serviceName);
[1926]524
[1900]525                if (msgSourceLifeline == null) {
526                    throw new RuntimeException(
[1926]527                                               "Error creating message: could not determine source lifeline for component: " +
528                                                   clientName);
[1752]529                }
[1900]530                if (msgTargetLifeline == null) {
531                    throw new RuntimeException(
[1926]532                                               "Error creating message: could not determine target lifeline for component: " +
533                                                   serviceName);
[1897]534                }
535                // determine correct target interface
[1898]536                Set<Interface> targetInterfaces =
[1897]537                    getRealizedInterfacesFromProperty((Property) msgTargetLifeline.getRepresents());
538                if (targetInterfaces.isEmpty()) {
539                    throw new RuntimeException("no interface associated with the property " +
540                        msgTargetLifeline.getRepresents().getName());
541                }
[1896]542                Interface targetInterface = null;
[1897]543                for (Interface intface : targetInterfaces) {
[1896]544                    if (getOperationFromName(intface.getOperations(), methodName) != null) {
545                        // interface found
546                        targetInterface = intface;
547                        break;
548                    }
549                }
[1897]550                if (targetInterface == null) {
[1896]551                    StringBuilder errStrBuilder = new StringBuilder();
[1900]552                    errStrBuilder
553                        .append("Error creating message: operation not found in the implementing interfaces (");
[1896]554                    Iterator<Interface> iter = targetInterfaces.iterator();
[1897]555                    while (iter.hasNext()) {
[1896]556                        String interfaceName = iter.next().getName();
557                        errStrBuilder.append(interfaceName);
[1897]558                        if (iter.hasNext()) {
[1896]559                            errStrBuilder.append(",");
[1897]560                        }
561                        else {
[1896]562                            errStrBuilder.append("): " + methodName);
563                        }
564                    }
565                    throw new RuntimeException(errStrBuilder.toString());
566                }
[1897]567
568                Operation calledOperation =
569                    getOperationFromName(targetInterface.getOperations(), methodName);
570
571                // setup for both SYNCH and ASYNCH calls
572                MessageOccurrenceSpecification callSendFragment =
[1926]573                    (MessageOccurrenceSpecification) interaction.createFragment(prefix +
574                        "callSendFragment", UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
[1897]575                MessageOccurrenceSpecification callRecvFragment =
[1926]576                    (MessageOccurrenceSpecification) interaction.createFragment(prefix +
577                        "callRecvFragment", UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
[1897]578
579                callSendFragment.setCovered(msgSourceLifeline);
580                callRecvFragment.setCovered(msgTargetLifeline);
581
582                // create call
583                Message callMessage = interaction.createMessage(methodName);
[1926]584                callMessage.setSignature(calledOperation);
585                setMessageParameters(callMessage, calledOperation, event, prefix);
[1897]586                callMessage.setConnector(inferConnector(msgSourceLifeline, msgTargetLifeline));
587                callMessage.setSendEvent(callSendFragment);
588                callMessage.setReceiveEvent(callRecvFragment);
589                callSendFragment.setMessage(callMessage);
590                callRecvFragment.setMessage(callMessage);
591
[1896]592                boolean asynch = false;
[1900]593                if (calledOperation.getConcurrency() == CallConcurrencyKind.CONCURRENT_LITERAL) {
[1898]594                    asynch = true;
595                }
[1897]596                if (asynch) {
597                    // Create ASYNCH call
598                    callMessage.setMessageSort(MessageSort.ASYNCH_CALL_LITERAL);
599                }
600                else {
[1896]601                    // SYNCH call
[1897]602                    callMessage.setMessageSort(MessageSort.SYNCH_CALL_LITERAL);
603
604                    // setup reply and behavior execution specifications
[1896]605                    MessageOccurrenceSpecification replySendFragment =
606                        (MessageOccurrenceSpecification) interaction
[1926]607                            .createFragment(prefix + "replySendFragment",
[1896]608                                            UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
609                    MessageOccurrenceSpecification replyRecvFragment =
610                        (MessageOccurrenceSpecification) interaction
[1926]611                            .createFragment(prefix + "replyRecvFragment",
[1896]612                                            UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
[1897]613
614                    replySendFragment.setCovered(msgTargetLifeline);
615                    replyRecvFragment.setCovered(msgSourceLifeline);
616
[1900]617                    /*
618                     * BehaviorExecutionSpecification sourceBehaviorExecutionSpecification =
619                     * (BehaviorExecutionSpecification) interaction .createFragment(":" + methodName
620                     * + "_sourceBhvExecSpec",
621                     * UMLPackage.Literals.BEHAVIOR_EXECUTION_SPECIFICATION);
622                     * BehaviorExecutionSpecification targetBehaviorExecutionSpecification =
623                     * (BehaviorExecutionSpecification) interaction .createFragment(":" + methodName
624                     * + "_targetBhvExecSpec",
625                     * UMLPackage.Literals.BEHAVIOR_EXECUTION_SPECIFICATION);
626                     *
627                     * sourceBehaviorExecutionSpecification.setStart(callSendFragment);
628                     * sourceBehaviorExecutionSpecification.setFinish(replyRecvFragment);
629                     * targetBehaviorExecutionSpecification.setStart(callRecvFragment);
630                     * targetBehaviorExecutionSpecification.setFinish(replySendFragment);
631                     */
[1897]632
[1896]633                    // create reply
634                    Message replyMessage = interaction.createMessage(methodName + "_reply");
635                    replyMessage.setMessageSort(MessageSort.REPLY_LITERAL);
636                    replyMessage.setSignature(calledOperation);
637                    replyMessage.setSendEvent(replySendFragment);
638                    replyMessage.setReceiveEvent(replyRecvFragment);
639                    replySendFragment.setMessage(replyMessage);
640                    replyRecvFragment.setMessage(replyMessage);
[1753]641                }
[1643]642
[1633]643                i++;
[1624]644            }
645        }
646    }
647
648    /**
649     * <p>
[1643]650     * Calculates the usage score of an interaction as the logsum of the event probabilities
651     * multiplied with the length of the interaction.
652     * </p>
653     *
654     * @param interaction
655     *            interaction for which the score is calculated
656     * @param usageProfile
657     *            usage profile used for the calculation
658     * @return calculated usage score
659     */
[1763]660    public static double calculateUsageScore(Interaction interaction,
661                                             IStochasticProcess usageProfile)
662    {
[1643]663        double usageScore = 0.0d;
664
665        EList<InteractionFragment> interactionFragments = interaction.getFragments();
666        List<Event> eventSequence = new LinkedList<>();
667        eventSequence.add(Event.STARTEVENT);
668        for (InteractionFragment interactionFragment : interactionFragments) {
669            if (interactionFragment.getName() != null &&
[1897]670                interactionFragment.getName().endsWith("_recvFragment")) // TODO must be more
671                                                                         // generic
[1643]672            {
673                String serviceName =
[1763]674                    interactionFragment.getCovereds().get(0).getRepresents().getName().split("_")[0];
[1643]675                String methodName = "UNKNOWN";
676                if (interactionFragment instanceof MessageOccurrenceSpecification) {
677                    methodName =
678                        ((MessageOccurrenceSpecification) interactionFragment).getMessage()
679                            .getName();
680                }
[1926]681                // eventSequence.add(new Event(new SimpleSOAPEventType(methodName, serviceName, "",
682                // ))); // TODO
683                // add
684                // client
685                // name
[1643]686            }
687        }
[1763]688        eventSequence.add(Event.ENDEVENT);
[1643]689        double prob = usageProfile.getLogSum(eventSequence);
[1763]690        usageScore = eventSequence.size() * prob;
[1643]691
692        return usageScore;
693    }
694
695    /**
696     * <p>
[1763]697     * Extends the given model with an activity for usage-based scheduling of the test cases.
698     * </p>
699     *
700     * @param model
701     *            model to be extended
702     * @param usageProfile
[1897]703     *            usage profile used as foundation
[1763]704     */
[1897]705    public static void createScheduling(Model model,
706                                        IStochasticProcess usageProfile,
707                                        String testContextName)
708    {
[1763]709
710        final Profile utpProfile = model.getAppliedProfile("utp");
711        final Stereotype utpTestCase = (Stereotype) utpProfile.getOwnedMember("TestCase");
[1896]712        final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext");
[1763]713
[1896]714        Component testContext = fetchTestContext(model, utpTestContext, testContextName);
[1897]715        if (testContext == null) {
[1896]716            throw new RuntimeException("Could not find any test context in the model");
717        }
[1763]718
719        Map<Operation, Double> usageScoreMapUnsorted = new HashMap<>();
720
721        // first, we determine all test cases and calculate their usage scores
722        for (Operation operation : testContext.getAllOperations()) {
723            if (operation.getAppliedStereotypes().contains(utpTestCase)) {
724                Interaction interaction = (Interaction) operation.getMethods().get(0);
725                usageScoreMapUnsorted
726                    .put(operation, calculateUsageScore(interaction, usageProfile));
727            }
728        }
729        Map<Operation, Double> usageScoreMapSorted = sortByValue(usageScoreMapUnsorted);
730
731        // now we create the scheduling
732        Activity schedulingActivity =
733            (Activity) testContext.createOwnedBehavior("UsageBasedScheduling",
734                                                       UMLPackage.Literals.ACTIVITY);
735        testContext.setClassifierBehavior(schedulingActivity);
736
737        ActivityNode startNode =
738            schedulingActivity.createOwnedNode("final", UMLPackage.Literals.INITIAL_NODE);
739        ActivityNode finalNode =
740            schedulingActivity.createOwnedNode("final", UMLPackage.Literals.ACTIVITY_FINAL_NODE);
741
742        ActivityNode currentOperationNode = startNode;
743
744        for (Entry<Operation, Double> entry : usageScoreMapSorted.entrySet()) {
745            Operation operation = entry.getKey();
746            CallOperationAction nextOperationNode =
747                (CallOperationAction) schedulingActivity
748                    .createOwnedNode(operation.getName(), UMLPackage.Literals.CALL_OPERATION_ACTION);
749            nextOperationNode.setOperation(operation);
750
751            ActivityEdge edge =
752                schedulingActivity.createEdge(currentOperationNode.getName() + "_to_" +
753                    nextOperationNode.getName(), UMLPackage.Literals.CONTROL_FLOW);
754            edge.setSource(currentOperationNode);
755            edge.setTarget(nextOperationNode);
756
757            currentOperationNode = nextOperationNode;
758        }
759
760        ActivityEdge edge =
761            schedulingActivity
762                .createEdge(currentOperationNode.getName() + "_to_" + finalNode.getName(),
763                            UMLPackage.Literals.CONTROL_FLOW);
764        edge.setSource(currentOperationNode);
765        edge.setTarget(finalNode);
766    }
767
768    /**
769     * From
770     * http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java
771     * and adapted to do an inverse sorting
772     */
773    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
774        List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
775        Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
776            @Override
777            public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
778                return -1 * (o1.getValue()).compareTo(o2.getValue());
779            }
780        });
781
782        Map<K, V> result = new LinkedHashMap<>();
783        for (Map.Entry<K, V> entry : list) {
784            result.put(entry.getKey(), entry.getValue());
785        }
786        return result;
787    }
788
789    /**
790     * <p>
[1624]791     * Fetches an operation using only its name from a list of operations. Returns the first match
792     * found or null if no match is found.
793     * </p>
794     *
795     * @param operations
796     *            list of operations
797     * @param name
798     *            name of the operation
799     * @return first matching operation; null if no match is found
800     */
801    private static Operation getOperationFromName(EList<Operation> operations, String name) {
802        if (name == null) {
803            throw new IllegalArgumentException("name of the operation must not be null");
804        }
805        if (operations != null) {
806            for (Operation operation : operations) {
807                if (operation.getName() != null && operation.getName().equals(name)) {
808                    return operation;
809                }
810            }
811        }
812        return null;
813    }
814
815    /**
816     * <p>
817     * Determines which transitions match a given {@link SOAPEventType}.
818     * </p>
819     *
820     * @param transitions
821     *            the transitions
822     * @param eventType
823     *            the SOAP event
824     * @return matching transitions
825     */
[1926]826    private static List<Transition> matchTransitions(List<Transition> transitions, Event event) {
827        String eventService = SOAPUtils.getServiceNameFromEvent(event);
828        String eventMethod = SOAPUtils.getCalledMethodFromEvent(event);
829
830        Map<Interface, String> interfaceServiceMap =
831            createInterfaceServiceMap(transitions.get(0).getModel());
832
[1604]833        List<Transition> matching = new LinkedList<>();
834        for (Transition transition : transitions) {
[1926]835            EList<Trigger> triggers = transition.getTriggers();
836            if (triggers.size() == 1) {
837                if (triggers.get(0).getEvent() instanceof CallEvent) {
838                    CallEvent callEvent = (CallEvent) triggers.get(0).getEvent();
839                    String transitionMethod = callEvent.getOperation().getName();
840
841                    Interface intface = callEvent.getOperation().getInterface();
842                    for (Relationship relationship : intface.getRelationships()) {
843                        for (Element element : relationship.getRelatedElements()) {
844                            if (element instanceof Component) {
845
846                            }
847                        }
848                    }
849
850                    String transitionService =
851                        interfaceServiceMap.get(callEvent.getOperation().getInterface());
852                    if (eventMethod.equals(transitionMethod) &&
853                        eventService.equals(transitionService))
854                    {
855                        matching.add(transition);
856                    }
857                }
[1604]858            }
[1926]859
[1604]860        }
861        return matching;
862    }
[1897]863
[1898]864    private static Set<Interface> getRealizedInterfacesFromProperty(Property property) {
[1763]865        return getRealizedInterfaceFromComponent((Component) property.getType());
866    }
[1897]867
[1898]868    private static Set<Interface> getRealizedInterfaceFromComponent(Component comp) {
869        Set<Interface> interfaces = new HashSet<>();
[1897]870        // Interface myInterface = null;
871        for (Property property : comp.getAttributes()) {
872            if (property instanceof Port) {
[1835]873                Port port = (Port) property;
[1897]874                if (!port.isConjugated()) {
[1900]875                    interfaces.addAll(port.getProvideds());
[1835]876                }
877            }
878        }
[1896]879        return interfaces;
[1763]880    }
[1897]881
882    private static Component fetchTestContext(Package pkg,
883                                              Stereotype utpTestContext,
884                                              String testContextName)
885    {
[1896]886        List<Component> testContexts = fetchTestContextRecursively(pkg, utpTestContext);
[1897]887        if (testContexts.isEmpty()) {
[1896]888            return null;
889        }
[1897]890        if (testContextName != null) {
891            for (Component testContext : testContexts) {
892                if (testContextName.equals(testContext.getName())) {
[1896]893                    return testContext;
894                }
[1835]895            }
[1896]896            return null;
[1897]897        }
898        else {
[1896]899            return testContexts.get(0);
[1835]900        }
901    }
[1897]902
903    private static List<Component> fetchTestContextRecursively(Package pkg,
904                                                               Stereotype utpTestContext)
905    {
[1896]906        List<Component> testContexts = new LinkedList<>();
[1897]907        for (Element element : pkg.getOwnedElements()) {
908            if (element instanceof Package) {
[1896]909                testContexts.addAll(fetchTestContextRecursively((Package) element, utpTestContext));
910            }
[1897]911            if (element instanceof Component &&
912                element.getAppliedStereotypes().contains(utpTestContext))
913            {
[1896]914                testContexts.add((Component) element);
915            }
916        }
917        return testContexts;
918    }
[1897]919
920    /**
921     * <p>
[1900]922     * Infers connector between two lifelines. TODO: currently assumes only one connector between
923     * two lifelines possible. I need to make sure this assumption is valid.
[1897]924     * </p>
925     *
926     * @param userAttributes
927     * @param targetAttributes
928     */
929    private static Connector inferConnector(Lifeline msgSourceLifeline, Lifeline msgTargetLifeline)
930    {
931        EList<Property> userAttributes =
932            ((Component) msgSourceLifeline.getRepresents().getType()).getAttributes();
933        EList<Property> targetAttributes =
934            ((Component) msgTargetLifeline.getRepresents().getType()).getAttributes();
935        for (Property userAttribute : userAttributes) {
936            if (userAttribute instanceof Port) {
937                EList<ConnectorEnd> userEnds = ((Port) userAttribute).getEnds();
938                for (ConnectorEnd userEnd : userEnds) {
939                    Connector userConnector = (Connector) userEnd.eContainer();
940                    for (Property targetAttribute : targetAttributes) {
941                        if (targetAttribute instanceof Port) {
942                            EList<ConnectorEnd> targetEnds = ((Port) targetAttribute).getEnds();
943                            for (ConnectorEnd targetEnd : targetEnds) {
944                                Connector targetConnector = (Connector) targetEnd.eContainer();
945                                if (targetConnector == userConnector) {
946                                    return targetConnector;
947                                }
948                            }
949                        }
950                    }
951                }
952            }
953        }
954        return null;
955    }
[1926]956
957    private static Map<Interface, String> createInterfaceServiceMap(Model model) {
958        Map<Interface, String> interfaceServiceMap = new HashMap<>();
959        final Profile utpProfile = model.getModel().getAppliedProfile("utp");
960        final Stereotype utpTestComponent = (Stereotype) utpProfile.getOwnedMember("TestComponent");
961        final Stereotype utpSUT = (Stereotype) utpProfile.getOwnedMember("SUT");
962        final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext");
963        List<Component> testContexts =
964            fetchTestContextRecursively(model.getModel(), utpTestContext);
965        for (Component testContext : testContexts) {
966            for (Property property : testContext.getAllAttributes()) {
967                if (property.getAppliedStereotypes().contains(utpSUT) ||
968                    property.getType().getAppliedStereotypes().contains(utpTestComponent))
969                {
970                    for (Interface intface : getRealizedInterfacesFromProperty(property)) {
971                        interfaceServiceMap.put(intface, property.getName());
972                    }
973                }
974            }
975        }
976        return interfaceServiceMap;
977    }
978
979    private static void setMessageParameters(Message callMessage,
980                                             Operation calledOperation,
981                                             Event event,
982                                             String prefix)
983    {
984        org.w3c.dom.Element requestBody = SOAPUtils.getSoapRequestBodyFromEvent(event);
985
[1908]986        // Set parameters of operation
[1926]987        for (Parameter param : calledOperation.getOwnedParameters()) {
988            Expression argument =
989                (Expression) callMessage.createArgument(param.getName(), param.getType(),
990                                                        UMLPackage.Literals.EXPRESSION);
991
992            if (param.getDirection() == ParameterDirectionKind.IN_LITERAL ||
993                param.getDirection() == ParameterDirectionKind.INOUT_LITERAL)
994            {
995                if (param.getType() instanceof DataType) {
996                    List<org.w3c.dom.Element> paramNodes =
997                        getMatchingChildNode((DataType) param.getType(), requestBody);
998                    for (org.w3c.dom.Element paramNode : paramNodes) {
999                        InstanceSpecification instSpec =
1000                            createInstanceSpecification((DataType) param.getType(), event, prefix,
1001                                                        paramNode, "");
1002
1003                        InstanceValue value =
1004                            (InstanceValue) argument
1005                                .createOperand(null, param.getType(),
1006                                               UMLPackage.Literals.INSTANCE_VALUE);
1007                        value.setInstance(instSpec);
[1908]1008                    }
1009                }
[1926]1010                else if (param.getType() instanceof PrimitiveType) {
1011                    createOperandPrimitiveType(param, argument, requestBody);
1012                }
1013            }
1014            else {
[1908]1015                // set literalNull for out and return parameters
1016                argument.createOperand(null, param.getType(), UMLPackage.Literals.LITERAL_NULL);
1017            }
1018        }
1019    }
[1926]1020
1021    private static InstanceSpecification createInstanceSpecification(DataType type,
1022                                                                     Event event,
1023                                                                     String prefix,
1024                                                                     org.w3c.dom.Element currentNode,
1025                                                                     String path)
1026    {
1027        if ("".equals(path)) {
1028            path = type.getName();
1029        }
1030        // System.out.println(path);
[1908]1031        String pkgUBTInstSpecs = "UBT_InstanceSpecifications";
1032        Model model = type.getModel();
1033        Package ubtInstSpecPkg = (Package) model.getOwnedMember(pkgUBTInstSpecs);
[1926]1034        if (ubtInstSpecPkg == null) {
1035            ubtInstSpecPkg =
1036                (Package) type.getModel().createPackagedElement(pkgUBTInstSpecs,
1037                                                                UMLPackage.Literals.PACKAGE);
[1908]1038        }
[1926]1039        String serviceName = SOAPUtils.getServiceNameFromEvent(event);
[1908]1040        Package serviceInstSpecPkg = (Package) ubtInstSpecPkg.getOwnedMember(serviceName);
[1926]1041        if (serviceInstSpecPkg == null) {
1042            serviceInstSpecPkg =
1043                (Package) ubtInstSpecPkg.createPackagedElement(serviceName,
1044                                                               UMLPackage.Literals.PACKAGE);
[1908]1045        }
[1926]1046
1047        InstanceSpecification instSpec =
1048            (InstanceSpecification) serviceInstSpecPkg.createPackagedElement(prefix + "instspec_" +
1049                type.getName(), UMLPackage.Literals.INSTANCE_SPECIFICATION);
[1908]1050        instSpec.getClassifiers().add(type);
[1926]1051        for (Property prop : type.getAllAttributes()) {
1052            if (prop.getType() instanceof PrimitiveType) {
1053                createSlotPrimitiveType(instSpec, prop, currentNode, path);
1054            }
1055            else if (prop.getType() instanceof DataType) {
1056                List<org.w3c.dom.Element> attributeNodes = null;
1057                int multiplicityChosen = 0;
1058                if (currentNode != null) {
1059                    attributeNodes = getMatchingChildNode(prop, currentNode);
1060                    multiplicityChosen = attributeNodes.size();
1061                }
1062
1063                if (multiplicityChosen == 0 && prop.getLower() > 0) {
1064                    if (currentNode != null) {
1065                        Console.traceln(Level.WARNING,
1066                                        "required attribute not found in SOAP message: " + path +
1067                                            "." + prop.getName());
1068                        Console
1069                            .traceln(Level.WARNING,
1070                                     "setting default values for this attribute and all its children");
1071                        Console.traceln(Level.FINE, "XML structure of path:" + StringTools.ENDLINE +
1072                            SOAPUtils.getSerialization(currentNode));
1073                    }
1074                    multiplicityChosen = prop.getLower();
1075                }
1076                for (int i = 0; i < multiplicityChosen; i++) {
1077                    org.w3c.dom.Element attributeNode = null;
1078                    if (attributeNodes != null && !attributeNodes.isEmpty()) {
1079                        attributeNode = attributeNodes.get(i);
1080                    }
1081
1082                    Slot slot = instSpec.createSlot();
1083                    slot.setDefiningFeature(prop);
1084
1085                    InstanceValue value =
1086                        (InstanceValue) slot.createValue(prop.getName() + "_" + i, prop.getType(),
1087                                                         UMLPackage.Literals.INSTANCE_VALUE);
1088                    value.setInstance(createInstanceSpecification((DataType) prop.getType(), event,
1089                                                                  prefix, attributeNode, path +
1090                                                                      "." + prop.getName()));
1091                }
1092            }
1093            else {
1094                Console.traceln(Level.SEVERE, "property neither DataType nor PrimitiveType: " +
1095                    prop.getType());
1096                // TODO abort?
1097            }
1098        }
1099        return instSpec;
1100    }
1101
1102    private static void createOperandPrimitiveType(Parameter param,
1103                                                   Expression argument,
1104                                                   org.w3c.dom.Element currentNode)
1105    {
1106        if ("String".equals(param.getType().getName())) {
1107            LiteralString spec =
1108                (LiteralString) argument.createOperand(param.getName(), null,
1109                                                       UMLPackage.Literals.LITERAL_STRING);
1110            spec.setValue("foobar"); // TODO needs to be real value
1111        }
1112        else if ("Integer".equals(param.getType().getName())) {
1113            LiteralInteger spec =
1114                (LiteralInteger) argument.createOperand(param.getName(), null,
1115                                                        UMLPackage.Literals.LITERAL_INTEGER);
1116            spec.setValue(42); // TODO needs to be real value
1117        }
1118        else if ("Boolean".equals(param.getType().getName())) {
1119            LiteralBoolean spec =
1120                (LiteralBoolean) argument.createOperand(param.getName(), null,
1121                                                        UMLPackage.Literals.LITERAL_BOOLEAN);
1122            spec.setValue(true); // TODO needs to be real value
1123        }
1124        else if ("Real".equals(param.getType().getName())) {
1125            LiteralReal spec =
1126                (LiteralReal) argument.createOperand(param.getName(), null,
1127                                                     UMLPackage.Literals.LITERAL_REAL);
1128            spec.setValue(3.14); // TODO needs to be real value
1129        }
1130    }
1131
1132    private static void createSlotPrimitiveType(InstanceSpecification instSpec,
1133                                                Property prop,
1134                                                org.w3c.dom.Element currentNode,
1135                                                String path)
1136    {
1137        List<String> attributeValues = getPrimitiveTypeValuesFromElement(prop, currentNode);
1138
1139        if (attributeValues.isEmpty()) {
1140            if (prop.getLower() == 0) {
1141                // ignoring optional attribute
1142                return;
1143            }
1144            else {
1145                if (currentNode != null) {
1146                    Console.traceln(Level.WARNING,
1147                                    "required attribute not found in SOAP message: " + path + "." +
1148                                        prop.getName());
1149                    Console.traceln(Level.WARNING, "setting default values for this attribute");
1150                }
1151                Console.traceln(Level.FINE, "XML structure of path:" + StringTools.ENDLINE +
1152                    SOAPUtils.getSerialization(currentNode));
1153                attributeValues.add(null);
1154            }
1155        }
1156        for (String attributeValue : attributeValues) {
[1908]1157            Slot slot = instSpec.createSlot();
1158            slot.setDefiningFeature(prop);
[1926]1159            if ("String".equals(prop.getType().getName())) {
1160                LiteralString value =
1161                    (LiteralString) slot.createValue(prop.getName(), null,
1162                                                     UMLPackage.Literals.LITERAL_STRING);
1163                if (attributeValue != null) {
1164                    value.setValue(attributeValue);
[1908]1165                }
[1926]1166                else {
1167                    value.setValue("foobar");
[1908]1168                }
[1926]1169            }
1170            else if ("Integer".equals(prop.getType().getName())) {
1171                LiteralInteger value =
1172                    (LiteralInteger) slot.createValue(prop.getName(), null,
1173                                                      UMLPackage.Literals.LITERAL_INTEGER);
1174                if (attributeValue != null) {
1175                    value.setValue(Integer.parseInt(attributeValue));
[1908]1176                }
[1926]1177                else {
1178                    value.setValue(42);
1179                }
1180            }
1181            else if ("Boolean".equals(prop.getType().getName())) {
1182                LiteralBoolean value =
1183                    (LiteralBoolean) slot.createValue(prop.getName(), null,
1184                                                      UMLPackage.Literals.LITERAL_BOOLEAN);
1185                if (attributeValue != null) {
1186                    value.setValue(Boolean.parseBoolean(attributeValue));
1187                }
1188                else {
1189                    value.setValue(true);
1190                }
1191            }
1192            else if ("Real".equals(prop.getType().getName())) {
1193                LiteralReal value =
1194                    (LiteralReal) slot.createValue(prop.getName(), null,
1195                                                   UMLPackage.Literals.LITERAL_REAL);
1196                if (attributeValue != null) {
1197                    value.setValue(Double.parseDouble(attributeValue));
1198                }
1199                else {
[1908]1200                    value.setValue(3.14); // TODO needs to be real value
1201                }
1202            }
[1926]1203            else {
1204                Console.traceln(Level.SEVERE, "could not create literal for primitive type: " +
1205                    prop.getType().getName());
1206                // TODO abort?
[1908]1207            }
1208        }
1209    }
[1926]1210
1211    // TODO comment
1212    private static List<org.w3c.dom.Element> getMatchingChildNode(Type type,
1213                                                                  org.w3c.dom.Element parentNode)
1214    {
1215        return getMachingChildNode(type.getName(), parentNode);
1216    }
1217
1218    // TODO comment
1219    private static List<org.w3c.dom.Element> getMatchingChildNode(Property prop,
1220                                                                  org.w3c.dom.Element parentNode)
1221    {
1222        return getMachingChildNode(prop.getName(), parentNode);
1223    }
1224
1225    // TODO comment
1226    private static List<org.w3c.dom.Element> getMachingChildNode(String typeNameRaw,
1227                                                                 org.w3c.dom.Element parentNode)
1228    {
1229        List<org.w3c.dom.Element> matchingNodes = new ArrayList<>();
1230        Node parameterNode = null;
1231        if (parentNode != null) {
1232            NodeList parameterNodes = parentNode.getChildNodes();
1233            String[] typeNameSplit = typeNameRaw.split(":");
1234            String typeName = typeNameSplit[typeNameSplit.length - 1];
1235            for (int i = 0; i < parameterNodes.getLength(); i++) {
1236                parameterNode = parameterNodes.item(i);
1237                if (parameterNode.getNodeType() == Node.ELEMENT_NODE) {
1238                    String[] parameterNodeSplit = parameterNode.getNodeName().split(":");
1239                    String parameterNodeName = parameterNodeSplit[parameterNodeSplit.length - 1];
1240                    if (typeName.equals(parameterNodeName)) {
1241                        matchingNodes.add((org.w3c.dom.Element) parameterNode);
1242                    }
1243                }
1244            }
1245            /*
1246             * if( !matchingSOAPFound) { Console.traceln(Level.WARNING,
1247             * "could not look up name of parameter in SOAP request: " + typeName); if(
1248             * elementCount==0 ) { Console.traceln(Level.INFO, "\tno parameters found"); } else {
1249             * Console.traceln(Level.INFO, "\tparameters found:"); for( int i=0 ;
1250             * i<parameterNodes.getLength(); i++ ) { if(
1251             * parameterNodes.item(i).getNodeType()==Node.ELEMENT_NODE ) {
1252             * Console.traceln(Level.INFO, "\t\t" + parameterNodes.item(i).getNodeName()); } } }
1253             * Console.traceln(Level.WARNING,
1254             * "using dummy values for this parameter (and nested values) instead"); }
1255             */
1256        }
1257        return matchingNodes;
1258    }
1259
1260    // TODO
1261    private static List<String> getPrimitiveTypeValuesFromElement(Property prop,
1262                                                                  org.w3c.dom.Element currentNode)
1263    {
1264        List<String> attributeValues = new LinkedList<>();
1265
1266        if (currentNode != null) {
1267            // first check attributes of the node
1268            Attr attribute = currentNode.getAttributeNode(prop.getName());
1269            if (attribute != null) {
1270                attributeValues.add(attribute.getValue());
1271            }
1272            else {
1273                // now check elements
1274                List<org.w3c.dom.Element> elements = getMatchingChildNode(prop, currentNode);
1275                for (org.w3c.dom.Element element : elements) {
1276                    attributeValues.add(element.getTextContent());
1277                }
1278            }
1279        }
1280
1281        return attributeValues;
1282    }
1283
[1604]1284}
Note: See TracBrowser for help on using the repository browser.