// Copyright 2012 Georg-August-Universität Göttingen, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package de.ugoe.cs.autoquest.plugin.uml;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Region;
import org.eclipse.uml2.uml.StateMachine;
import org.eclipse.uml2.uml.Transition;
import org.eclipse.uml2.uml.Vertex;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.autoquest.plugin.http.eventcore.SOAPEventType;
import de.ugoe.cs.autoquest.plugin.uml.eventcore.UMLTransitionType;
/**
*
* TODO comment
*
*
* @author Steffen Herbold
*/
public class UMLUtils {
public static List createUMLTransitionSequence(List sequence, StateMachine stateMachine) {
List> matchingSequences = determineMatchingTransitionSequences(sequence, stateMachine);
if (matchingSequences.size() != 1) {
throw new RuntimeException("no unique match found; " + matchingSequences.size() +
" matches");
}
List umlEventSequence = new LinkedList<>();
for (Transition transition : matchingSequences.get(0)) {
umlEventSequence.add(new Event(new UMLTransitionType(transition)));
}
return umlEventSequence;
}
public static void convertStateMachineToUsageProfile(Collection> sequences, StateMachine stateMachine) {
// create state->outgoings hashmap
Map> stateMap = new HashMap<>();
for( Region region : stateMachine.getRegions() ) {
for( Vertex state : region.getSubvertices() ) {
stateMap.put(state, new HashMap());
}
}
// create counters for each transition
for( List sequence : sequences) {
for( Event event : sequence ) {
if( event.getType() instanceof UMLTransitionType ) {
Transition transition = ((UMLTransitionType) event.getType()).getTransition();
Map transitionMap = stateMap.get(transition.getSource());
Integer value = transitionMap.get(transition);
if( value==null ) {
value = 0;
}
transitionMap.put(transition, value+1);
} else {
throw new RuntimeException("Wrong event type. Only UMLTransitionType supported but was: " +
event.getType().getClass().getName());
}
}
}
// calculate probabilities
for( Region region : stateMachine.getRegions() ) {
for( Vertex state : region.getSubvertices() ) {
Map transitionMap = stateMap.get(state);
int totalCount = 0;
for( Entry entry : transitionMap.entrySet() ) {
totalCount += entry.getValue();
}
if( totalCount!=0 ) {
for( Transition transition : state.getOutgoings() ) {
double prob = 0.0d;
if( transitionMap.containsKey(transition)) {
prob = ((double) transitionMap.get(transition))/totalCount;
}
Comment comment = transition.createOwnedComment();
comment.setBody("" + prob );
}
} else {
// system has never been in this state, all transitions equally likely
int numOutgoings = state.getOutgoings().size();
for( Transition transition : state.getOutgoings() ) {
Comment comment = transition.createOwnedComment();
comment.setBody("" + (1.0d/numOutgoings) );
}
}
}
}
}
public static List> determineMatchingTransitionSequences(List sequence, StateMachine stateMachine) {
EList regions = stateMachine.getRegions();
EList states = null;
for (Region region : regions) {
if (states == null) {
states = region.getSubvertices();
}
else {
states.addAll(region.getSubvertices());
}
}
List allTransitions = new LinkedList<>();
for (Vertex state : states) {
allTransitions.addAll(state.getOutgoings());
}
List> matchingSequences = null;
List currentTransitions = null;
// first, we try to find a single unique transition that we can match using the method name
for (Iterator eventIterator = sequence.iterator(); eventIterator.hasNext();) {
Event event = eventIterator.next();
if (event.getType() instanceof SOAPEventType) {
SOAPEventType eventType = (SOAPEventType) event.getType();
if (matchingSequences == null) {
matchingSequences = new LinkedList<>();
List initialMatches = matchTransitions(allTransitions, eventType);
for (Transition transition : initialMatches) {
List candidate = new LinkedList<>();
candidate.add(transition);
matchingSequences.add(candidate);
}
currentTransitions = initialMatches;
}
else {
List> nextMatchingSequences = new LinkedList<>();
List nextCurrentTransitions = new LinkedList<>();
Iterator currentTransitionIterator = currentTransitions.iterator();
Iterator> currentMatchingSequencesIterator =
matchingSequences.iterator();
while (currentTransitionIterator.hasNext()) {
Transition currentTransition = currentTransitionIterator.next();
List currentMatch = currentMatchingSequencesIterator.next();
List matches =
matchTransitions(currentTransition.getTarget().getOutgoings(),
eventType);
if (matches.isEmpty()) {
throw new RuntimeException("no matches found");
}
for (Transition matchingTransition : matches) {
List candidate = new LinkedList<>(currentMatch);
candidate.add(matchingTransition);
nextMatchingSequences.add(candidate);
nextCurrentTransitions.add(matchingTransition);
}
}
matchingSequences = nextMatchingSequences;
currentTransitions = nextCurrentTransitions;
}
}
else {
throw new RuntimeException("Wrong event type. Only UMLTransitionType supported but was: " +
event.getType().getClass().getName());
}
}
return matchingSequences;
}
private static List matchTransitions(List transitions, SOAPEventType eventType)
{
List matching = new LinkedList<>();
for (Transition transition : transitions) {
// String serviceName = transition.getName().split("\\.")[0]; // TODO service name check
String methodName = transition.getName().split("\\.")[1];
if (methodName.equals(eventType.getCalledMethod())) {
matching.add(transition);
}
}
return matching;
}
}