blob: f2da106019779b46386a3aaae06c980dbf88c6a0 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2020 Eclipse APP4MC contributors.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************
*/
package org.eclipse.app4mc.amalthea._import.btf.model;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.app4mc.amalthea.model.ProcessEventType;
import org.eclipse.app4mc.amalthea.model.RunnableEventType;
import org.eclipse.emf.common.util.Enumerator;
public enum BTFEntityState {
// initial state
notInitialized(new SimpleEntry<>(Collections.emptyList(), Arrays.asList(RunnableEventType.START)), //
new SimpleEntry<>(Collections.emptyList(), Arrays.asList(ProcessEventType.ACTIVATE))),
// in BTF this is actually the "active" state
startDelay(new SimpleEntry<>(Arrays.asList(ProcessEventType.ACTIVATE), Arrays.asList(ProcessEventType.START))),
running(new SimpleEntry<>(
Arrays.asList(RunnableEventType.START, RunnableEventType.RESUME),
Arrays.asList(RunnableEventType.TERMINATE, RunnableEventType.SUSPEND)), //
new SimpleEntry<>(
Arrays.asList(ProcessEventType.START, ProcessEventType.RESUME, ProcessEventType.RUN),
Arrays.asList(ProcessEventType.TERMINATE, ProcessEventType.PREEMPT, ProcessEventType.POLL, ProcessEventType.WAIT))),
polling(new SimpleEntry<>(Arrays.asList(ProcessEventType.POLL, ProcessEventType.POLL_PARKING), Arrays.asList(ProcessEventType.RUN, ProcessEventType.PARK))),
parking(new SimpleEntry<>(Arrays.asList(ProcessEventType.PARK), Arrays.asList(ProcessEventType.POLL_PARKING, ProcessEventType.RELEASE_PARKING))),
waiting(new SimpleEntry<>(Arrays.asList(ProcessEventType.WAIT), Arrays.asList(ProcessEventType.RELEASE))),
ready(new SimpleEntry<>(Arrays.asList(RunnableEventType.SUSPEND), Arrays.asList(RunnableEventType.RESUME)), //
new SimpleEntry<>(Arrays.asList(ProcessEventType.PREEMPT, ProcessEventType.RELEASE, ProcessEventType.RELEASE_PARKING),
Arrays.asList(ProcessEventType.RESUME))),
// meta state (not represented as combi state for simplicity)
response(new SimpleEntry<>(Arrays.asList(ProcessEventType.ACTIVATE), Arrays.asList(ProcessEventType.TERMINATE))),
// final state
terminated(new SimpleEntry<>(Arrays.asList(RunnableEventType.TERMINATE), Collections.emptyList()), //
new SimpleEntry<>(Arrays.asList(ProcessEventType.TERMINATE), Collections.emptyList()));
public final Map<BTFEntityType, Entry<List<Enumerator>, List<Enumerator>>> entityType2InOutEvents;
// list of all states excluding initial and final states
public static final List<BTFEntityState> actStates = Stream.of(values())
.filter(p -> p.entityType2InOutEvents.values().stream().noneMatch(e -> e.getKey().isEmpty()))
.filter(p -> p.entityType2InOutEvents.values().stream().noneMatch(e -> e.getValue().isEmpty()))
.collect(Collectors.toList());
@SafeVarargs
private BTFEntityState(final Entry<List<Enumerator>, List<Enumerator>>... inOutEvents) {
this.entityType2InOutEvents = new LinkedHashMap<>();
Stream.of(inOutEvents).forEach(e -> {
String entityTypeName = e.getKey().stream().findFirst().orElseGet(e.getValue().stream().findFirst()::get).getClass().getSimpleName();
entityTypeName = entityTypeName.substring(0, entityTypeName.indexOf("EventType")).toLowerCase();
this.entityType2InOutEvents.put(BTFEntityType.getForName(entityTypeName), e);
});
}
public static List<String> getValidityConstraints(final BTFEntityType entityType) {
final List<String> validityConstraints = new ArrayList<>();
// events for initial and final states must occur exactly once
Stream.of(values()).filter(s -> !actStates.contains(s)).map(s -> s.entityType2InOutEvents.get(entityType))
.filter(Objects::nonNull).forEach(entry -> {
entry.getKey().forEach(e -> validityConstraints.add(e.getName().toLowerCase() + "EventCount = 1"));
entry.getValue().forEach(e -> validityConstraints.add(e.getName().toLowerCase() + "EventCount = 1"));
});
// sum of incoming events must equal sum of outgoing events (excluding loop events)
actStates.stream().map(s -> s.entityType2InOutEvents.get(entityType)).filter(Objects::nonNull).forEach(entry -> {
final Set<Enumerator> loopEvents = new LinkedHashSet<>(entry.getKey());
loopEvents.retainAll(entry.getValue());
final String left = entry.getKey().stream().filter(e -> !loopEvents.contains(e)).map(e -> e.getName().toLowerCase() + "EventCount")
.collect(Collectors.joining(" + "));
final String right = entry.getValue().stream().filter(e -> !loopEvents.contains(e)).map(e -> e.getName().toLowerCase() + "EventCount")
.collect(Collectors.joining(" + "));
validityConstraints.add(left + " = " + right);
});
return validityConstraints;
}
public static Set<Enumerator> getPossibleEventsFor(final BTFEntityType entityType) {
final Set<Enumerator> result = new LinkedHashSet<>(BTFCountMetric.getInvolvedBTFEventsForEntityType(entityType));
Stream.of(values()).map(s -> s.entityType2InOutEvents.get(entityType))
.filter(Objects::nonNull).flatMap(e -> Stream.concat(e.getKey().stream(), e.getValue().stream())).distinct()
.forEach(result::add);
return result;
}
}