blob: d8bcf1b461767b298abec633f68e49877df13cdb [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2022 Dortmund University of Applied Sciences and Arts and others.
*
* 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
*
* Contributors:
* Dortmund University of Applied Sciences and Arts - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.amalthea.model.util.stimuli;
import java.math.BigInteger;
import org.eclipse.app4mc.amalthea.model.PeriodicBurstStimulus;
import org.eclipse.app4mc.amalthea.model.PeriodicStimulus;
import org.eclipse.app4mc.amalthea.model.PeriodicSyntheticStimulus;
import org.eclipse.app4mc.amalthea.model.RelativePeriodicStimulus;
import org.eclipse.app4mc.amalthea.model.SingleStimulus;
import org.eclipse.app4mc.amalthea.model.Stimulus;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.VariableRateStimulus;
import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
public class EventModelFactory {
/**
* Constant representing a Time object corresponding to 0ms.
*/
private static final Time ZEROMS = FactoryUtil.createTime("0ms");
// Suppress default constructor
private EventModelFactory() {
throw new IllegalStateException("Utility class");
}
public static IEventModel of(final Stimulus s) {
if (s instanceof PeriodicStimulus) {
return ofStimuli((PeriodicStimulus) s);
} else if (s instanceof PeriodicSyntheticStimulus) {
return ofStimuli((PeriodicSyntheticStimulus) s);
} else if (s instanceof RelativePeriodicStimulus) {
return ofStimuli((RelativePeriodicStimulus) s);
} else if (s instanceof PeriodicBurstStimulus) {
return ofStimuli((PeriodicBurstStimulus) s);
} else if (s instanceof SingleStimulus) {
return ofStimuli((SingleStimulus) s);
} else if (s instanceof VariableRateStimulus) {
return ofStimuli((VariableRateStimulus) s);
}
// Stimulus is not supported
return null;
}
/*********************************************************
* Factory methods for individual APP4MC stimuli
*********************************************************/
private static IEventModel ofStimuli(PeriodicStimulus s) {
EMPeriodic em = new EMPeriodic();
em.setRecurrence(s.getRecurrence());
/*
* Check if minDistance is set. If not, we are safe to initialize this variable
* with a dummy value of zero, as it will only be used as part of max functions
* (i.e. to make sure a lower bound on the distance is not exceeded)
*/
if (s.getMinDistance() == null) {
em.setMinDistance(FactoryUtil.createTime("0ms"));
} else {
em.setMinDistance(s.getMinDistance());
}
/**
* Check if jitter is is set. If not, we are safe to initialize this variable
* with a dummy value of zero, as it will only be used as in additions /
* subtractions.
*/
if (s.getJitter() == null) {
em.setJitter(FactoryUtil.createTime("0ms"));
} else {
em.setJitter(s.getJitter().getUpperBound());
}
return em;
}
private static IEventModel ofStimuli(PeriodicSyntheticStimulus s) {
EMPeriodicSynthetic em = new EMPeriodicSynthetic();
em.setOuterPeriod(s.getRecurrence());
em.setEntries(s.getOccurrenceTimes());
return em;
}
private static IEventModel ofStimuli(RelativePeriodicStimulus periodicRelative) {
EMPeriodicRelative em = new EMPeriodicRelative();
em.setLowerBoundDistance(periodicRelative.getNextOccurrence().getLowerBound());
em.setUpperBoundDistance(periodicRelative.getNextOccurrence().getUpperBound());
return em;
}
private static IEventModel ofStimuli(PeriodicBurstStimulus s) {
EMPeriodicBurst em = new EMPeriodicBurst();
// Feasibility check to prevent the creation of an invalid object that would
// cause exceptions.
if (EventModelFactory.isNullOrZero(s.getRecurrence()) || EventModelFactory.isNullOrZero(s.getBurstLength())) {
return null;
}
// Set Mandatory parameters
em.setOuterPeriod(s.getRecurrence());
em.setBurstLength(s.getBurstLength());
/*
* From APP4MC Help: The number of occurrences per burst are specified via
* occurrenceCount. The occurrenceMinDinstance defines the minimal distance
* between them. The burstLength defines the maximum time the burst pattern can
* last. If the number of occurrences multiplied with the minimum distance
* between activations is bigger than the burstLength only the number of
* activations that fit into the burstLength are executed.
*/
// Check whether or not OccurrenceCount * OccurrenceMinDistance <
// BurstLength, and limit the number of events accordingly.
// if tMinDistance != 0 && tMinDistance * (occurranceCount - 1) >
// tBurstLength
if (!EventModelFactory.isNullOrZero(s.getOccurrenceMinDistance())
&& !EventModelFactory.isNullOrZero(em.getBurstLength()) && s.getOccurrenceMinDistance()
.multiply(s.getOccurrenceCount() - (long) 1).compareTo(em.getBurstLength()) > 0) {
// OccurrenceCount * OccurrenceMinDistance > BurstLength, i.e. limit
// nb. of occurrences
em.setOccurrenceCount((int) Math.ceil(em.getBurstLength().divide(s.getOccurrenceMinDistance())));
} else {
// BurstLength is either not set, or does not constrain the nb. of
// Occurrences
em.setOccurrenceCount(s.getOccurrenceCount());
}
// Initialize optional parameter
if (s.getOccurrenceMinDistance() != null) {
em.setMinDistance(s.getOccurrenceMinDistance());
em.setDeltaBurst(em.getBurstLength().subtract(em.getMinDistance().multiply(em.getOccurrenceCount() - 1)));
} else {
em.setMinDistance(ZEROMS);
em.setDeltaBurst(ZEROMS);
}
return em;
}
@java.lang.SuppressWarnings("squid:S1172")
private static IEventModel ofStimuli(SingleStimulus singleStimulus) {
// Warnings disabled on purpose, since it is intended that neither
// singleStimulus nor em are used within this method.
@java.lang.SuppressWarnings("squid:S1488")
EMSingle em = new EMSingle();
return em;
}
private static IEventModel ofStimuli(VariableRateStimulus s) {
EMVariableRate em = new EMVariableRate();
em.setStep(s.getStep());
em.setLowerBoundOccurrences(s.getOccurrencesPerStep().getLowerBound());
em.setUpperBoundOccurrences(s.getOccurrencesPerStep().getUpperBound());
em.setAverageBoundOccurrences(s.getOccurrencesPerStep().getAverage());
return em;
}
/*********************************************************
* Utility functions used to support arithmetic operations
*********************************************************/
/**
* Returns the maximum between <a href="#{@link}">{@link Time}</a> a and b
*
* @param a
* @param b
* @return
*/
public static Time max(final Time a, final Time b) {
return (a.compareTo(b) > 0) ? a : b;
}
/**
* Returns the minimum between <a href="#{@link}">{@link Time}</a> a and b
*
* @param a
* @param b
* @return
*/
public static Time min(final Time a, final Time b) {
return (a.compareTo(b) < 0) ? a : b;
}
/**
* Returns {@code True} if the given {@link Time} is either {@code Null} or 0.
*
* @param t
* @return
*/
public static boolean isNullOrZero(final Time t) {
return (t == null || t.getValue().compareTo(BigInteger.ZERO) == 0);
}
}