Ignore:
Timestamp:
03/20/15 16:00:10 (9 years ago)
Author:
sherbold
Message:
  • refactored and commented UMLUtils
  • created UTPUtils
  • moved DOM related methods from UMLUtils to SOAPUtils
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-plugin-uml/src/main/java/de/ugoe/cs/autoquest/plugin/uml/UMLUtils.java

    r1926 r1929  
    1515package de.ugoe.cs.autoquest.plugin.uml; 
    1616 
    17 import java.io.StringWriter; 
    18 import java.util.ArrayList; 
    1917import java.util.Collection; 
    2018import java.util.Collections; 
     
    3230import java.util.TreeSet; 
    3331 
    34 import javax.xml.transform.Transformer; 
    35 import javax.xml.transform.TransformerException; 
    36 import javax.xml.transform.TransformerFactory; 
    37 import javax.xml.transform.TransformerFactoryConfigurationError; 
    38 import javax.xml.transform.dom.DOMSource; 
    39 import javax.xml.transform.stream.StreamResult; 
    40  
    4132import org.eclipse.emf.common.util.EList; 
    42 import org.eclipse.emf.common.util.URI; 
    4333import org.eclipse.uml2.uml.Activity; 
    4434import org.eclipse.uml2.uml.ActivityEdge; 
     
    7464import org.eclipse.uml2.uml.Port; 
    7565import org.eclipse.uml2.uml.PrimitiveType; 
    76 import org.eclipse.uml2.uml.Profile; 
    7766import org.eclipse.uml2.uml.Property; 
    7867import org.eclipse.uml2.uml.Region; 
     
    8372import org.eclipse.uml2.uml.Transition; 
    8473import org.eclipse.uml2.uml.Trigger; 
    85 import org.eclipse.uml2.uml.Type; 
    8674import org.eclipse.uml2.uml.UMLPackage; 
     75import org.eclipse.uml2.uml.ValueSpecification; 
    8776import org.eclipse.uml2.uml.Vertex; 
    88 import org.w3c.dom.Attr; 
    89 import org.w3c.dom.Node; 
    90 import org.w3c.dom.NodeList; 
    9177 
    9278import de.ugoe.cs.autoquest.eventcore.Event; 
     
    11399    final static int MAX_MULTIPLICITY = 10; 
    114100 
    115     final public static URI UML_PRIMITIVE_TYPES_URI = URI 
    116         .createURI("pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml", true); 
    117  
    118101    /** 
    119102     * <p> 
     
    134117                                           String testContextName) 
    135118    { 
    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  
    141119        int violationCount = 0; 
    142         Component testContext = fetchTestContext(model, utpTestContext, testContextName); 
     120        Component testContext = fetchTestContext(model, testContextName); 
    143121        if (testContext == null) { 
    144122            violationCount++; 
     
    186164        // fetch all SUTs and TestComponents 
    187165        HashMap<String, Property> properties = new HashMap<>(); 
    188         for (Property property : testContext.getAllAttributes()) { 
    189             if (property.getAppliedStereotypes().contains(utpSUT)) { 
    190                 properties.put(property.getName(), property); 
    191             } 
    192             else if (property.getType().getAppliedStereotypes().contains(utpTestComponent)) { 
    193                 properties.put(property.getName(), property); 
    194             } 
     166        for (Property property : fetchAllSUTProperties(testContext)) { 
     167            properties.put(property.getName(), property); 
     168        } 
     169        for (Property property : fetchAllTestComponentProperties(testContext)) { 
     170            properties.put(property.getName(), property); 
    195171        } 
    196172        Console.traceln(Level.INFO, "Found the following services in the TestConfiguration:"); 
     
    455431     *            test context found is used. 
    456432     */ 
    457     public static void createInteractionFromEventSequence(List<Event> sequence, 
    458                                                           Model model, 
    459                                                           String interactionName, 
    460                                                           String testContextName) 
     433    public static Interaction createInteractionFromEventSequence(List<Event> sequence, 
     434                                                                 Model model, 
     435                                                                 String interactionName, 
     436                                                                 String testContextName) 
    461437    { 
    462         final Profile utpProfile = model.getAppliedProfile("utp"); 
    463         final Stereotype utpTestCase = (Stereotype) utpProfile.getOwnedMember("TestCase"); 
    464         final Stereotype utpTestComponent = (Stereotype) utpProfile.getOwnedMember("TestComponent"); 
    465         final Stereotype utpSUT = (Stereotype) utpProfile.getOwnedMember("SUT"); 
    466         final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext"); 
    467  
    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  
    473         Component testContext = fetchTestContext(model, utpTestContext, testContextName); 
     438        final Component testContext = fetchTestContext(model, testContextName); 
    474439        if (testContext == null) { 
    475440            throw new RuntimeException("Could not find any test context in the model"); 
    476441        } 
    477442 
    478         Operation operation = testContext.createOwnedOperation(interactionName, null, null); 
    479         operation.applyStereotype(utpTestCase); 
    480  
    481         Interaction interaction = 
     443        final Operation operation = testContext.createOwnedOperation(interactionName, null, null); 
     444        operation.applyStereotype(UTPUtils.getTestCaseStereotype(model)); 
     445 
     446        final Interaction interaction = 
    482447            (Interaction) testContext.createPackagedElement(interactionName + "_Impl", 
    483448                                                            UMLPackage.Literals.INTERACTION); 
     
    487452        Lifeline userLifeline = null; 
    488453 
    489         for (Property property : testContext.getAllAttributes()) { 
    490             if (property.getAppliedStereotypes().contains(utpSUT)) { 
    491                 String serviceName = property.getName(); 
    492                 Lifeline targetLifeline = interaction.createLifeline(serviceName); 
    493                 targetLifeline.setRepresents(property); 
    494             } 
    495             else if (property.getType().getAppliedStereotypes().contains(utpTestComponent)) { 
    496                 if (userLifeline != null) { 
    497                     throw new RuntimeException( 
    498                                                "TestContext must only have one TestComponent for the application of usage-based testing."); 
    499                 } 
    500                 userLifeline = interaction.createLifeline(property.getName()); 
    501                 userLifeline.setRepresents(property); 
    502             } 
    503         } 
     454        for (Property property : fetchAllSUTProperties(testContext)) { 
     455            String serviceName = property.getName(); 
     456            Lifeline targetLifeline = interaction.createLifeline(serviceName); 
     457            targetLifeline.setRepresents(property); 
     458        } 
     459        for (Property property : fetchAllTestComponentProperties(testContext)) { 
     460            // TODO check if this is still required 
     461            if (userLifeline != null) { 
     462                throw new RuntimeException( 
     463                                           "TestContext must only have one TestComponent for the application of usage-based testing."); 
     464            } 
     465            userLifeline = interaction.createLifeline(property.getName()); 
     466            userLifeline.setRepresents(property); 
     467        } 
     468 
    504469        if (userLifeline == null) { 
    505470            throw new RuntimeException("No TestComponent found, could not create user lifeline."); 
     
    580545                callRecvFragment.setCovered(msgTargetLifeline); 
    581546 
     547                // get connector 
     548                Connector connector = inferConnector(msgSourceLifeline, msgTargetLifeline); 
     549 
    582550                // create call 
    583                 Message callMessage = interaction.createMessage(methodName); 
     551                Message callMessage = interaction.createMessage(prefix + "call"); 
    584552                callMessage.setSignature(calledOperation); 
    585                 setMessageParameters(callMessage, calledOperation, event, prefix); 
    586                 callMessage.setConnector(inferConnector(msgSourceLifeline, msgTargetLifeline)); 
     553                setCallMessageParameters(callMessage, calledOperation, event, prefix); 
     554                callMessage.setConnector(connector); 
    587555                callMessage.setSendEvent(callSendFragment); 
    588556                callMessage.setReceiveEvent(callRecvFragment); 
     
    632600 
    633601                    // create reply 
    634                     Message replyMessage = interaction.createMessage(methodName + "_reply"); 
     602                    Message replyMessage = interaction.createMessage(prefix + "_reply"); 
    635603                    replyMessage.setMessageSort(MessageSort.REPLY_LITERAL); 
    636604                    replyMessage.setSignature(calledOperation); 
     605                    setReplyMessageParameters(replyMessage, calledOperation); 
     606                    replyMessage.setConnector(connector); 
    637607                    replyMessage.setSendEvent(replySendFragment); 
    638608                    replyMessage.setReceiveEvent(replyRecvFragment); 
     
    644614            } 
    645615        } 
     616        return interaction; 
    646617    } 
    647618 
     
    662633    { 
    663634        double usageScore = 0.0d; 
    664  
    665635        EList<InteractionFragment> interactionFragments = interaction.getFragments(); 
    666636        List<Event> eventSequence = new LinkedList<>(); 
    667637        eventSequence.add(Event.STARTEVENT); 
    668638        for (InteractionFragment interactionFragment : interactionFragments) { 
    669             if (interactionFragment.getName() != null && 
    670                 interactionFragment.getName().endsWith("_recvFragment")) // TODO must be more 
    671                                                                          // generic 
    672             { 
    673                 String serviceName = 
    674                     interactionFragment.getCovereds().get(0).getRepresents().getName().split("_")[0]; 
    675                 String methodName = "UNKNOWN"; 
    676                 if (interactionFragment instanceof MessageOccurrenceSpecification) { 
    677                     methodName = 
    678                         ((MessageOccurrenceSpecification) interactionFragment).getMessage() 
    679                             .getName(); 
    680                 } 
    681                 // eventSequence.add(new Event(new SimpleSOAPEventType(methodName, serviceName, "", 
    682                 // ))); // TODO 
    683                 // add 
    684                 // client 
    685                 // name 
     639            if (interactionFragment instanceof MessageOccurrenceSpecification) { 
     640                Message message = 
     641                    ((MessageOccurrenceSpecification) interactionFragment).getMessage(); 
     642                if (message.getReceiveEvent().equals(interactionFragment) && isCallMessage(message)) 
     643                { 
     644                    String clientName = 
     645                        ((MessageOccurrenceSpecification) message.getSendEvent()).getCovereds() 
     646                            .get(0).getName(); 
     647                    String serviceName = 
     648                        ((MessageOccurrenceSpecification) message.getReceiveEvent()).getCovereds() 
     649                            .get(0).getName(); 
     650                    String methodName = message.getSignature().getName(); 
     651                    eventSequence.add(new Event(new SimpleSOAPEventType(methodName, serviceName, 
     652                                                                        clientName, null))); 
     653                } 
    686654            } 
    687655        } 
     
    707675                                        String testContextName) 
    708676    { 
    709  
    710         final Profile utpProfile = model.getAppliedProfile("utp"); 
    711         final Stereotype utpTestCase = (Stereotype) utpProfile.getOwnedMember("TestCase"); 
    712         final Stereotype utpTestContext = (Stereotype) utpProfile.getOwnedMember("TestContext"); 
    713  
    714         Component testContext = fetchTestContext(model, utpTestContext, testContextName); 
     677        final Component testContext = fetchTestContext(model, testContextName); 
    715678        if (testContext == null) { 
    716679            throw new RuntimeException("Could not find any test context in the model"); 
     
    720683 
    721684        // first, we determine all test cases and calculate their usage scores 
     685        final Stereotype utpTestCase = UTPUtils.getTestCaseStereotype(model); 
    722686        for (Operation operation : testContext.getAllOperations()) { 
    723             if (operation.getAppliedStereotypes().contains(utpTestCase)) { 
     687            if (operation.getAppliedStereotypes().contains(utpTestCase) && 
     688                !operation.getMethods().isEmpty()) 
     689            { 
    724690                Interaction interaction = (Interaction) operation.getMethods().get(0); 
    725691                usageScoreMapUnsorted 
     
    764730        edge.setSource(currentOperationNode); 
    765731        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; 
    787732    } 
    788733 
     
    862807    } 
    863808 
     809    /** 
     810     * <p> 
     811     * Fetches all realized interfaces from the type of a UML {@link Property} (i.e., 
     812     * property.getType()). If no interfaces are realized, an empty set is returned. 
     813     * </p> 
     814     *  
     815     * @param property 
     816     *            property, of the whose realized interfaces of the type are determined 
     817     * @return realized interfaces 
     818     */ 
    864819    private static Set<Interface> getRealizedInterfacesFromProperty(Property property) { 
    865820        return getRealizedInterfaceFromComponent((Component) property.getType()); 
    866821    } 
    867822 
    868     private static Set<Interface> getRealizedInterfaceFromComponent(Component comp) { 
     823    /** 
     824     * <p> 
     825     * Fetches all realized interfaces from a UML {@link Component}. If no interfaces are realized, 
     826     * an empty set is returned. 
     827     * </p> 
     828     *  
     829     * @param comp 
     830     *            component whose realized interfaces are determined 
     831     * @return realized interfaces 
     832     */ 
     833    private static Set<Interface> getRealizedInterfaceFromComponent(Component component) { 
    869834        Set<Interface> interfaces = new HashSet<>(); 
    870835        // Interface myInterface = null; 
    871         for (Property property : comp.getAttributes()) { 
     836        for (Property property : component.getAttributes()) { 
    872837            if (property instanceof Port) { 
    873838                Port port = (Port) property; 
     
    880845    } 
    881846 
    882     private static Component fetchTestContext(Package pkg, 
    883                                               Stereotype utpTestContext, 
    884                                               String testContextName) 
    885     { 
    886         List<Component> testContexts = fetchTestContextRecursively(pkg, utpTestContext); 
     847    /** 
     848     * <p> 
     849     * Determines searches within a {@link Package} for a component to which the UTP TestContext 
     850     * stereotype is applied. 
     851     * <ul> 
     852     * <li>If no testContextName is provided, the first test context found is returned.</li> 
     853     * <li>In case no test context is found, null is returned.</li> 
     854     * </p> 
     855     *  
     856     * @param pkg 
     857     *            package where the test context is being locked for 
     858     * @param testContextName 
     859     *            name of the test context; in case no test name is specified, use null and not the 
     860     *            empty String. 
     861     * @return {@link Component} to which the TestContext stereotype is applied 
     862     */ 
     863    private static Component fetchTestContext(final Package pkg, final String testContextName) { 
     864        List<Component> testContexts = fetchAllTestContexts(pkg); 
    887865        if (testContexts.isEmpty()) { 
    888866            return null; 
     
    901879    } 
    902880 
    903     private static List<Component> fetchTestContextRecursively(Package pkg, 
    904                                                                Stereotype utpTestContext) 
    905     { 
    906         List<Component> testContexts = new LinkedList<>(); 
     881    /** 
     882     * <p> 
     883     * Retrieves all UML {@link Component}s to which the UTP TestContext stereotype is applied from 
     884     * a package. This method calls itself recursively to include all components contained in 
     885     * sub-packages. 
     886     * </p> 
     887     * <p> 
     888     * In case no test context is found, an empty list is returned. 
     889     * </p> 
     890     *  
     891     * @param pkg 
     892     *            package from which the test contexts are retrieved 
     893     * @return {@link List} of test contexts 
     894     */ 
     895    private static List<Component> fetchAllTestContexts(final Package pkg) { 
     896        final Stereotype utpTestContext = UTPUtils.getTestContextStereotype(pkg.getModel()); 
     897        final List<Component> testContexts = new LinkedList<>(); 
    907898        for (Element element : pkg.getOwnedElements()) { 
    908899            if (element instanceof Package) { 
    909                 testContexts.addAll(fetchTestContextRecursively((Package) element, utpTestContext)); 
     900                testContexts.addAll(fetchAllTestContexts((Package) element)); 
    910901            } 
    911902            if (element instanceof Component && 
     
    920911    /** 
    921912     * <p> 
    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. 
    924      * </p> 
    925      *  
    926      * @param userAttributes 
     913     * Retrieves all properties that represent a UTP TestComponent from a test context. 
     914     * </p> 
     915     *  
     916     * @param testContext 
     917     *            test context from which the properties are retrieved 
     918     * @return properties that represent test components 
     919     */ 
     920    private static Set<Property> fetchAllTestComponentProperties(final Component testContext) { 
     921        // fetch all SUTs and TestComponents 
     922        final Stereotype utpTestComponent = 
     923            UTPUtils.getTestComponentStereotype(testContext.getModel()); 
     924        final Set<Property> properties = new HashSet<>(); 
     925        for (Property property : testContext.getAllAttributes()) { 
     926            if (property.getType().getAppliedStereotypes().contains(utpTestComponent)) { 
     927                properties.add(property); 
     928            } 
     929        } 
     930        return properties; 
     931    } 
     932 
     933    /** 
     934     * <p> 
     935     * Retrieves all properties that represent a UTP SUT from a test context. 
     936     * </p> 
     937     *  
     938     * @param testContext 
     939     *            test context from which the properties are retrieved 
     940     * @return properties that represent the SUTs 
     941     */ 
     942    private static Set<Property> fetchAllSUTProperties(final Component testContext) { 
     943        // fetch all SUTs and TestComponents 
     944        final Stereotype utpSUT = UTPUtils.getSUTStereotype(testContext.getModel()); 
     945        final Set<Property> properties = new HashSet<>(); 
     946        for (Property property : testContext.getAllAttributes()) { 
     947            if (property.getAppliedStereotypes().contains(utpSUT)) { 
     948                properties.add(property); 
     949            } 
     950        } 
     951        return properties; 
     952    } 
     953 
     954    /** 
     955     * <p> 
     956     * Infers connector between two lifelines. 
     957     * </p> 
     958     * <p> 
     959     * TODO: Currently assumes only one connector between two lifelines possible. This assumption is 
     960     * invalid as soon as there are two ports that connect the same two properties. 
     961     * </p> 
     962     *  
     963     * @param msgSourceLifeline 
     964     *            source lifeline of the message 
    927965     * @param targetAttributes 
     966     *            target lifeline of the message 
    928967     */ 
    929968    private static Connector inferConnector(Lifeline msgSourceLifeline, Lifeline msgTargetLifeline) 
     
    955994    } 
    956995 
     996    /** 
     997     * <p> 
     998     * Creates a map that maps the interfaces to the properties, i.e., services that they are 
     999     * represented by. 
     1000     * </p> 
     1001     * <p> 
     1002     * TODO: currently assumes that each interfaces is only realized by one property 
     1003     * </p> 
     1004     *  
     1005     * @param model 
     1006     *            model for which the interface->service map is created 
     1007     * @return the map 
     1008     */ 
    9571009    private static Map<Interface, String> createInterfaceServiceMap(Model model) { 
    9581010        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); 
     1011        List<Component> testContexts = fetchAllTestContexts(model.getModel()); 
    9651012        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                     } 
     1013            for (Property property : fetchAllSUTProperties(testContext)) { 
     1014                for (Interface intface : getRealizedInterfacesFromProperty(property)) { 
     1015                    interfaceServiceMap.put(intface, property.getName()); 
     1016                } 
     1017            } 
     1018            for (Property property : fetchAllTestComponentProperties(testContext)) { 
     1019                for (Interface intface : getRealizedInterfacesFromProperty(property)) { 
     1020                    interfaceServiceMap.put(intface, property.getName()); 
    9731021                } 
    9741022            } 
     
    9771025    } 
    9781026 
    979     private static void setMessageParameters(Message callMessage, 
    980                                              Operation calledOperation, 
    981                                              Event event, 
    982                                              String prefix) 
     1027    /** 
     1028     * <p> 
     1029     * Sets values for the parameters of a call message. The values are, if possible, inferred from 
     1030     * the event that is provided. 
     1031     * </p> 
     1032     *  
     1033     * @param callMessage 
     1034     *            call message for which the parameters are set 
     1035     * @param calledOperation 
     1036     *            operation that is called by the message 
     1037     * @param event 
     1038     *            event that provides the parameters; in case of null, default values are assumed 
     1039     * @param prefix 
     1040     *            prefix of the call message; used to create good warnings and debugging information 
     1041     */ 
     1042    private static void setCallMessageParameters(Message callMessage, 
     1043                                                 Operation calledOperation, 
     1044                                                 Event event, 
     1045                                                 String prefix) 
    9831046    { 
    9841047        org.w3c.dom.Element requestBody = SOAPUtils.getSoapRequestBodyFromEvent(event); 
     1048        Package instSpecPkg = null; 
    9851049 
    9861050        // Set parameters of operation 
    9871051        for (Parameter param : calledOperation.getOwnedParameters()) { 
     1052            if (instSpecPkg == null) { 
     1053                instSpecPkg = getOrCreateInstanceSpecificationPackage(param.getModel(), event); 
     1054            } 
     1055 
     1056            String path = calledOperation.getName() + ":" + param.getName(); 
    9881057            Expression argument = 
    9891058                (Expression) callMessage.createArgument(param.getName(), param.getType(), 
    9901059                                                        UMLPackage.Literals.EXPRESSION); 
    9911060 
    992             if (param.getDirection() == ParameterDirectionKind.IN_LITERAL || 
    993                 param.getDirection() == ParameterDirectionKind.INOUT_LITERAL) 
    994             { 
     1061            if (isInParameter(param)) { 
    9951062                if (param.getType() instanceof DataType) { 
    9961063                    List<org.w3c.dom.Element> paramNodes = 
    997                         getMatchingChildNode((DataType) param.getType(), requestBody); 
    998                     for (org.w3c.dom.Element paramNode : paramNodes) { 
     1064                        SOAPUtils.getMatchingChildNode(param.getType().getName(), requestBody); 
     1065                    int multiplicityChosen = paramNodes.size(); 
     1066 
     1067                    if (multiplicityChosen == 0 && param.getLower() > 0) { 
     1068                        Console.traceln(Level.WARNING, 
     1069                                        "required attribute not found in SOAP message: " + path); 
     1070                        Console 
     1071                            .traceln(Level.WARNING, 
     1072                                     "setting default values for this attribute and all its children"); 
     1073                        Console.traceln(Level.FINE, "XML structure of path:" + StringTools.ENDLINE + 
     1074                            SOAPUtils.getSerialization(requestBody)); 
     1075                        multiplicityChosen = param.getLower(); 
     1076                    } 
     1077                    for (int i = 0; i < multiplicityChosen; i++) { 
     1078                        org.w3c.dom.Element paramNode = null; 
     1079                        if (!paramNodes.isEmpty()) { 
     1080                            paramNode = paramNodes.get(i); 
     1081                        } 
    9991082                        InstanceSpecification instSpec = 
    1000                             createInstanceSpecification((DataType) param.getType(), event, prefix, 
    1001                                                         paramNode, ""); 
     1083                            createInstanceSpecification((DataType) param.getType(), instSpecPkg, 
     1084                                                        prefix, paramNode, path); 
    10021085 
    10031086                        InstanceValue value = 
     
    10091092                } 
    10101093                else if (param.getType() instanceof PrimitiveType) { 
    1011                     createOperandPrimitiveType(param, argument, requestBody); 
     1094                    createOperandPrimitiveType(param, argument, requestBody, path); 
    10121095                } 
    10131096            } 
     
    10191102    } 
    10201103 
     1104    /** 
     1105     * <p> 
     1106     * Creates an {@link InstanceSpecification} for a data type in the given package. The values are 
     1107     * inferred, if possible, from the DOM node. The prefix and the path are used for naming the 
     1108     * instance specification and to provide good warnings and debug information in case of 
     1109     * problems. 
     1110     * </p> 
     1111     *  
     1112     * @param type 
     1113     *            DataType for which the {@link InstanceSpecification} is created 
     1114     * @param pkg 
     1115     *            package in which the {@link InstanceSpecification} is created 
     1116     * @param prefix 
     1117     *            prefix used for naming the {@link InstanceSpecification} 
     1118     * @param currentNode 
     1119     *            node of a DOM from which values are inferred 
     1120     * @param path 
     1121     *            used for warnings and debug information 
     1122     * @return {@link InstanceSpecification} for the given type 
     1123     */ 
    10211124    private static InstanceSpecification createInstanceSpecification(DataType type, 
    1022                                                                      Event event, 
     1125                                                                     Package pkg, 
    10231126                                                                     String prefix, 
    10241127                                                                     org.w3c.dom.Element currentNode, 
     
    10281131            path = type.getName(); 
    10291132        } 
    1030         // System.out.println(path); 
    1031         String pkgUBTInstSpecs = "UBT_InstanceSpecifications"; 
    1032         Model model = type.getModel(); 
    1033         Package ubtInstSpecPkg = (Package) model.getOwnedMember(pkgUBTInstSpecs); 
    1034         if (ubtInstSpecPkg == null) { 
    1035             ubtInstSpecPkg = 
    1036                 (Package) type.getModel().createPackagedElement(pkgUBTInstSpecs, 
    1037                                                                 UMLPackage.Literals.PACKAGE); 
    1038         } 
    1039         String serviceName = SOAPUtils.getServiceNameFromEvent(event); 
    1040         Package serviceInstSpecPkg = (Package) ubtInstSpecPkg.getOwnedMember(serviceName); 
    1041         if (serviceInstSpecPkg == null) { 
    1042             serviceInstSpecPkg = 
    1043                 (Package) ubtInstSpecPkg.createPackagedElement(serviceName, 
    1044                                                                UMLPackage.Literals.PACKAGE); 
    1045         } 
    10461133 
    10471134        InstanceSpecification instSpec = 
    1048             (InstanceSpecification) serviceInstSpecPkg.createPackagedElement(prefix + "instspec_" + 
    1049                 type.getName(), UMLPackage.Literals.INSTANCE_SPECIFICATION); 
     1135            (InstanceSpecification) pkg 
     1136                .createPackagedElement(prefix + "instspec_" + type.getName(), 
     1137                                       UMLPackage.Literals.INSTANCE_SPECIFICATION); 
    10501138        instSpec.getClassifiers().add(type); 
    10511139        for (Property prop : type.getAllAttributes()) { 
     
    10571145                int multiplicityChosen = 0; 
    10581146                if (currentNode != null) { 
    1059                     attributeNodes = getMatchingChildNode(prop, currentNode); 
     1147                    attributeNodes = SOAPUtils.getMatchingChildNode(prop.getName(), currentNode); 
    10601148                    multiplicityChosen = attributeNodes.size(); 
    10611149                } 
     
    10861174                        (InstanceValue) slot.createValue(prop.getName() + "_" + i, prop.getType(), 
    10871175                                                         UMLPackage.Literals.INSTANCE_VALUE); 
    1088                     value.setInstance(createInstanceSpecification((DataType) prop.getType(), event, 
     1176                    value.setInstance(createInstanceSpecification((DataType) prop.getType(), pkg, 
    10891177                                                                  prefix, attributeNode, path + 
    10901178                                                                      "." + prop.getName())); 
     
    11001188    } 
    11011189 
     1190    /** 
     1191     * <p> 
     1192     * Gets or creates a {@link Package} for {@link InstanceSpecification} created by the 
     1193     * usage-based testing. Each service gets its own sub-package within a package called 
     1194     * UBT_InstanceSpecifications. " 
     1195     * </p> 
     1196     *  
     1197     * @param model 
     1198     *            model in which the package is generated 
     1199     * @param event 
     1200     *            event from which the service name is inferred 
     1201     * @return package for the {@link InstanceSpecification}s 
     1202     */ 
     1203    private static Package getOrCreateInstanceSpecificationPackage(Model model, Event event) { 
     1204        String pkgUBTInstSpecs = "UBT_InstanceSpecifications"; 
     1205        Package ubtInstSpecPkg = (Package) model.getOwnedMember(pkgUBTInstSpecs); 
     1206        if (ubtInstSpecPkg == null) { 
     1207            ubtInstSpecPkg = 
     1208                (Package) model.createPackagedElement(pkgUBTInstSpecs, UMLPackage.Literals.PACKAGE); 
     1209        } 
     1210        String serviceName = SOAPUtils.getServiceNameFromEvent(event); 
     1211        Package serviceInstSpecPkg = (Package) ubtInstSpecPkg.getOwnedMember(serviceName); 
     1212        if (serviceInstSpecPkg == null) { 
     1213            serviceInstSpecPkg = 
     1214                (Package) ubtInstSpecPkg.createPackagedElement(serviceName, 
     1215                                                               UMLPackage.Literals.PACKAGE); 
     1216        } 
     1217        return serviceInstSpecPkg; 
     1218    } 
     1219 
     1220    /** 
     1221     * <p> 
     1222     * Creates an operand that defines a {@link PrimitiveType}. 
     1223     * </p> 
     1224     * <p> 
     1225     * TODO: Currently does nothing in case of multiplicity 0. I am not sure if, in that case, one 
     1226     * has to define LiteralNull instead. 
     1227     * </p> 
     1228     *  
     1229     * @param param 
     1230     *            parameter for which the operand is created 
     1231     * @param argument 
     1232     *            argument to which the operand is added 
     1233     * @param currentNode 
     1234     *            DOM node from which is value for the operand is inferred 
     1235     * @param path 
     1236     *            used for warnings and debug information 
     1237     */ 
    11021238    private static void createOperandPrimitiveType(Parameter param, 
    11031239                                                   Expression argument, 
    1104                                                    org.w3c.dom.Element currentNode) 
     1240                                                   org.w3c.dom.Element currentNode, 
     1241                                                   String path) 
    11051242    { 
    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  
     1243        List<String> attributeValues = SOAPUtils.getValuesFromElement(param.getName(), currentNode); 
     1244 
     1245        if (attributeValues.isEmpty()) { 
     1246            if (param.getLower() == 0) { 
     1247                // ignoring optional attribute 
     1248                return; 
     1249            } 
     1250            else { 
     1251                if (currentNode != null) { 
     1252                    Console.traceln(Level.WARNING, 
     1253                                    "required attribute not found in SOAP message: " + path + "." + 
     1254                                        param.getName()); 
     1255                    Console.traceln(Level.WARNING, "setting default values for this attribute"); 
     1256                    Console.traceln(Level.FINE, "XML structure of path:" + StringTools.ENDLINE + 
     1257                        SOAPUtils.getSerialization(currentNode)); 
     1258                } 
     1259                attributeValues.add(null); 
     1260            } 
     1261        } 
     1262        for (String attributeValue : attributeValues) { 
     1263            if ("String".equals(param.getType().getName())) { 
     1264                LiteralString spec = 
     1265                    (LiteralString) argument.createOperand(param.getName(), null, 
     1266                                                           UMLPackage.Literals.LITERAL_STRING); 
     1267                if (attributeValue != null) { 
     1268                    spec.setValue(attributeValue); 
     1269                } 
     1270                else { 
     1271                    spec.setValue("foobar"); 
     1272                } 
     1273            } 
     1274            else if ("Integer".equals(param.getType().getName())) { 
     1275                LiteralInteger spec = 
     1276                    (LiteralInteger) argument.createOperand(param.getName(), null, 
     1277                                                            UMLPackage.Literals.LITERAL_INTEGER); 
     1278                if (attributeValue != null) { 
     1279                    spec.setValue(Integer.parseInt(attributeValue)); 
     1280                } 
     1281                else { 
     1282                    spec.setValue(42); 
     1283                } 
     1284            } 
     1285            else if ("Boolean".equals(param.getType().getName())) { 
     1286                LiteralBoolean spec = 
     1287                    (LiteralBoolean) argument.createOperand(param.getName(), null, 
     1288                                                            UMLPackage.Literals.LITERAL_BOOLEAN); 
     1289                if (attributeValue != null) { 
     1290                    spec.setValue(Boolean.parseBoolean(attributeValue)); 
     1291                } 
     1292                else { 
     1293                    spec.setValue(true); 
     1294                } 
     1295            } 
     1296            else if ("Real".equals(param.getType().getName())) { 
     1297                LiteralReal spec = 
     1298                    (LiteralReal) argument.createOperand(param.getName(), null, 
     1299                                                         UMLPackage.Literals.LITERAL_REAL); 
     1300                if (attributeValue != null) { 
     1301                    spec.setValue(Double.parseDouble(attributeValue)); 
     1302                } 
     1303                else { 
     1304                    spec.setValue(3.14); 
     1305                } 
     1306            } 
     1307        } 
     1308    } 
     1309 
     1310    /** 
     1311     * <p> 
     1312     * Creates a {@link Slot} in an {@link InstanceSpecification} for a primitive type. 
     1313     * </p> 
     1314     *  
     1315     * @param instSpec 
     1316     *            instance specification to which the slot is added 
     1317     * @param prop 
     1318     *            property that describes the slot 
     1319     * @param currentNode 
     1320     *            DOM node from which is value for the slot is inferred 
     1321     * @param path 
     1322     *            used for warnings and debug information 
     1323     */ 
    11321324    private static void createSlotPrimitiveType(InstanceSpecification instSpec, 
    11331325                                                Property prop, 
     
    11351327                                                String path) 
    11361328    { 
    1137         List<String> attributeValues = getPrimitiveTypeValuesFromElement(prop, currentNode); 
     1329        List<String> attributeValues = SOAPUtils.getValuesFromElement(prop.getName(), currentNode); 
    11381330 
    11391331        if (attributeValues.isEmpty()) { 
     
    11481340                                        prop.getName()); 
    11491341                    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)); 
     1342                    Console.traceln(Level.FINE, "XML structure of path:" + StringTools.ENDLINE + 
     1343                        SOAPUtils.getSerialization(currentNode)); 
     1344                } 
    11531345                attributeValues.add(null); 
    11541346            } 
     
    11981390                } 
    11991391                else { 
    1200                     value.setValue(3.14); // TODO needs to be real value 
     1392                    value.setValue(3.14); 
    12011393                } 
    12021394            } 
     
    12091401    } 
    12101402 
    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()); 
     1403    /** 
     1404     * <p> 
     1405     * Sets values for the parameters of a reply message. The values are, all LiterealNull and to 
     1406     * the INOUT, OUT and REPLY parameters, the UTP stereotype LiteralAny is applied. 
     1407     * </p> 
     1408     *  
     1409     * @param replyMessage 
     1410     *            reply message for which the parameters are set 
     1411     * @param calledOperation 
     1412     *            operation that is replied for by the message 
     1413     */ 
     1414    private static void setReplyMessageParameters(Message replyMessage, Operation calledOperation) { 
     1415        for (Parameter param : calledOperation.getOwnedParameters()) { 
     1416            Expression argument = 
     1417                (Expression) replyMessage.createArgument(param.getName(), param.getType(), 
     1418                                                         UMLPackage.Literals.EXPRESSION); 
     1419            if (isOutParameter(param)) { 
     1420                ValueSpecification operand = 
     1421                    argument.createOperand(null, param.getType(), UMLPackage.Literals.LITERAL_NULL); 
     1422                operand.applyStereotype(UTPUtils.getLiteralAnyStereotype(param.getModel())); 
    12711423            } 
    12721424            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  
     1425                argument.createOperand(null, param.getType(), UMLPackage.Literals.LITERAL_NULL); 
     1426            } 
     1427        } 
     1428    } 
     1429 
     1430    /** 
     1431     * <p> 
     1432     * Checks if a parameter has the direction IN or INOUT 
     1433     * </p> 
     1434     *  
     1435     * @param parameter 
     1436     *            parameter that is checked 
     1437     * @return true if the direction is IN or INOUT; false otherwise 
     1438     */ 
     1439    private static boolean isInParameter(Parameter parameter) { 
     1440        return parameter.getDirection() == ParameterDirectionKind.IN_LITERAL || 
     1441            parameter.getDirection() == ParameterDirectionKind.INOUT_LITERAL; 
     1442    } 
     1443 
     1444    /** 
     1445     * <p> 
     1446     * Checks if a parameter has the direction RETURN, OUT or INOUT 
     1447     * </p> 
     1448     *  
     1449     * @param parameter 
     1450     *            parameter that is checked 
     1451     * @return true if the direction is RETURN, OUT, or INOUT; false otherwise 
     1452     */ 
     1453    private static boolean isOutParameter(Parameter parameter) { 
     1454        return parameter.getDirection() == ParameterDirectionKind.RETURN_LITERAL || 
     1455            parameter.getDirection() == ParameterDirectionKind.OUT_LITERAL || 
     1456            parameter.getDirection() == ParameterDirectionKind.INOUT_LITERAL; 
     1457    } 
     1458 
     1459    /** 
     1460     * <p> 
     1461     * Checks if the {@link MessageSort} of a message is a call message, i.e., ASYNCH_CALL or 
     1462     * SYNCH_CALL. 
     1463     * </p> 
     1464     *  
     1465     * @param message 
     1466     *            message that is checked 
     1467     * @return true if the message is a call message; false otherwise 
     1468     */ 
     1469    private static boolean isCallMessage(Message message) { 
     1470        if (message == null) { 
     1471            return false; 
     1472        } 
     1473        MessageSort msgSort = message.getMessageSort(); 
     1474        return msgSort == MessageSort.ASYNCH_CALL_LITERAL || 
     1475            msgSort == MessageSort.SYNCH_CALL_LITERAL; 
     1476    } 
     1477 
     1478    /** 
     1479     * <p> 
     1480     * inverse-sorts the values of a map. Has been adapted from <a href= 
     1481     * "http://stackoverflow.com/questions/109383/how-to-sort-a-mapkey-value-on-the-values-in-java" 
     1482     * >this</a> StackOverflow post. 
     1483     * </p> 
     1484     *  
     1485     * @param map 
     1486     *            map whose values are sorted 
     1487     * @return sorted version of the map 
     1488     */ 
     1489    private static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { 
     1490        // TODO possibly move to another class 
     1491        List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet()); 
     1492        Collections.sort(list, new Comparator<Map.Entry<K, V>>() { 
     1493            @Override 
     1494            public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) { 
     1495                return -1 * (o1.getValue()).compareTo(o2.getValue()); 
     1496            } 
     1497        }); 
     1498 
     1499        Map<K, V> result = new LinkedHashMap<>(); 
     1500        for (Map.Entry<K, V> entry : list) { 
     1501            result.put(entry.getKey(), entry.getValue()); 
     1502        } 
     1503        return result; 
     1504    } 
    12841505} 
Note: See TracChangeset for help on using the changeset viewer.