/
PetrinetHelper.php
113 lines (100 loc) · 4.28 KB
/
PetrinetHelper.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
namespace Tienvx\Bundle\MbtBundle\Service\Petrinet;
use Petrinet\Model\PlaceInterface as PetrinetPlaceInterface;
use Petrinet\Model\TransitionInterface as PetrinetTransitionInterface;
use SingleColorPetrinet\Builder\SingleColorPetrinetBuilder;
use SingleColorPetrinet\Model\ColorfulFactoryInterface;
use SingleColorPetrinet\Model\ColorInterface;
use SingleColorPetrinet\Model\PetrinetInterface;
use Tienvx\Bundle\MbtBundle\Model\Model\Revision\PlaceInterface;
use Tienvx\Bundle\MbtBundle\Model\Model\Revision\TransitionInterface;
use Tienvx\Bundle\MbtBundle\Model\Model\RevisionInterface;
use Tienvx\Bundle\MbtBundle\Service\ExpressionLanguage;
class PetrinetHelper implements PetrinetHelperInterface
{
public const FAKE_START_PLACE_ID = -1;
protected ColorfulFactoryInterface $colorfulFactory;
protected ExpressionLanguage $expressionLanguage;
public function __construct(ColorfulFactoryInterface $colorfulFactory, ExpressionLanguage $expressionLanguage)
{
$this->colorfulFactory = $colorfulFactory;
$this->expressionLanguage = $expressionLanguage;
}
public function build(RevisionInterface $revision): PetrinetInterface
{
$builder = new SingleColorPetrinetBuilder($this->colorfulFactory);
$places = $this->getPlaces($revision, $builder);
$transitions = $this->getTransitions($revision, $builder);
foreach ($revision->getTransitions() as $index => $transition) {
if ($transition instanceof TransitionInterface) {
if ($transition->isStart()) {
$builder->connect($places[self::FAKE_START_PLACE_ID], $transitions[$index], 1);
} else {
$this->connectPlacesToTransition(
array_intersect_key($places, array_flip($transition->getFromPlaces())),
$transitions[$index],
$builder
);
}
$this->connectTransitionToPlaces($transitions[$index], $transition->getToPlaces(), $places, $builder);
}
}
return $builder->getPetrinet();
}
protected function getPlaces(RevisionInterface $revision, SingleColorPetrinetBuilder $builder): array
{
$places = [];
$places[self::FAKE_START_PLACE_ID] = $builder->place(self::FAKE_START_PLACE_ID);
foreach ($revision->getPlaces() as $index => $place) {
if ($place instanceof PlaceInterface) {
$places[$index] = $builder->place($index);
}
}
return $places;
}
protected function getTransitions(RevisionInterface $revision, SingleColorPetrinetBuilder $builder): array
{
$transitions = [];
foreach ($revision->getTransitions() as $index => $transition) {
if ($transition instanceof TransitionInterface) {
$transitions[$index] = $builder->transition(
$transition->getGuard()
? fn (ColorInterface $color): bool => (bool) $this->expressionLanguage->evaluate(
$transition->getGuard(),
$color->getValues()
)
: null,
$transition->getExpression()
? fn (ColorInterface $color): array => (array) $this->expressionLanguage->evaluate(
$transition->getExpression(),
$color->getValues()
)
: null,
$index
);
}
}
return $transitions;
}
protected function connectPlacesToTransition(
array $places,
PetrinetTransitionInterface $transition,
SingleColorPetrinetBuilder $builder
): void {
foreach ($places as $place) {
if ($place instanceof PetrinetPlaceInterface) {
$builder->connect($place, $transition, 1);
}
}
}
protected function connectTransitionToPlaces(
PetrinetTransitionInterface $transition,
array $toPlaces,
array $places,
SingleColorPetrinetBuilder $builder
): void {
foreach ($toPlaces as $toPlace) {
$builder->connect($transition, $places[$toPlace], 1);
}
}
}