Skip to content

Commit

Permalink
#19 fix detekt issues and add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ThetaSinner committed Oct 30, 2018
1 parent 548989c commit f01f3f8
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class GraphicalAssetPersistence {
return repo.findAll()
}

/**
* Find a graphical asset by name
*
* @param name The name of the asset
* @return the asset, if found
*/
fun find(name: String): GraphicalAssetEntity? {
val asset = repo.findByName(name)
return if (asset.isPresent) asset.get() else null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@ import java.util.Optional
* Repository for storing graphical assets
*/
interface GraphicalAssetRepository : CrudRepository<GraphicalAssetEntity, Long> {
/**
* Find a graphical asset by name
*
* @param name The name of the asset
* @return the asset, if found
*/
fun findByName(name: String): Optional<GraphicalAssetEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ package org.ephyra.acropolis.report.api

import java.io.InputStream

/**
* Image source to provide images on request to the rendering process.
*/
interface IImageSource {
/**
* Get an image by its resource name
*
* @param resourceName The resource name of the image
* @return An input stream for the image data to be read from
*/
fun get(resourceName: String): InputStream
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ package org.ephyra.acropolis.report.api

import org.ephyra.acropolis.report.api.model.GraphContainer

/**
* Interface for a report runner. This interface provides the entry point into this module.
*/
interface IReportRunner {
/**
* Run a report based on the provided model
*
* @param graphContainer The container for the model to build the report from
* @param imageSource Source to allow images to be provided during the rendering process
*/
fun run(graphContainer: GraphContainer, imageSource: IImageSource)
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,78 @@
package org.ephyra.acropolis.report.api.model

/**
* Container for a graph model.
* Allows metadata to be provided with the model.
*/
class GraphContainer(
val graph: Graph
) {
private val subGraphs: MutableList<SubGraphSelector> = ArrayList()

/**
* Define a named sub-graph of the graph held by this container.
* The provided list of nodes can later be used to extract a sub-graph.
*
* @param name The name of the sub-graph
* @param includeNodes The nodes to include in the sub-graph
*/
fun defineSubgraph(name: String, includeNodes: List<Node>) {
subGraphs.add(SubGraphSelector(name, includeNodes))
}
}

/**
* Model to represent a graph, in the mathematical sense.
*/
class Graph {
private val nodes: MutableSet<Node> = HashSet()

private val edges: MutableList<Edge> = ArrayList()

/**
* Add a node to the graph
*
* @param node The node to add
*/
fun addNode(node: Node) {
nodes.add(node)
}

/**
* Add an edge between two nodes
*
* @param n1 Node to connect
* @param n2 Node to connect
*/
fun addEdge(n1: Node, n2: Node) {
edges.add(Edge(n1, n2, false))
}

/**
* Add a directed edge between two nodes
*
* @param from The source node for the edge
* @param to The sink node for the edge
*/
fun addDirectedEdge(from: Node, to: Node) {
edges.add(Edge(from, to, true))
}

/**
* Find a node by its label
*
* @param label The label to search for
* @return The node, if found
*/
fun findNode(label: String): Node? {
return nodes.find { node -> node.label == label }
}

// Only valid for di-graphs, otherwise much allow edges if incoming edges have a corresponding outgoing edge.
/**
* Find nodes, N, such that all edges which connect N to the graph, N is the source.
*
* Only valid for di-graphs, otherwise must allow edges if incoming edges have a corresponding outgoing edge.
*/
fun findSourceNodes(): HashSet<Node> {
val tempNodes = HashSet<Node>()
tempNodes.addAll(nodes)
Expand All @@ -44,10 +85,19 @@ class Graph {
return tempNodes
}

/**
* Return which ever node happens to be first.
*
* @return The first node in the graph, as it is stored
*/
fun firstNode(): Node {
return nodes.first()
}

/**
* Finds edges such that the specified node is the source, and collects the set of sink nodes
* from these edges.
*/
fun findNodesConnectedFrom(node: Node): HashSet<Node> {
val tempNodes = HashSet<Node>()
edges.forEach { edge ->
Expand All @@ -60,10 +110,16 @@ class Graph {
}
}

/**
* Model to represent a node in a graph
*/
class Node(
val label: String
)

/**
* Model to represent an edge in a graph
*/
class Edge(
val source: Node,

Expand All @@ -72,6 +128,9 @@ class Edge(
val directed: Boolean = false
)

/**
* Selector for building a sub-graph from a subset of a graph's nodes.
*/
class SubGraphSelector (
val name: String,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package org.ephyra.acropolis.report.config
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration

/**
* Configuration root for the module. By directing the Spring framework to load this class as configuration
* the entire module will be configured for use.
*/
@Configuration
@ComponentScan(basePackages = ["org.ephyra.acropolis.report.config", "org.ephyra.acropolis.report.impl"])
open class ReportConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import org.ephyra.acropolis.report.impl.render.DiagramRenderer
import org.springframework.stereotype.Component
import java.lang.IllegalStateException

/**
* Implementation of the report runner interface.
*/
@Suppress("MagicNumber")
@Component
private class ReportRunner : IReportRunner {
internal class ReportRunner : IReportRunner {
override fun run(graphContainer: GraphContainer, imageSource: IImageSource) {
println("Running report")
val depthMap = buildNodeDepth(graphContainer.graph)
Expand All @@ -28,7 +32,8 @@ private class ReportRunner : IReportRunner {
val diagramPadding = 30

val diagramWidth = 2 * diagramPadding + (maxDepth + 1) * tileWidth + maxDepth * cardSeparationHorizontal
val diagramHeight = 2 * diagramPadding + (maxCountAtDepth + 1) * tileHeight + maxCountAtDepth * cardSeparationVertical
val diagramHeight = 2 * diagramPadding + (maxCountAtDepth + 1) * tileHeight
+ maxCountAtDepth * cardSeparationVertical

val tempDepthCounts = HashMap<Int, Int>()
depthCounts.forEach { depth, count ->
Expand All @@ -41,7 +46,8 @@ private class ReportRunner : IReportRunner {

val depthCount = depthCounts[depth] ?: throw IllegalStateException("missing depth count")

val y = ((diagramHeight - 2 * diagramPadding) / depthCount) * currentDepthCount + diagramPadding - 0.5 * diagramHeight
val y = ((diagramHeight - 2 * diagramPadding) / depthCount) * currentDepthCount
+ diagramPadding - 0.5 * diagramHeight

val position = Position(
(diagramPadding + depth * cardSeparationHorizontal + depth * tileWidth).toFloat(),
Expand Down Expand Up @@ -110,6 +116,9 @@ private class ReportRunner : IReportRunner {
}
}

/**
* Represents a position on a 2D plane
*/
class Position(
val x: Float,
val y: Float
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import java.io.File
import java.lang.IllegalStateException
import javax.imageio.ImageIO

/**
* Wrapper around Java2D API operations to provide a specific set of operations for use
* in diagram rendering.
*/
@Suppress("MagicNumber")
class DiagramRenderer(
private val width: Int,

Expand All @@ -26,15 +31,30 @@ class DiagramRenderer(
target.fillRect(0, 0, width, height)
}

/**
* Add an image to the diagram at the specified coordinates
*
* @param positionX The offset of the left side of the image from the left side of the diagram
* @param positionY The offset of the top side of the image from the top side of the diagram
* @param source The source to fetch the image from
*/
fun addImage(positionX: Int, positionY: Int, source: File) {
val img = ImageIO.read(source)
target.drawImage(img, positionX, positionY, img.width, img.height, null)
}

/**
* Export the diagram to file
*
* @param outFile The file to write to
*/
fun export(outFile: File) {
ImageIO.write(targetImg, outFile.extension, outFile)
}

/**
* Draw a connection between two tiles.
*/
fun drawConnection() {
target.stroke = BasicStroke(4f)
target.color = Color.BLUE
Expand All @@ -50,6 +70,12 @@ class DiagramRenderer(
target.drawPolygon(polygon)
}

/**
* Draw a string of text onto the diagram using the given font.
*
* @param str The text to draw
* @param fontFile The file from which to load a font for use in the rendering
*/
fun drawString(str: String, fontFile: File) {
if (fontFile.extension != "ttf") {
throw IllegalStateException("Cannot use a font which is not TTF")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,11 @@ interface IGraphicalAssetService {
*/
fun findAll(): List<GraphicalAsset>

/**
* Find a graphical asset by name
*
* @param name The name of the asset to find
* @return The graphical asset, if found
*/
fun find(name: String): GraphicalAssetEntity?
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ import org.springframework.context.annotation.Configuration
* in order to configure this module correctly.
*/
@Configuration
@ComponentScan(basePackages = ["org.ephyra.acropolis.persistence.config", "org.ephyra.acropolis.report.config", "org.ephyra.acropolis.service.impl"])
@ComponentScan(basePackages = [
"org.ephyra.acropolis.persistence.config",
"org.ephyra.acropolis.report.config",
"org.ephyra.acropolis.service.impl"
])
class ServiceConfiguration
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import java.io.ByteArrayInputStream
import java.io.InputStream
import java.lang.IllegalStateException

/**
* Implementation of the image source for use with the report module.
* The implementation makes use of the graphical asset service to load requested resources from the database.
*/
@Component
class GraphicalAssetImageSource : IImageSource {
@Autowired
Expand Down

0 comments on commit f01f3f8

Please sign in to comment.