224 lines
8.1 KiB
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;
|
|
}
|
|
}
|