package rocks.inspectit.server.ci.event; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; import org.apache.commons.collections.CollectionUtils; import org.springframework.context.ApplicationEvent; import rocks.inspectit.server.util.CollectionSubtractUtils; import rocks.inspectit.shared.cs.ci.Profile; import rocks.inspectit.shared.cs.ci.assignment.AbstractClassSensorAssignment; import rocks.inspectit.shared.cs.ci.profile.data.AbstractProfileData; import rocks.inspectit.shared.cs.ci.profile.data.SensorAssignmentProfileData; /** * Event that signals that an {@link Profile} has been updated via CI. * * @author Ivan Senic * */ public class ProfileUpdateEvent extends ApplicationEvent { /** * Generated UID. */ private static final long serialVersionUID = 1040042583468927682L; /** * Profile before updating. */ private final Profile before; /** * Profile after updating. */ private final Profile after; /** * Default constructor. * * @param source * the component that published the event (never {@code null}) * @param before * Profile before updating. * @param after * Profile after updated. */ public ProfileUpdateEvent(Object source, Profile before, Profile after) { super(source); // check null if ((null == before) || (null == after)) { throw new IllegalArgumentException("Profile references must not be null."); } // check same id if (!Objects.equals(before.getId(), after.getId())) { throw new IllegalArgumentException("Before and after profile references must have same profile id."); } this.before = before; this.after = after; } /** * Returns id of the profile being updated. * * @return Returns id of the profile being updated. */ public String getProfileId() { return after.getId(); } /** * Returns if the profile is active. * * @return Returns if the profile is active. */ public boolean isProfileActive() { return after.isActive(); } /** * If profile was deactivated as the result of the update action. * * @return If profile was deactivated as the result of the update action. */ public boolean isProfileDeactivated() { return before.isActive() && !after.isActive(); } /** * If profile was activated as the result of the update action. * * @return If profile was activated as the result of the update action. */ public boolean isProfileActivated() { return !before.isActive() && after.isActive(); } /** * Returns all {@link AbstractClassSensorAssignment} that are "removed" as result of this * update. If profile was deactivated then it means that all assignments before the update are * considered for removal. * * @return Returns all {@link AbstractClassSensorAssignment} that are "removed". */ public Collection<AbstractClassSensorAssignment<?>> getRemovedSensorAssignments() { if (isProfileDeactivated()) { // if deactivated then we consider all old assignment to be for removal return getAllSensorAssignments(before); } else if (isProfileActivated()) { // if it was activated then nothing is for removal return Collections.emptyList(); } else { // otherwise find the difference return getAssignmentsDifference(before, after); } } /** * Returns all {@link AbstractClassSensorAssignment} that are "added" as result of this update. * If profile was activated then it means that all assignments after the update are considered * for adding. * * @return Returns all {@link AbstractClassSensorAssignment} that are "removed". */ public Collection<AbstractClassSensorAssignment<?>> getAddedSensorAssignments() { if (isProfileDeactivated()) { // if it was deactivated then nothing is for adding return Collections.emptyList(); } else if (isProfileActivated()) { // if activated then we consider all new assignment to be for adding return getAllSensorAssignments(after); } else { // otherwise find the difference return getAssignmentsDifference(after, before); } } /** * Returns all {@link AbstractClassSensorAssignment}s from the profile. * * @param profile * {@link Profile} * @return Returns all {@link AbstractClassSensorAssignment}s from the profile. */ private Collection<AbstractClassSensorAssignment<?>> getAllSensorAssignments(Profile profile) { Collection<AbstractClassSensorAssignment<?>> results = new ArrayList<>(); AbstractProfileData<?> profileData = profile.getProfileData(); if (profileData.isOfType(SensorAssignmentProfileData.class)) { List<? extends AbstractClassSensorAssignment<?>> data = profileData.getData(SensorAssignmentProfileData.class); if (CollectionUtils.isNotEmpty(data)) { results.addAll(data); } } return results; } /** * Finds {@link AbstractClassSensorAssignment}s that exists in first profile and not in the * second one. * * @param p1 * First profile * @param p2 * Second profile * @return {@link AbstractClassSensorAssignment}s that exists in first profile and not in the * second one. */ private Collection<AbstractClassSensorAssignment<?>> getAssignmentsDifference(Profile p1, Profile p2) { Collection<AbstractClassSensorAssignment<?>> results1 = getAllSensorAssignments(p1); Collection<AbstractClassSensorAssignment<?>> results2 = getAllSensorAssignments(p2); return CollectionSubtractUtils.subtractSafe(results1, results2); } }