Files
BloomPatched/build/scripts/Targets/TargetDescriptionFiles/Services/Xml/XmlService.php

224 lines
8.1 KiB
PHP

<?php
namespace Targets\TargetDescriptionFiles\Services\Xml;
use DOMDocument;
use DOMException;
use Targets\TargetDescriptionFiles\TargetDescriptionFile;
use Targets\TargetDescriptionFiles\Avr8\Avr8TargetDescriptionFile;
use Targets\TargetDescriptionFiles\Services\Xml\Exceptions\XmlParsingException;
use Targets\TargetDescriptionFiles\TargetFamily;
require_once __DIR__ . '/FromXmlService.php';
require_once __DIR__ . '/ToXmlService.php';
require_once __DIR__ . '/../../TargetDescriptionFile.php';
require_once __DIR__ . '/../../Avr8/Avr8TargetDescriptionFile.php';
require_once __DIR__ . '/Exceptions/XmlParsingException.php';
/**
* The XmlService provides conversion of TargetDescriptionFile objects to/from XML documents.
*
* This can be used to:
* - Construct a new instance of TargetDescriptionFile, from an XML document.
* - Convert a TargetDescriptionFile instance to an XML document.
*/
class XmlService
{
private FromXmlService $fromXmlService;
private ToXmlService $toXmlService;
public function __construct(?FromXmlService $fromXmlService = null, ?ToXmlService $toXmlService = null)
{
$this->fromXmlService = $fromXmlService ?? new FromXmlService();
$this->toXmlService = $toXmlService ?? new ToXmlService();
}
/**
* Constructs a TargetDescriptionFile from the given XML document.
*
* @param DOMDocument $document
* The XML document from which to construct the TargetDescriptionFile.
*
* @return TargetDescriptionFile
* The constructed TargetDescriptionFile.
*/
public function fromXml(DOMDocument $document): TargetDescriptionFile
{
$deviceElement = $this->fromXmlService->getDeviceElement($document);
$deviceAttributesByName = $this->fromXmlService->getNodeAttributesByName($deviceElement);
$targetFamily = TargetFamily::tryFrom($deviceAttributesByName['family'] ?? null);
if (!$targetFamily instanceof TargetFamily) {
throw new XmlParsingException('Failed to resolve target family - missing/invalid family attribute');
}
$tdf = match ($targetFamily) {
TargetFamily::AVR_8 => new Avr8TargetDescriptionFile(),
default => new TargetDescriptionFile(),
};
$tdf->deviceAttributesByName = $deviceAttributesByName;
$propertyGroupElements = $this->fromXmlService->getDeviceElementsFromXPath(
'property-groups/property-group',
$document
);
foreach ($propertyGroupElements as $element) {
$tdf->propertyGroups[] = $this->fromXmlService->propertyGroupFromElement($element);
}
$addressSpaceElements = $this->fromXmlService->getDeviceElementsFromXPath(
'address-spaces/address-space',
$document
);
foreach ($addressSpaceElements as $element) {
$tdf->addressSpaces[] = $this->fromXmlService->addressSpaceFromElement($element);
}
$physicalInterfaceElements = $this->fromXmlService->getDeviceElementsFromXPath(
'physical-interfaces/physical-interface',
$document
);
foreach ($physicalInterfaceElements as $element) {
$tdf->physicalInterfaces[] = $this->fromXmlService->physicalInterfaceFromElement($element);
}
$peripheralElements = $this->fromXmlService->getDeviceElementsFromXPath(
'peripherals/peripheral',
$document
);
foreach ($peripheralElements as $element) {
$tdf->peripherals[] = $this->fromXmlService->peripheralFromElement($element);
}
$moduleElements = $this->fromXmlService->getDeviceElementsFromXPath(
'modules/module',
$document
);
foreach ($moduleElements as $element) {
$tdf->modules[] = $this->fromXmlService->moduleFromElement($element);
}
$padElements = $this->fromXmlService->getDeviceElementsFromXPath(
'pads/pad',
$document
);
foreach ($padElements as $element) {
$tdf->pads[] = $this->fromXmlService->padFromElement($element);
}
$pinoutElements = $this->fromXmlService->getDeviceElementsFromXPath(
'pinouts/pinout',
$document
);
foreach ($pinoutElements as $element) {
$tdf->pinouts[] = $this->fromXmlService->pinoutFromElement($element);
}
$variantElements = $this->fromXmlService->getDeviceElementsFromXPath(
'variants/variant',
$document
);
foreach ($variantElements as $element) {
$tdf->variants[] = $this->fromXmlService->variantFromElement($element);
}
return $tdf;
}
/**
* Generates an XML document from the given TDF.
*
* @param TargetDescriptionFile $tdf
* The TDF from which to generate the XML document.
*
* @return DOMDocument
* The generated XML document.
*
* @throws DOMException
*/
public function toXml(TargetDescriptionFile $tdf): DOMDocument
{
$document = new DOMDocument('1.0', 'UTF-8');
$deviceElement = $document->createElement('device');
$deviceElement->setAttribute('name', $tdf->getName());
$deviceElement->setAttribute('family', $tdf->getFamily()->value ?? '');
$deviceElement->setAttribute('configuration-value', $tdf->getConfigurationValue());
$architecture = $tdf->getArchitecture();
if (!empty($architecture)) {
$deviceElement->setAttribute('architecture', $architecture);
}
$vendor = $tdf->getVendor();
if (!empty($vendor)) {
$deviceElement->setAttribute('vendor', $vendor);
}
foreach ($tdf->getAdditionalDeviceAttributes() as $attrName => $attrValue) {
$deviceElement->setAttribute($attrName, $attrValue);
}
if (!empty($tdf->propertyGroups)) {
$propertyGroupsElement = $document->createElement('property-groups');
foreach ($tdf->propertyGroups as $propertyGroup) {
$propertyGroupsElement->append($this->toXmlService->propertyGroupToXml($propertyGroup, $document));
}
}
$deviceElement->append($propertyGroupsElement);
$addressSpacesElement = $document->createElement('address-spaces');
foreach ($tdf->addressSpaces as $addressSpace) {
$addressSpacesElement->append($this->toXmlService->addressSpaceToXml($addressSpace, $document));
}
$deviceElement->append($addressSpacesElement);
$interfacesElement = $document->createElement('physical-interfaces');
foreach ($tdf->physicalInterfaces as $interface) {
$interfacesElement->append($this->toXmlService->physicalInterfaceToXml($interface, $document));
}
$deviceElement->append($interfacesElement);
$peripheralsElement = $document->createElement('peripherals');
foreach ($tdf->peripherals as $peripheral) {
$peripheralsElement->append($this->toXmlService->peripheralToXml($peripheral, $document));
}
$deviceElement->append($peripheralsElement);
$modulesElement = $document->createElement('modules');
foreach ($tdf->modules as $module) {
$modulesElement->append($this->toXmlService->moduleToXml($module, $document));
}
$deviceElement->append($modulesElement);
$padsElement = $document->createElement('pads');
foreach ($tdf->pads as $pad) {
$padsElement->append($this->toXmlService->padToXml($pad, $document));
}
$deviceElement->append($padsElement);
$pinoutsElement = $document->createElement('pinouts');
foreach ($tdf->pinouts as $pinout) {
$pinoutsElement->append($this->toXmlService->pinoutToXml($pinout, $document));
}
$deviceElement->append($pinoutsElement);
$variantsElement = $document->createElement('variants');
foreach ($tdf->variants as $variant) {
$variantsElement->append($this->toXmlService->variantToXml($variant, $document));
}
$deviceElement->append($variantsElement);
$document->append($deviceElement);
return $document;
}
}