Support for property groups in variant elements, in TDFs

This commit is contained in:
Nav
2024-10-12 16:25:11 +01:00
parent 22cca07242
commit 5c896bb2ca
7 changed files with 158 additions and 7 deletions

View File

@@ -1046,7 +1046,8 @@ class AtdfService
strtolower($attributes['ordercode'] ?? $attributes['name'] ?? '')
),
$attributes['ordercode'] ?? $attributes['name'] ?? null,
isset($attributes['pinout']) ? strtolower($attributes['pinout']) : null
isset($attributes['pinout']) ? strtolower($attributes['pinout']) : null,
[]
);
}
}

View File

@@ -1039,6 +1039,17 @@ class ValidationService
. '" - check pinout key';
}
$processedPropertyGroupKeys = [];
foreach ($variant->propertyGroups as $propertyGroup) {
$failures = array_merge($failures, $this->validatePropertyGroup($propertyGroup));
if ($propertyGroup->key !== null && in_array($propertyGroup->key, $processedPropertyGroupKeys)) {
$failures[] = 'Duplicate property group key ("' . $propertyGroup->key . '") detected';
}
$processedPropertyGroupKeys[] = $propertyGroup->key;
}
return array_map(
fn (string $failure): string => 'Variant "' . $variant->name . '" validation failure: ' . $failure,
$failures

View File

@@ -450,10 +450,32 @@ class FromXmlService
{
$attributes = $this->getNodeAttributesByName($element);
return new Variant(
$output = new Variant(
$attributes['key'] ?? null,
$attributes['name'] ?? null,
$attributes['pinout-key'] ?? null
$attributes['pinout-key'] ?? null,
[]
);
$propertyGroupsElements = $element->getElementsByTagName('property-groups');
if (
$propertyGroupsElements->count() === 1
&& ($propertyGroupsElement = $propertyGroupsElements->item(0)) instanceof DOMElement
) {
foreach ($propertyGroupsElement->childNodes as $childNode) {
if (!$childNode instanceof DOMElement) {
continue;
}
if ($childNode->nodeName === 'property-group') {
$output->propertyGroups[] = $this->propertyGroupFromElement($childNode);
}
}
} elseif ($propertyGroupsElements->count() > 1) {
throw new XmlParsingException('Unexpected number of "property-groups" elements');
}
return $output;
}
}

View File

@@ -406,6 +406,15 @@ class ToXmlService
$element->setAttribute('name', $variant->name);
$element->setAttribute('pinout-key', $variant->pinoutKey);
if (!empty($variant->propertyGroups)) {
$propertyGroupsElement = $document->createElement('signals');
foreach ($variant->propertyGroups as $propertyGroup) {
$propertyGroupsElement->append($this->propertyGroupToXml($propertyGroup, $document));
}
$element->append($propertyGroupsElement);
}
return $element;
}
}

View File

@@ -1,16 +1,52 @@
<?php
namespace Targets\TargetDescriptionFiles;
require_once __DIR__ . "/PropertyGroup.php";
class Variant
{
public ?string $key = null;
public ?string $name = null;
public ?string $pinoutKey = null;
public function __construct(?string $key, ?string $name, ?string $pinoutKey)
/** @var PropertyGroup[] */
public array $propertyGroups = [];
public function __construct(?string $key, ?string $name, ?string $pinoutKey, array $propertyGroups)
{
$this->key = $key;
$this->name = $name;
$this->pinoutKey = $pinoutKey;
$this->propertyGroups = $propertyGroups;
}
public function getPropertyGroup(array|string $keys): ?PropertyGroup
{
if (is_string($keys)) {
$keys = explode('.', $keys);
}
$firstLevelGroupKey = array_shift($keys);
foreach ($this->propertyGroups as $propertyGroup) {
if ($propertyGroup->key === $firstLevelGroupKey) {
return !empty($keys) ? $propertyGroup->getSubgroup($keys) : $propertyGroup;
}
}
return null;
}
public function getProperty(array|string $propertyGroupKeys, $propertyKey): ?Property
{
return ($propertyGroup = $this->getPropertyGroup($propertyGroupKeys)) instanceof PropertyGroup
? $propertyGroup->getProperty($propertyKey)
: null;
}
public function getPropertyValue(array|string $propertyGroupKeys, $propertyKey): ?string
{
return ($property = $this->getProperty($propertyGroupKeys, $propertyKey)) instanceof Property
? $property->value
: null;
}
}

View File

@@ -926,11 +926,23 @@ namespace Targets::TargetDescription
}
Variant TargetDescriptionFile::variantFromXml(const QDomElement& xmlElement) {
return {
auto output = Variant{
TargetDescriptionFile::getAttribute(xmlElement, "key"),
TargetDescriptionFile::getAttribute(xmlElement, "name"),
TargetDescriptionFile::getAttribute(xmlElement, "pinout-key")
TargetDescriptionFile::getAttribute(xmlElement, "pinout-key"),
{}
};
for (
auto element = xmlElement.firstChildElement("property-groups").firstChildElement("property-group");
!element.isNull();
element = element.nextSiblingElement("property-group")
) {
auto propertyGroup = TargetDescriptionFile::propertyGroupFromXml(element);
output.propertyGroupsByKey.emplace(propertyGroup.key, std::move(propertyGroup));
}
return output;
}
TargetAddressSpaceDescriptor TargetDescriptionFile::targetAddressSpaceDescriptorFromAddressSpace(

View File

@@ -1,6 +1,13 @@
#pragma once
#include <string>
#include <map>
#include <functional>
#include "PropertyGroup.hpp"
#include "src/Services/StringService.hpp"
#include "Exceptions/InvalidTargetDescriptionDataException.hpp"
namespace Targets::TargetDescription
{
@@ -10,14 +17,67 @@ namespace Targets::TargetDescription
std::string name;
std::string pinoutKey;
std::map<std::string, PropertyGroup, std::less<void>> propertyGroupsByKey;
Variant(
const std::string& key,
const std::string& name,
const std::string& pinoutKey
const std::string& pinoutKey,
const std::map<std::string, PropertyGroup, std::less<void>>& propertyGroupsByKey
)
: key(key)
, name(name)
, pinoutKey(pinoutKey)
, propertyGroupsByKey(propertyGroupsByKey)
{}
std::optional<std::reference_wrapper<const PropertyGroup>> tryGetPropertyGroup(std::string_view keyStr) const {
const auto keys = Services::StringService::split(keyStr, '.');
const auto firstSubgroupIt = this->propertyGroupsByKey.find(*keys.begin());
return firstSubgroupIt != this->propertyGroupsByKey.end()
? keys.size() > 1
? firstSubgroupIt->second.tryGetSubgroup(keys | std::ranges::views::drop(1))
: std::optional{std::cref(firstSubgroupIt->second)}
: std::nullopt;
}
const PropertyGroup& getPropertyGroup(std::string_view keyStr) const {
const auto propertyGroup = this->tryGetPropertyGroup(keyStr);
if (!propertyGroup.has_value()) {
throw Exceptions::InvalidTargetDescriptionDataException{
"Failed to get property group \"" + std::string{keyStr} + "\" from TDF - property group not found"
};
}
return propertyGroup->get();
}
std::optional<std::reference_wrapper<const Property>> tryGetProperty(
std::string_view groupKey,
std::string_view propertyKey
) const {
const auto propertyGroup = this->tryGetPropertyGroup(groupKey);
if (!propertyGroup.has_value()) {
return std::nullopt;
}
return propertyGroup->get().tryGetProperty(propertyKey);
}
const Property& getProperty(std::string_view groupKey, std::string_view propertyKey) const {
const auto property = this->tryGetProperty(groupKey, propertyKey);
if (!property.has_value()) {
throw Exceptions::InvalidTargetDescriptionDataException{
"Failed to get property \"" + std::string{propertyKey} + "\" from group \"" + std::string{groupKey}
+ "\", from TDF - property/group not found"
};
}
return property->get();
}
};
}