Skip to content

Commit

Permalink
Merge pull request #56 from EphyraSoftware/feature/18-text-reports
Browse files Browse the repository at this point in the history
Project reporting to text
  • Loading branch information
Sub-Xaero authored Oct 23, 2018
2 parents 056628c + 9a6dfad commit 4f771aa
Show file tree
Hide file tree
Showing 22 changed files with 422 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.ephyra.acropolis.external

import java.lang.IllegalStateException

/**
* Types for supported references in the external model
*/
Expand Down Expand Up @@ -27,13 +29,26 @@ fun extractRef(ref: String): Pair<RefType, String> {
return Pair(refType, refParts[1])
}

/**
* Pack a reference into its string format from its type and name
*/
fun packRef(refType: RefType, name: String): String {
val refTypeString = when(refType) {
RefType.APPLICATION -> "application"
RefType.SYSTEM -> "system"
}

return "$refTypeString.$name"
}

/**
* Types of supported system software specializations
*/
enum class SystemSoftwareSpecialization {
ReverseProxy,
LoadBalancer,
Queue,
Datastore,
UnknownSpecialization
}

Expand All @@ -48,6 +63,23 @@ fun extractSystemSpecialization(name: String): SystemSoftwareSpecialization {
"REVERSEPROXY" -> SystemSoftwareSpecialization.ReverseProxy
"LOADBALANCER" -> SystemSoftwareSpecialization.LoadBalancer
"QUEUE" -> SystemSoftwareSpecialization.Queue
"DATASTORE" -> SystemSoftwareSpecialization.Datastore
else -> SystemSoftwareSpecialization.UnknownSpecialization
}
}

/**
* Extracts the enumerated type from the input name.
* Unrecognised names are mapped to the UnknownSpecialization enumeration value.
*
* Note that the match against the name is NOT case-sensitive.
*/
fun packSystemSpecialization(systemSoftwareSpecialization: SystemSoftwareSpecialization): String {
return when (systemSoftwareSpecialization) {
SystemSoftwareSpecialization.ReverseProxy -> "ReverseProxy"
SystemSoftwareSpecialization.LoadBalancer -> "LoadBalancer"
SystemSoftwareSpecialization.Queue -> "Queue"
SystemSoftwareSpecialization.Datastore -> "Datastore"
else -> throw IllegalStateException("Missing conversion for specialization [$systemSoftwareSpecialization]")
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.ephyra.acropolis.external

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.ephyra.acropolis.external.model.Project
import org.slf4j.LoggerFactory
import java.io.StringWriter

/**
* Helper for working with YAML as an external format for the Acropolis external data model.
Expand All @@ -15,6 +17,9 @@ class YamlHelper {

/**
* Deserialize the input string to a project model.
*
* @param yamlData The YAML data to deserialize
* @return The external project model
*/
fun loadFromString(yamlData: String): Project? {
val mapper = ObjectMapper(YAMLFactory())
Expand All @@ -26,4 +31,24 @@ class YamlHelper {
null
}
}

/**
* Serialize the input project model to string.
*
* @param project The project to serialize
* @return The project data as a YAML formatted string
*/
fun serialize(project: Project): String? {
val mapper = ObjectMapper(YAMLFactory())
mapper.registerModule(KotlinModule())
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
return try {
val stringWriter = StringWriter()
mapper.writeValue(stringWriter, project)
String(stringWriter.buffer)
} catch (e: JsonMappingException) {
logger.error("Failed to convert project with name [${project.name}] from external model to string", e)
null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id


/**
*
* @property id Auto-generated database ID
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.ephyra.acropolis.persistence.api.entity

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
Expand All @@ -8,14 +9,13 @@ import javax.persistence.Id
/**
* The base type around which everything is centred. Acts as an entrypoint/parent scoping for all
* subsequent types and operations.
*
* @see SystemSoftwareEntity for params
*/
@Entity
class ProjectEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = 0

@Column(unique = true, length = 100)
var name: String = ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,14 @@ class ApplicationSoftwarePersistence {
fun update(applicationSoftware: ApplicationSoftwareEntity) {
repo.save(applicationSoftware)
}

/**
* Finds all application-software entities which are in the specified project.
*
* @param projectId The id of the project to search for application-software entities
* @return The list of application-software entities
*/
fun findAll(projectId: Long): List<ApplicationSoftwareEntity> {
return repo.findByProjectId(projectId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,19 @@ class SystemSoftwarePersistence {

/**
* Updates an existing database record with the details contained within the entity parameter
* @param entity the instance of the entity containing modified fields to be persisted to the database
* @param systemSoftware The instance of the entity containing modified fields to be persisted to the database
*/
fun update(systemSoftware: SystemSoftwareEntity) {
repo.save(systemSoftware)
}

/**
* Finds all system-software entities which are in the specified project.
*
* @param projectId The id of the project to search for system-software entities
* @return The list of system-software entities
*/
fun findAll(projectId: Long): List<SystemSoftwareEntity> {
return repo.findByProjectId(projectId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ internal interface ApplicationSoftwareRepository : CrudRepository<ApplicationSof
* @return An instance of ApplicationSoftwareEntity if one is found
*/
fun findByNameAndProjectId(name: String, projectId: Long): Optional<ApplicationSoftwareEntity>

/**
* Find all the applications which have the given project id.
*
* @param projectId The id of the project to search for applications in
* @return Applications which are included in the specified project
*/
fun findByProjectId(projectId: Long): List<ApplicationSoftwareEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ internal interface SystemSoftwareRepository : CrudRepository<SystemSoftwareEntit
* @return An instance of SystemSoftwareEntity if one is found
*/
fun findByNameAndProjectId(name: String, projectId: Long): Optional<SystemSoftwareEntity>

/**
* Finds all systems which belong to the project identified by projectId
*
* @param projectId The id of the project to find systems for
* @return list of systems which belong to the identified project
*/
fun findByProjectId(projectId: Long): List<SystemSoftwareEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ spring:
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
datasource:
url: 'jdbc:mysql://localhost:3306/acropolisdev'
username: root
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.ephyra.acropolis.service

import org.ephyra.acropolis.external.YamlHelper
import org.ephyra.acropolis.service.api.IExportService
import org.ephyra.acropolis.service.api.IImportService
import org.ephyra.acropolis.service.api.ImportType
import org.ephyra.acropolis.service.config.ServiceConfiguration
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension

/**
* Test that the import and export services represent a symmetric operation
*/
@ExtendWith(SpringExtension::class)
@SpringBootTest(classes = [IntegrationTestConfiguration::class, ServiceConfiguration::class])
class ImportExportRoundTripIntTest {
@Autowired
private lateinit var importService: IImportService

@Autowired
private lateinit var exportService: IExportService

/**
* Test that YAML can be symmetrically imported and exported
*/
@Test
@DisplayName("Test that YAML can be symmetrically imported and exported")
fun importExportRTT() {
val data = String(javaClass.getResourceAsStream("/round-trip-test-project.yml").readAllBytes())
importService.importProject(data, ImportType.YAML)

val yamlHelper = YamlHelper()
val originalProject = yamlHelper.loadFromString(data)
?: throw IllegalStateException("Failed to deserialize project")

val exportedData = exportService.export(originalProject.name, ImportType.YAML)

// Have to serialize the data which was loaded from file again to make sure the result will match.
val expected = yamlHelper.serialize(originalProject)

assertEquals(expected, exportedData)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: '1.0'
name: 'round trip project'
software:
applications:
- name: 'Application One'
description: 'Description for Application One'
talks_to:
- 'system.System Three - ReverseProxy'
- name: 'Application Two'
description: 'Description for Application Two'
talks_to:
- 'application.Application One'
systems:
- name: 'System One'
description: 'Description for System One'
- name: 'System Two - Queue'
description: 'Description for System Two - Queue'
specialization: Queue
talks_to:
- 'system.System One'
- name: 'System Three - ReverseProxy'
description: 'Description for System Three - ReverseProxy'
specialization: ReverseProxy
talks_to:
- 'system.System Two - Queue'
- name: 'System Four - LoadBalancer'
description: 'Description for System Four - LoadBalancer'
specialization: LoadBalancer
talks_to:
- 'system.System Two - Queue'
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ interface IApplicationSoftwareService {
*/
fun find(name: String, projectId: Long): ApplicationSoftwareEntity?

/**
* Finds all the applications which belong to a project.
*
* @param projectName The name of the project to search in for applications
* @return All the applications which belong to the specified project
*/
fun findAll(projectName: String): List<ApplicationSoftwareEntity>

/**
* Update an application software instance by saving the changes which have been made.
* to the managed entity.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ interface IConnectionService {
* Lists all the connections starting from the passed entity.
*
* @param fromConnectable The instance of a Connectanle type to get all connections from
* @param connectionType Enum constant to filter the type of connection to search for
* @return A list of all instances that have connections from the passed entity
*/
fun getConnectionsFrom(fromConnectable: IConnectable): List<IConnectable>
fun getConnectionsFrom(fromConnectable: IConnectable, connectionType: ConnectionType): List<IConnectable>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.ephyra.acropolis.service.api

/**
* Service interface for exporting project data
*/
interface IExportService {
/**
* Export a project identified by name to a specified data format.
*
* @param projectName The name of the project to export
* @param exportType The type of data format to output
* @return The data representing the exported project in the specified data format
*/
fun export(projectName: String, exportType: ImportType): String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ interface ISystemSoftwareService {
*/
fun find(name: String, projectId: Long): SystemSoftwareEntity?

/**
* Finds all the systems which belong to a project.
*
* @param projectName The name of the project to search in for systems
* @return All the systems which belong to the specified project
*/
fun findAll(projectName: String): List<SystemSoftwareEntity>

/**
* Update an application software instance by saving the changes which have been made
* to the managed entity.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ class ApplicationSoftwareService : IApplicationSoftwareService {
return persistence.findByName(name, projectId)
}

override fun findAll(projectName: String): List<ApplicationSoftwareEntity> {
val project = projectService.find(projectName)
if (project == null) {
val msg = "Could not find project with name [$projectName]"
logger.error(msg)
throw IllegalStateException(msg)
}

return persistence.findAll(project.id)
}

override fun update(applicationSoftware: ApplicationSoftwareEntity) {
persistence.update(applicationSoftware)
}
Expand Down
Loading

0 comments on commit 4f771aa

Please sign in to comment.