@startuml
skinparam classAttributeIconSize 0

' --- Interfaces ---
interface StreetSegmentObserver <<Interface>> {
}

interface StreetSegmentSubject <<Interface>> {
}

interface LabelManager <<Interface>> {
  + adjustHeadValue(segment : StreetSegment)
  + getLabel(intersectionID : int) : Label
}

interface CandidateLabelManager <<Interface>> {
  + getCandidateLabel() : Label
}

interface PermanentLabelManager <<Interface>> {
  + getSmallestLabel() : Label
  + makePermanent(intersectionID : int)
}

interface ShortestPathAlgorithm <<Interface>> {
  + findPath(origin : int, destination : int, net : StreetNetwork) : Map<String, StreetSegment>
  + addStreetSegmentObserver(observer : StreetSegmentObserver)
  + removeStreetSegmentObserver(observer : StreetSegmentObserver)
  + notifyStreetSegmentObservers(segmentIDs : List<String>)
}

' --- Main Classes ---

class Label {
  - permanent : boolean
  - value : double
  - id : int
  - predecessor : StreetSegment
  + Label()
  + Label(id : int)
  + adjustValue(possibleValue : double, possiblePredecessor : StreetSegment)
  + getID() : int
  + getPredecessor() : StreetSegment
  + getValue() : double
  + isPermanent() : boolean
  + makePermanent()
  + setValue(value : double)
}

class StreetNetwork {
  - intersections : List<Intersection>
  + StreetNetwork()
  + addIntersection(index : int, intersection : Intersection)
  + getIntersection(index : int) : Intersection
  + size() : int
  + createStreetNetwork(streets : Map<String, Street>) : StreetNetwork
}

abstract class AbstractLabelManager {
  # labels : Label[]
  + AbstractLabelManager(networkSize : int)
  + adjustHeadValue(segment : StreetSegment)
  + getLabel(intersectionID : int) : Label
}

class CandidateLabelList {
  + NEWEST : String = "N"
  + OLDEST : String = "O"
  - candidates : List<Integer>
  - policy : String
  + CandidateLabelList(policy : String, networkSize : int)
  + adjustHeadValue(segment : StreetSegment)
  + getCandidateLabel() : Label
}

class PermanentLabelList {
  + PermanentLabelList(networkSize : int)
  + adjustHeadValue(segment : StreetSegment)
  + getSmallestLabel() : Label
  + makePermanent(intersectionID : int)
}

class PermanentLabelHeap {
  - <<Private Attributes As Needed>>
  + PermanentLabelHeap(d : int, networkSize : int)
  + adjustHeadValue(segment : StreetSegment)
  + getSmallestLabel() : Label
  + makePermanent(intersectionID : int)
  - <<Private Methods As Needed>>
}

class PermanentLabelBuckets {
  - <<Private Attributes As Needed>>
  + PermanentLabelBuckets(networkSize : int)
  + adjustHeadValue(segment : StreetSegment)
  + getSmallestLabel() : Label
  + makePermanent(intersectionID : int)
  - <<Private Methods As Needed>>
}

abstract class AbstractShortestPathAlgorithm {
  - observers : Collection<StreetSegmentObserver>
  + AbstractShortestPathAlgorithm()
  + findPath(origin : int, destination : int, net : StreetNetwork) : Map<String, StreetSegment>
  + addStreetSegmentObserver(observer : StreetSegmentObserver)
  + removeStreetSegmentObserver(observer : StreetSegmentObserver)
  + notifyStreetSegmentObservers(segmentIDs : List<String>)
}

class LabelCorrectingAlgorithm {
  - labels : CandidateLabelManager
  + LabelCorrectingAlgorithm(labels : CandidateLabelManager)
  + findPath(origin : int, destination : int, net : StreetNetwork) : Map<String, StreetSegment>
}

class LabelSettingAlgorithm {
  - labels : PermanentLabelManager
  + LabelSettingAlgorithm(labels : PermanentLabelManager)
  + findPath(origin : int, destination : int, net : StreetNetwork) : Map<String, StreetSegment>
}

' --- GUI / Worker Classes ---

class SwingWorker<T, V> {
}

class PathFindingWorker {
}

class BackgroundTaskDialog {
}

abstract class AbstractModalDialog {
}

class "javax.swing.JDialog" as JDialog {
}

' --- Updated Relationships ---

' Correction: ShortestPathAlgorithm extends StreetSegmentSubject
StreetSegmentSubject <|-- ShortestPathAlgorithm

' Correction: PathFindingWorker implements StreetSegmentObserver
StreetSegmentObserver <|.. PathFindingWorker

' Standard Hierarchy
LabelManager <|-- CandidateLabelManager
LabelManager <|-- PermanentLabelManager
LabelManager <|.. AbstractLabelManager

AbstractLabelManager <|-- CandidateLabelList
CandidateLabelManager <|.. CandidateLabelList

AbstractLabelManager <|-- PermanentLabelList
PermanentLabelManager <|.. PermanentLabelList

AbstractLabelManager <|-- PermanentLabelHeap
PermanentLabelManager <|.. PermanentLabelHeap

AbstractLabelManager <|-- PermanentLabelBuckets
PermanentLabelManager <|.. PermanentLabelBuckets

ShortestPathAlgorithm <|.. AbstractShortestPathAlgorithm
AbstractShortestPathAlgorithm <|-- LabelCorrectingAlgorithm
AbstractShortestPathAlgorithm <|-- LabelSettingAlgorithm

SwingWorker <|-- PathFindingWorker
PathFindingWorker -> ShortestPathAlgorithm : executes
BackgroundTaskDialog -left-|> SwingWorker
AbstractModalDialog -left-|> BackgroundTaskDialog
JDialog -left-|> AbstractModalDialog

@enduml
