com.alliander.osgp.core.application.services.EventNotificationMessageService.java Source code

Java tutorial

Introduction

Here is the source code for com.alliander.osgp.core.application.services.EventNotificationMessageService.java

Source

/**
 * Copyright 2015 Smart Society Services B.V.
 *
 * 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
 */
package com.alliander.osgp.core.application.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alliander.osgp.domain.core.entities.Device;
import com.alliander.osgp.domain.core.entities.DeviceOutputSetting;
import com.alliander.osgp.domain.core.entities.Event;
import com.alliander.osgp.domain.core.entities.RelayStatus;
import com.alliander.osgp.domain.core.entities.Ssld;
import com.alliander.osgp.domain.core.exceptions.UnknownEntityException;
import com.alliander.osgp.domain.core.repositories.DeviceRepository;
import com.alliander.osgp.domain.core.repositories.EventRepository;
import com.alliander.osgp.domain.core.repositories.SsldRepository;
import com.alliander.osgp.domain.core.valueobjects.EventType;
import com.alliander.osgp.domain.core.valueobjects.RelayType;
import com.alliander.osgp.dto.valueobjects.EventNotificationDto;

@Service
@Transactional
public class EventNotificationMessageService {

    private static final Logger LOGGER = LoggerFactory.getLogger(EventNotificationMessageService.class);

    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private EventRepository eventRepository;

    @Autowired
    private SsldRepository ssldRepository;

    @Transactional(value = "transactionManager")
    public void handleEvent(final String deviceIdentification, final Date dateTime, final EventType eventType,
            final String description, final Integer index) throws UnknownEntityException {

        // Lookup device
        final Device device = this.deviceRepository.findByDeviceIdentification(deviceIdentification);

        if (device != null) {
            // If the event belonged to an existing device, then save it,
            // otherwise don't.
            this.eventRepository.save(new Event(device, dateTime, eventType, description, index));

            // Checking to see if it was a switching event
            if (eventType.equals(EventType.LIGHT_EVENTS_LIGHT_ON)
                    || eventType.equals(EventType.LIGHT_EVENTS_LIGHT_OFF)
                    || eventType.equals(EventType.TARIFF_EVENTS_TARIFF_ON)
                    || eventType.equals(EventType.TARIFF_EVENTS_TARIFF_OFF)) {
                this.handleSwitchingEvent(device, eventType, index);
            }

        } else {
            throw new UnknownEntityException(Device.class, deviceIdentification);
        }
    }

    @Transactional(value = "transactionManager")
    public void handleEvents(final String deviceIdentification, final List<EventNotificationDto> eventNotifications)
            throws UnknownEntityException {

        final Device device = this.deviceRepository.findByDeviceIdentification(deviceIdentification);
        if (device == null) {
            throw new UnknownEntityException(Device.class, deviceIdentification);
        }

        /*
         * A list of bundled events may contain events that occurred over a
         * period of time (and as such may contain multiple switching events per
         * relay). Handling light switching events, only update the relay status
         * once for the last switching in the list.
         */

        final List<Event> lightSwitchingEvents = new ArrayList<>();

        for (final EventNotificationDto eventNotification : eventNotifications) {

            final EventType eventType = EventType.valueOf(eventNotification.getEventType().name());
            final Event event = new Event(device, eventNotification.getDateTime().toDate(), eventType,
                    eventNotification.getDescription(), eventNotification.getIndex());
            this.eventRepository.save(event);

            if (eventType.equals(EventType.LIGHT_EVENTS_LIGHT_ON)
                    || eventType.equals(EventType.LIGHT_EVENTS_LIGHT_OFF)) {
                lightSwitchingEvents.add(event);
            }
        }

        this.handleLightSwitchingEvents(device, lightSwitchingEvents);
    }

    private void handleLightSwitchingEvents(final Device device, final List<Event> lightSwitchingEvents) {

        if (lightSwitchingEvents.isEmpty()) {
            return;
        }

        final Map<Integer, RelayStatus> lastRelayStatusPerIndex = new TreeMap<>();
        final Set<Integer> indexesLightRelays = new TreeSet<>();
        final Ssld ssld = this.ssldRepository.findOne(device.getId());
        for (final DeviceOutputSetting deviceOutputSetting : ssld.getOutputSettings()) {
            if (deviceOutputSetting.getOutputType().equals(RelayType.LIGHT)) {
                indexesLightRelays.add(deviceOutputSetting.getExternalId());
            }
        }

        for (final Event lightSwitchingEvent : lightSwitchingEvents) {
            final Date switchingTime = lightSwitchingEvent.getDateTime();
            final Integer index = lightSwitchingEvent.getIndex();
            final Set<Integer> switchIndexes = new TreeSet<>();
            if (index == 0) {
                switchIndexes.addAll(indexesLightRelays);
            } else {
                switchIndexes.add(index);
            }
            for (final Integer relayIndex : switchIndexes) {
                final boolean lightsOn = EventType.LIGHT_EVENTS_LIGHT_ON.equals(lightSwitchingEvent.getEventType());
                if (lastRelayStatusPerIndex.get(index) == null
                        || switchingTime.after(lastRelayStatusPerIndex.get(index).getLastKnowSwitchingTime())) {
                    lastRelayStatusPerIndex.put(index,
                            new RelayStatus(device, relayIndex, lightsOn, switchingTime));
                }
            }
        }

        if (!lastRelayStatusPerIndex.isEmpty()) {
            ssld.updateRelayStatusses(lastRelayStatusPerIndex);
            this.deviceRepository.save(device);
        }
    }

    private void handleSwitchingEvent(final Device device, final EventType eventType, final int index) {

        // if the index == 0 handle all LIGHT relays, otherwise just handle the
        // index
        if (index == 0) {
            final Ssld ssld = this.ssldRepository.findOne(device.getId());
            for (final DeviceOutputSetting deviceOutputSetting : ssld.getOutputSettings()) {
                if (deviceOutputSetting.getOutputType().equals(RelayType.LIGHT)) {
                    this.updateRelayStatus(deviceOutputSetting.getExternalId(), device, eventType);
                }
            }
        } else {
            this.updateRelayStatus(index, device, eventType);
        }

        this.deviceRepository.save(device);
    }

    private void updateRelayStatus(final int index, final Device device, final EventType eventType) {

        final boolean isRelayOn = EventType.LIGHT_EVENTS_LIGHT_ON.equals(eventType)
                || EventType.TARIFF_EVENTS_TARIFF_ON.equals(eventType);

        // Only handle the event if the relay doesn't have a status yet, or
        // if the state changed
        final Ssld ssld = this.ssldRepository.findOne(device.getId());
        if ((ssld.getRelayStatusByIndex(index) == null)
                || (ssld.getRelayStatusByIndex(index).isLastKnownState() != isRelayOn)) {
            LOGGER.info("Handling new event {} for device {} to update the relay status for index {}.",
                    eventType.name(), device.getDeviceIdentification(), index);

            ssld.updateRelayStatusByIndex(index,
                    new RelayStatus(device, index, isRelayOn, DateTime.now().toDate()));
        }
    }
}