Skip to content

Commit

Permalink
Merge pull request #21 from valb3r/feature/FBP-6-persistence-to-xml-s…
Browse files Browse the repository at this point in the history
…upport

Feature/fbp 6 persistence to xml support
  • Loading branch information
valb3r committed May 15, 2020
2 parents da028a8 + aacd0a9 commit 790ce27
Show file tree
Hide file tree
Showing 20 changed files with 854 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.valb3r.bpmn.intellij.plugin

import com.intellij.psi.PsiFile
import com.intellij.ui.EditorTextField
import com.valb3r.bpmn.intellij.plugin.events.setUpdateEventsRegistry
import com.valb3r.bpmn.intellij.plugin.events.updateEventsRegistry
import com.valb3r.bpmn.intellij.plugin.flowable.parser.FlowableObjectFactory
import com.valb3r.bpmn.intellij.plugin.flowable.parser.FlowableParser
Expand All @@ -13,13 +14,14 @@ import javax.swing.JTable

class CanvasBuilder {

private val updateEvents = updateEventsRegistry()
private var newObjectsFactory: NewElementsProvider? = null

fun build(properties: JTable, editorFactory: (value: String) -> EditorTextField, canvas: Canvas, bpmnFile: PsiFile) {
updateEvents.reset()
val parser = FlowableParser()
setUpdateEventsRegistry(parser, bpmnFile.virtualFile)
updateEventsRegistry().reset()
bpmnFile.virtualFile.inputStream.use {
val process = FlowableParser().parse(it)
val process = parser.parse(it)
newObjectsFactory = newElementsFactory(FlowableObjectFactory())
canvas.reset(properties, editorFactory, process.toView(newObjectsFactory!!), BpmnProcessRenderer())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@ import com.valb3r.bpmn.intellij.plugin.bpmn.api.bpmn.BpmnElementId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.bpmn.elements.WithBpmnId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.diagram.DiagramElementId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.diagram.elements.ShapeElement
import com.valb3r.bpmn.intellij.plugin.bpmn.api.events.*
import com.valb3r.bpmn.intellij.plugin.bpmn.api.info.Property
import com.valb3r.bpmn.intellij.plugin.bpmn.api.info.PropertyType
import com.valb3r.bpmn.intellij.plugin.render.EdgeElementState
import com.valb3r.bpmn.intellij.plugin.render.WaypointElementState

data class StringValueUpdatedEvent(override val bpmnElementId: BpmnElementId, override val property: PropertyType, val newValue: String): PropertyUpdateWithId
data class StringValueUpdatedEvent(override val bpmnElementId: BpmnElementId, override val property: PropertyType, override val newValue: String): PropertyUpdateWithId

data class BooleanValueUpdatedEvent(override val bpmnElementId: BpmnElementId, override val property: PropertyType, val newValue: Boolean): PropertyUpdateWithId
data class BooleanValueUpdatedEvent(override val bpmnElementId: BpmnElementId, override val property: PropertyType, override val newValue: Boolean): PropertyUpdateWithId

data class DraggedToEvent(override val diagramElementId: DiagramElementId, override val dx: Float, override val dy: Float): LocationUpdateWithId
data class DraggedToEvent(override val diagramElementId: DiagramElementId, override val dx: Float, override val dy: Float, override val parentElementId: DiagramElementId?, override val internalPos: Int?): LocationUpdateWithId

data class NewWaypointsEvent(override val edgeElementId: DiagramElementId, override val waypoints: List<WaypointElementState>): NewWaypoints
data class NewWaypointsEvent(override val edgeElementId: DiagramElementId, override val waypoints: List<IdentifiableWaypoint>, override val epoch: Int): NewWaypoints

data class DiagramElementRemovedEvent(override val elementId: DiagramElementId): DiagramElementRemoved

data class BpmnElementRemovedEvent(override val elementId: BpmnElementId): BpmnElementRemoved

data class BpmnShapeObjectAddedEvent(override val bpmnObject: WithBpmnId, override val shape: ShapeElement, override val props: Map<PropertyType, Property>): BpmnShapeObjectAdded

data class BpmnEdgeObjectAddedEvent(override val bpmnObject: WithBpmnId, override val edge: EdgeElementState, override val props: Map<PropertyType, Property>): BpmnEdgeObjectAdded
data class BpmnEdgeObjectAddedEvent(override val bpmnObject: WithBpmnId, override val edge: EdgeWithIdentifiableWaypoints, override val props: Map<PropertyType, Property>): BpmnEdgeObjectAdded

data class CommittedToFile(val eventCount: Int): Event
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package com.valb3r.bpmn.intellij.plugin.events

import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.vfs.VirtualFile
import com.valb3r.bpmn.intellij.plugin.bpmn.api.BpmnParser
import com.valb3r.bpmn.intellij.plugin.bpmn.api.bpmn.BpmnElementId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.diagram.DiagramElementId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.events.Event
import com.valb3r.bpmn.intellij.plugin.bpmn.api.events.EventOrder
import com.valb3r.bpmn.intellij.plugin.bpmn.api.events.LocationUpdateWithId
import com.valb3r.bpmn.intellij.plugin.bpmn.api.events.PropertyUpdateWithId
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.atomic.AtomicLong
import java.util.concurrent.atomic.AtomicReference

private val updateEvents = AtomicReference<ProcessModelUpdateEvents>()

fun updateEventsRegistry(): ProcessModelUpdateEvents {
return updateEvents.updateAndGet {
if (null == it) {
return@updateAndGet ProcessModelUpdateEvents(CopyOnWriteArrayList())
}
fun setUpdateEventsRegistry(parser: BpmnParser, file: VirtualFile) {
updateEvents.set(ProcessModelUpdateEvents(parser, file, CopyOnWriteArrayList()))
}

return@updateAndGet it
}
fun updateEventsRegistry(): ProcessModelUpdateEvents {
return updateEvents.get()!!
}

// Global singleton
class ProcessModelUpdateEvents(private val updates: MutableList<Order<out Event>>) {
class ProcessModelUpdateEvents(private val parser: BpmnParser, private val file: VirtualFile, private val updates: MutableList<Order<out Event>>) {

private val order: AtomicLong = AtomicLong()
private val fileCommitListeners: MutableList<Any> = ArrayList()
Expand All @@ -46,48 +53,68 @@ class ProcessModelUpdateEvents(private val updates: MutableList<Order<out Event>
}

fun commitToFile() {
val lastCommit = updates.filter { it.event is CommittedToFile }.maxBy { it.order }
val bos = ByteArrayOutputStream()
file.inputStream.use {input ->
parser.update(input, bos, updates.filter { it.order > (lastCommit?.order ?: -1) }.map { it.event })
}
val toStore = Order(order.getAndIncrement(), CommittedToFile(0))
updates.add(toStore)

WriteAction.run<IOException> {
file.getOutputStream(null).use {
it.write(bos.toByteArray())
}
}
}

fun addPropertyUpdateEvent(event: PropertyUpdateWithId) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
propertyUpdatesByStaticId.computeIfAbsent(event.bpmnElementId) { CopyOnWriteArrayList() } += toStore
commitToFile()
}

fun addLocationUpdateEvent(event: LocationUpdateWithId) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
locationUpdatesByStaticId.computeIfAbsent(event.diagramElementId) { CopyOnWriteArrayList() } += toStore
commitToFile()
}

fun addWaypointStructureUpdate(event: NewWaypointsEvent) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
parentCreatesByStaticId.computeIfAbsent(event.edgeElementId) { CopyOnWriteArrayList() } += toStore
commitToFile()
}

fun addElementRemovedEvent(event: DiagramElementRemovedEvent) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
deletionsByStaticId.computeIfAbsent(event.elementId) { CopyOnWriteArrayList() } += toStore
commitToFile()
}

fun addElementRemovedEvent(event: BpmnElementRemovedEvent) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
deletionsByStaticBpmnId.computeIfAbsent(event.elementId) { CopyOnWriteArrayList() } += toStore
commitToFile()
}

fun addObjectEvent(event: BpmnShapeObjectAddedEvent) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
newShapeElements.add(toStore)
commitToFile()
}

fun addObjectEvent(event: BpmnEdgeObjectAddedEvent) {
val toStore = Order(order.getAndIncrement(), event)
updates.add(toStore)
newDiagramElements.add(toStore)
commitToFile()
}

fun currentPropertyUpdateEventList(elementId: BpmnElementId): List<EventOrder<PropertyUpdateWithId>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,27 @@ import com.valb3r.bpmn.intellij.plugin.events.BooleanValueUpdatedEvent
import com.valb3r.bpmn.intellij.plugin.events.StringValueUpdatedEvent
import com.valb3r.bpmn.intellij.plugin.events.updateEventsRegistry
import com.valb3r.bpmn.intellij.plugin.ui.components.FirstColumnReadOnlyModel
import java.awt.event.FocusEvent
import java.awt.event.FocusListener
import javax.swing.JTable

class PropertiesVisualizer(val table: JTable, val editorFactory: (value: String) -> EditorTextField) {

private val updateRegistry = updateEventsRegistry()
private var listenersForCurrentView: MutableList<(() -> Unit)> = mutableListOf()

@Synchronized
fun clear() {
// fire de-focus to move changes to memory, component listeners doesn't seem to work with EditorTextField
listenersForCurrentView.forEach { it() }
listenersForCurrentView.clear()

// drop and re-create table model
val model = FirstColumnReadOnlyModel()
model.addColumn("")
model.addColumn("")
table.model = model
table.columnModel.getColumn(1).preferredWidth = 500
model.fireTableDataChanged()
}

@Synchronized
fun visualize(bpmnElementId: BpmnElementId, properties: Map<PropertyType, Property>) {
// fire de-focus to move changes to memory, component listeners doesn't seem to work with EditorTextField
Expand Down Expand Up @@ -51,7 +63,7 @@ class PropertiesVisualizer(val table: JTable, val editorFactory: (value: String)

listenersForCurrentView.add {
if (initialValue != field.text) {
updateRegistry.addPropertyUpdateEvent(StringValueUpdatedEvent(bpmnElementId, type, field.text))
updateEventsRegistry().addPropertyUpdateEvent(StringValueUpdatedEvent(bpmnElementId, type, field.text))
}
}
return field
Expand All @@ -64,7 +76,7 @@ class PropertiesVisualizer(val table: JTable, val editorFactory: (value: String)

listenersForCurrentView.add {
if (initialValue != field.isSelected) {
updateRegistry.addPropertyUpdateEvent(StringValueUpdatedEvent(bpmnElementId, type, field.text))
updateEventsRegistry().addPropertyUpdateEvent(BooleanValueUpdatedEvent(bpmnElementId, type, field.isSelected))
}
}
return field
Expand All @@ -88,7 +100,7 @@ class PropertiesVisualizer(val table: JTable, val editorFactory: (value: String)
val initialValue = field.text
listenersForCurrentView.add {
if (initialValue != field.text) {
updateRegistry.addPropertyUpdateEvent(StringValueUpdatedEvent(bpmnElementId, type, removeQuotes(field.text)))
updateEventsRegistry().addPropertyUpdateEvent(StringValueUpdatedEvent(bpmnElementId, type, removeQuotes(field.text)))
}
}
}
Expand All @@ -98,29 +110,18 @@ class PropertiesVisualizer(val table: JTable, val editorFactory: (value: String)
}

private fun lastStringValueFromRegistry(bpmnElementId: BpmnElementId, type: PropertyType): String? {
return (updateRegistry.currentPropertyUpdateEventList(bpmnElementId)
return (updateEventsRegistry().currentPropertyUpdateEventList(bpmnElementId)
.map { it.event }
.filter { it.property.id == type.id }
.lastOrNull { it is StringValueUpdatedEvent } as StringValueUpdatedEvent?)
?.newValue
}

private fun lastBooleanValueFromRegistry(bpmnElementId: BpmnElementId, type: PropertyType): Boolean? {
return (updateRegistry.currentPropertyUpdateEventList(bpmnElementId)
return (updateEventsRegistry().currentPropertyUpdateEventList(bpmnElementId)
.map { it.event }
.filter { it.property.id == type.id }
.lastOrNull { it is BooleanValueUpdatedEvent } as BooleanValueUpdatedEvent?)
?.newValue
}

private class FocusEventListener(val onFocusLost: ((e: FocusEvent?) -> Unit)): FocusListener {

override fun focusLost(e: FocusEvent?) {
onFocusLost(e)
}

override fun focusGained(e: FocusEvent?) {
// NOP
}
}
}
Loading

0 comments on commit 790ce27

Please sign in to comment.