Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract the application core from infrastructure #20

Merged
merged 7 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import pl.itrack.airqeye.store.dataclient.luftdaten.model.Location;
import pl.itrack.airqeye.store.measurement.entity.Address;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.Address;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class)
interface AddressMapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import pl.itrack.airqeye.store.dataclient.luftdaten.model.LuftdatenMeasurement;
import pl.itrack.airqeye.store.measurement.entity.Installation;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.Installation;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class,
uses = {LocationMapper.class, AddressMapper.class, SensorMapper.class})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import pl.itrack.airqeye.store.measurement.entity.Location;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.Location;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class)
interface LocationMapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
import org.mapstruct.Mapping;
import pl.itrack.airqeye.store.dataclient.luftdaten.model.LuftdatenMeasurement;
import pl.itrack.airqeye.store.dataclient.luftdaten.model.SensorData;
import pl.itrack.airqeye.store.measurement.entity.Measurement;
import pl.itrack.airqeye.store.measurement.enumeration.Country;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.Measurement;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Country;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class,
uses = {MeasurementValueMapper.class, InstallationMapper.class})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import pl.itrack.airqeye.store.dataclient.luftdaten.model.SensorData;
import pl.itrack.airqeye.store.measurement.entity.MeasurementValue;
import pl.itrack.airqeye.store.measurement.enumeration.MeasurementType;
import pl.itrack.airqeye.store.measurement.enumeration.MeasurementUnit;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.MeasurementValue;
import pl.itrack.airqeye.store.measurement.domain.enumeration.MeasurementType;
import pl.itrack.airqeye.store.measurement.domain.enumeration.MeasurementUnit;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class)
interface MeasurementValueMapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import pl.itrack.airqeye.store.measurement.entity.Sensor;
import pl.itrack.airqeye.store.measurement.mapper.DefaultMapperConfig;
import pl.itrack.airqeye.store.measurement.domain.model.Sensor;
import pl.itrack.airqeye.store.measurement.infrastructure.mapper.DefaultMapperConfig;

@Mapper(config = DefaultMapperConfig.class)
interface SensorMapper {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
package pl.itrack.airqeye.store.dataclient.luftdaten.service;

import java.util.List;
import java.util.function.Supplier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pl.itrack.airqeye.store.dataclient.luftdaten.LuftdatenClient;
import pl.itrack.airqeye.store.dataclient.luftdaten.mapper.MeasurementMapper;
import pl.itrack.airqeye.store.measurement.entity.Measurement;
import pl.itrack.airqeye.store.measurement.enumeration.Feeder;
import pl.itrack.airqeye.store.measurement.service.HasUpdatableDataFeed;
import pl.itrack.airqeye.store.measurement.service.MeasurementService;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Feeder;
import pl.itrack.airqeye.store.measurement.domain.model.Measurement;
import pl.itrack.airqeye.store.measurement.domain.service.HasUpdatableDataFeed;
import pl.itrack.airqeye.store.measurement.infrastructure.service.MeasurementServiceAdapter;

@Transactional
@Service
public class LuftdatenService implements HasUpdatableDataFeed {

private LuftdatenClient luftdatenClient;

private MeasurementMapper measurementMapper;

private MeasurementService measurementService;
private MeasurementServiceAdapter measurementService;

public LuftdatenService(
final LuftdatenClient luftdatenClient,
final MeasurementMapper measurementMapper,
final MeasurementService measurementService) {
final MeasurementServiceAdapter measurementService) {
this.luftdatenClient = luftdatenClient;
this.measurementMapper = measurementMapper;
this.measurementService = measurementService;
}

// TODO: Data should be separately retrieved and persisted by some background job.
@Override
@Transactional
public void refreshDataIfRequired() {
final Supplier<List<Measurement>> luftdatenFeed = this::retrieveData;
measurementService.refreshDataIfRequired(luftdatenFeed, Feeder.LUFTDATEN);
}

/**
* Calls Luftdaten data feed and converts retrieved data to entities ready for persistence.
*
* @return list of measurements
*/
@Override
@Transactional(readOnly = true)
List<Measurement> retrieveData() {
public List<Measurement> retrieveData() {
return measurementMapper.fromDtos(luftdatenClient.getMeasurements());
}

@Override
public MeasurementServiceAdapter getMeasurementService() {
return measurementService;
}

@Override
public Feeder getFeederType() {
return Feeder.LUFTDATEN;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package pl.itrack.airqeye.store.measurement.domain.config;

public interface MeasurementProperties {

int getUpdateFrequencyInMinutes();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package pl.itrack.airqeye.store.measurement.enumeration;
package pl.itrack.airqeye.store.measurement.domain.enumeration;

import java.util.Arrays;
import java.util.stream.Stream;

public enum Country {
AE, AL, AR, AT, AU, BA, BE, BG, BO, BY, CA, CD, CH, CL, CN, CR, CY, CZ, DE, DK, DO, ES, FI, FR,
Expand All @@ -14,7 +14,7 @@ public enum Country {
* @return true if success, otherwise false
*/
public static boolean contains(final String testedValue) {
return Arrays.stream(values())
return Stream.of(values())
.map(Enum::name)
.anyMatch(code -> code.equals(testedValue));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pl.itrack.airqeye.store.measurement.domain.enumeration;

public enum Feeder {
LUFTDATEN, AIRLY, ARMAAG, GIOS
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.enumeration;
package pl.itrack.airqeye.store.measurement.domain.enumeration;

public enum MeasurementType {
PM1, PM25, PM10, PRESSURE, HUMIDITY, TEMPERATURE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.enumeration;
package pl.itrack.airqeye.store.measurement.domain.enumeration;

/**
* Units: °C, µg/m3.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pl.itrack.airqeye.store.measurement.domain.enumeration;

public enum Province {
POMORSKIE // TODO: add the rest
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import javax.persistence.Column;
import javax.persistence.Embeddable;
Expand All @@ -7,8 +7,8 @@
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import pl.itrack.airqeye.store.measurement.enumeration.Country;
import pl.itrack.airqeye.store.measurement.enumeration.Province;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Country;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Province;

@Data
@Builder
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.ArrayList;
Expand All @@ -21,7 +21,7 @@
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import pl.itrack.airqeye.store.measurement.enumeration.Feeder;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Feeder;

@Data
@Builder(toBuilder = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import javax.persistence.Column;
import javax.persistence.Embeddable;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.time.LocalDateTime;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.Column;
Expand All @@ -12,8 +12,8 @@
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import pl.itrack.airqeye.store.measurement.enumeration.MeasurementType;
import pl.itrack.airqeye.store.measurement.enumeration.MeasurementUnit;
import pl.itrack.airqeye.store.measurement.domain.enumeration.MeasurementType;
import pl.itrack.airqeye.store.measurement.domain.enumeration.MeasurementUnit;

@Data
@Builder(toBuilder = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pl.itrack.airqeye.store.measurement.entity;
package pl.itrack.airqeye.store.measurement.domain.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.Column;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package pl.itrack.airqeye.store.dataclient;
package pl.itrack.airqeye.store.measurement.domain.service;

import java.util.List;
import org.springframework.stereotype.Component;
import pl.itrack.airqeye.store.measurement.service.HasUpdatableDataFeed;

/**
* The component collects a list of available data feeders.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package pl.itrack.airqeye.store.measurement.domain.service;

import java.util.List;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Feeder;
import pl.itrack.airqeye.store.measurement.domain.model.Measurement;

public interface HasUpdatableDataFeed {

default void refreshDataIfRequired() {
getMeasurementService().refreshDataIfRequired(this::retrieveData, getFeederType());
}

List<Measurement> retrieveData();

MeasurementService getMeasurementService();

Feeder getFeederType();
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package pl.itrack.airqeye.store.measurement.service;
package pl.itrack.airqeye.store.measurement.domain.service;

public class InstallationNotFoundException extends RuntimeException {

InstallationNotFoundException(final Long id) {
public InstallationNotFoundException(final Long id) {
super("Could not find installation " + id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package pl.itrack.airqeye.store.measurement.domain.service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.function.Supplier;
import pl.itrack.airqeye.store.measurement.domain.config.MeasurementProperties;
import pl.itrack.airqeye.store.measurement.domain.enumeration.Feeder;
import pl.itrack.airqeye.store.measurement.domain.model.Measurement;

/**
* The main service handling the measurement related processes.
*/
public interface MeasurementService {

/**
* Retrieves measurements from all providers.
*
* @return a list of all measurements
*/
List<Measurement> retrieveMeasurements();

/**
* Provides the latest measurements related to given feeders's installation.
*
* @param stationId - related installation
* @param feeder - related data provider
* @return measurements
*/
List<Measurement> retrieveMeasurements(Long stationId, Feeder feeder);

/**
* Performs data refresh if outdated
*
* @param dataFeed - lazy data feed
* @param dataProvider - data provider (feeder)
*/
void refreshDataIfRequired(Supplier<List<Measurement>> dataFeed, Feeder dataProvider);

/**
* Checks whether data related to given feeder is outdated
*
* @param feeder - data provider
* @return true if update is required
*/
default boolean isUpdateRequired(Feeder feeder) {
LocalDateTime lastUpdateUtc = getLatestUpdate(feeder);
return LocalDateTime.now(ZoneOffset.UTC).isAfter(
lastUpdateUtc.plusMinutes(getMeasurementProperties().getUpdateFrequencyInMinutes()));
}

/**
* Finds the latest measurement date for given feeder.
*
* @param dataProvider - the feeder
* @return date time of the last measurement
*/
LocalDateTime getLatestUpdate(Feeder dataProvider);

/**
* Provides module settings specific for run environment
*
* @return measurement properties
*/
MeasurementProperties getMeasurementProperties();
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package pl.itrack.airqeye.store.measurement.adapters.config;
package pl.itrack.airqeye.store.measurement.infrastructure.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import pl.itrack.airqeye.store.measurement.domain.config.MeasurementProperties;

@Configuration
public class MeasurementProperties {
public class MeasurementPropertiesAdapter implements MeasurementProperties {

private int updateFrequencyInMinutes;

public MeasurementProperties(
public MeasurementPropertiesAdapter(
@Value("${airq-eye.update-frequency-in-minutes:10}") int updateFrequencyInMinutes) {
this.updateFrequencyInMinutes = updateFrequencyInMinutes;
}

@Override
public int getUpdateFrequencyInMinutes() {
return updateFrequencyInMinutes;
}
Expand Down
Loading