Importieren einer CSV-Datei¶
In diesem Beispiel geht es um einen Workflow zum Import von CSV-Dateien.
Zuerst sollen in einem Verzeichnis nacheinander alle *.csv
Dateien eingelesen und
im Anschluß jede Zeile der eingelesenen Datei in ein anderes Verzeichnis abgelegt werden.
Der Workflow sieht folgendermassen aus:
Zum Schutz vor der Verarbeitung, wird die Datei im Schritt readfile
nach der Identifizierung umbenannt.
Im Schritt archived
wird die Importdatei gelöscht.
Eine Archivierung der CSV-Datei kann optional hinzugefügt werden.
Container definieren¶
Als erstes wird eine Container-Klasse definiert. Ein Objekt dieser Klasse definiert den Status und enthält alle Informationen.
class Import extends \Alvine\Core\Alvine implements \Alvine\Application\Workflow\Container {
use \Alvine\Application\Workflow\Container\Implementation;
}
Aktion definieren¶
Als nächstes muss die eigentliche Aktion definiert werden. Hier soll für jede Zeile
in der CSV eine eigene Datei in ein anderes Verzeichnis /tmp/separat/
geschrieben werden.
Alternativ können die Daten auch direkt in eine Datenbank geschrieben oder andersweitig verarbeitet werden.
class SeparateAction extends \Alvine\Core\Alvine
implements \Alvine\Application\Workflow\Action {
public function run
(\Alvine\Application\Workflow\Container $container):
\Alvine\Application\Workflow\Container {
/** Ausgabeverzeichnis definieren und falls nicht vorhanden anlegen */
$dir=\Alvine\IO\File\TemporaryDirectory::getSystemDirectory()
->addChild('separat');
$dir->create();
/** Alle Einträge durchgehen */
foreach($container->rows AS $i=> $row) {
$j=0;
/** Verfügbaren Dateinamen ermitteln */
while(true) {
$fn='out-'.$i.'-'.$j++.'.csv';
$file=new \Alvine\IO\File\File($fn, $dir);
if(!$file->exists()) break;
}
/** Datei anlegen */
(new \Alvine\IO\CsvWriter($file->getOutputStream()))
->writeRow($row);
}
return $container;
}
public static function getInstanceFromParameterMap
(\Alvine\Types\Map\ParameterMap $data):
\Alvine\Application\Workflow\Action {
return new static();
}
}
XML einlesen und Workflow erstellen¶
Die XML wird eingelesen und verarbeitet.
$processor=(new \Alvine\Application\Workflow\Parser\XMLParser)->parse($xml);
Das Ergebnis ist eine Instanzen des Processors.
Einen neuen Container erstellen¶
Über die Factory-Methode wird ein neuer Container erstellt.
$container=$processor->create();
Workflow Automatisierung¶
Die Definition der Automatisierung sorgt dafür, das der gesamte Workflow durchlaufen wird.
Ausgabe der Containerinformationen¶
echo (string) $container;
Das Ergebnis des Workflows ist ein Container im Status archived
.
ID : 62f96686-b310-4d15-8a45-f51a5272eda0
State : archived
roundtrip : 3
⬤ 2019-06-01 10:00:00 import-csv
▶ container created
▷ 2019-06-01 10:00:00 import-csv ⬤ ▬▶ created
▶ container state changed from to created
⬗ 2019-06-01 10:00:00 import-csv
▶ importe file /tmp/import/a4.csv.
▷ 2019-06-01 10:00:00 import-csv created ▬▶ readfile
▶ container state changed from created to readfile
▷ 2019-06-01 10:00:00 import-csv readfile ▬▶ separated
▶ container state changed from readfile to separated
⬗ 2019-06-01 10:00:00 import-csv
▶ imported file /tmp/import/11cef568-fc73-4529-e195-5b4a7d2ce7e0 deleted.
▷ 2019-06-01 10:00:00 import-csv separated ▬▶ archived
▶ container state changed from separated to archived
Man sieht in dem Beispiel gut die einzelnen Übergänge und Aktionen.
XML-Datei¶
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Definition des Workflows -->
<workflow name="import-csv">
<admission state="created"
container-class="\MyNamespace\Import" />
<states>
<state name="created" />
<state name="readfile" />
<state name="separated" />
<state name="archived" />
</states>
<steps>
<step name="readfile">
<actions>
<!-- Daten einlesen -->
<action class="\Alvine\Application\Workflow\Action\File\ImportCsv">
<parameters>
<parameter
name="path">/tmp/import/</parameter>
<parameter
name="extension">csv</parameter>
</parameters>
</action>
</actions>
</step>
<step name="separate">
<actions>
<!-- Einzelne Datensätze separieren -->
<action class="\MyNamespace\SeparateAction" />
</actions>
</step>
<step name="archive">
<actions>
<action class="\Alvine\Application\Workflow\Action\File\DeleteImported" />
</actions>
</step>
</steps>
<automation>
<rules>
<!-- Wurde ein leerer Container erstellt, so soll er
in den Status readfile überführt werden -->
<rule name="created"
on="\Alvine\Application\Workflow\Event\Created">
<actions>
<action class="\Alvine\Application\Workflow\Automation\Action\DoTransition">
<parameters>
<parameter
name="transition">createdToReadfile</parameter>
</parameters>
</action>
</actions>
</rule>
<rule name="handle-transistion-1"
on="\Alvine\Application\Workflow\Event\EndTransition">
<conditions>
<condition class="\Alvine\Application\Workflow\Automation\Condition\IsState">
<parameters>
<parameter
name="state">readfile</parameter>
</parameters>
</condition>
</conditions>
<actions>
<action class="\Alvine\Application\Workflow\Automation\Action\DoTransition">
<parameters>
<parameter
name="transition">readfileToSeparated</parameter>
</parameters>
</action>
</actions>
</rule>
<rule name="handle-transistion-2"
on="\Alvine\Application\Workflow\Event\EndTransition">
<conditions>
<condition
class="\Alvine\Application\Workflow\Automation\Condition\IsState">
<parameters>
<parameter
name="state">separated</parameter>
</parameters>
</condition>
</conditions>
<actions>
<action class="\Alvine\Application\Workflow\Automation\Action\DoTransition">
<parameters>
<parameter
name="transition">separatedToArchived</parameter>
</parameters>
</action>
</actions>
</rule>
</rules>
</automation>
<transitions>
<transition name="createdToReadfile"
from="created"
to="readfile"
with="readfile" />
<transition name="readfileToSeparated"
from="readfile"
to="separated"
with="separate" />
<transition name="separatedToArchived"
from="separated"
to="archived"
with="archive" />
</transitions>
</workflow>