From 6f361a1777dd5c8abe487d83589b5a05ef3e5b8d Mon Sep 17 00:00:00 2001 From: Daniel Carbone Date: Wed, 29 Jan 2025 09:59:27 -0600 Subject: [PATCH] more work on xml serialization --- files/constants.php | 2 +- src/Enum/XMLValueLocationUtils.php | 37 ++++++++++ src/Utilities/ImportUtils.php | 4 +- src/Version/Definition/Property.php | 3 +- src/Version/Definition/Type.php | 8 +-- .../core/types/interface_element_type.php | 28 ++++---- .../core/types/interface_resource_type.php | 12 ++-- ...php => interface_value_container_type.php} | 8 +-- template/versions/types/class_default.php | 5 +- .../types/properties/methods/default.php | 13 +++- .../serialization/json/unserialize/header.php | 10 +-- .../serialization/xml/serialize/body.php | 3 +- .../serialization/xml/serialize/header.php | 2 +- .../serialization/xml/unserialize/body.php | 67 +++++++++++-------- .../serialization/xml/unserialize/header.php | 14 ++-- 15 files changed, 139 insertions(+), 77 deletions(-) create mode 100644 src/Enum/XMLValueLocationUtils.php rename template/core/types/{interface_primitive_container_type.php => interface_value_container_type.php} (87%) diff --git a/files/constants.php b/files/constants.php index 53c078d0..0ffdb65f 100644 --- a/files/constants.php +++ b/files/constants.php @@ -109,7 +109,7 @@ // Core types entities const PHPFHIR_TYPES_INTERFACE_TYPE = 'TypeInterface'; const PHPFHIR_TYPES_INTERFACE_PRIMITIVE_TYPE = 'PrimitiveTypeInterface'; -const PHPFHIR_TYPES_INTERFACE_PRIMITIVE_CONTAINER_TYPE = 'PrimitiveContainerTypeInterface'; +const PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE = 'ValueContainerTypeInterface'; const PHPFHIR_TYPES_INTERFACE_ELEMENT_TYPE = 'ElementTypeInterface'; const PHPFHIR_TYPES_INTERFACE_RESOURCE_TYPE = 'ResourceTypeInterface'; diff --git a/src/Enum/XMLValueLocationUtils.php b/src/Enum/XMLValueLocationUtils.php new file mode 100644 index 00000000..252f43f3 --- /dev/null +++ b/src/Enum/XMLValueLocationUtils.php @@ -0,0 +1,37 @@ +isValueProperty() => 'LOCAL_ATTRIBUTE', + default => 'ELEMENT', + }; + if ($withClass) { + return sprintf('%s::%s', PHPFHIR_ENCODING_ENUM_VALUE_XML_LOCATION, $case); + } + return $case; + } +} \ No newline at end of file diff --git a/src/Utilities/ImportUtils.php b/src/Utilities/ImportUtils.php index 75ca521c..a41135f4 100644 --- a/src/Utilities/ImportUtils.php +++ b/src/Utilities/ImportUtils.php @@ -98,9 +98,7 @@ public static function buildVersionTypeImports(Version $version, Type $type): vo $imports->addImport($namespace, $trait); } - if ($type->isPrimitiveOrListType() || $type->hasPrimitiveOrListParent()) { - - } else if ($type->isPrimitiveContainer() || $type->hasPrimitiveContainerParent()) { + if ($type->isPrimitiveContainer() || $type->hasPrimitiveContainerParent()) { $imports->addCoreFileImportsByName( PHPFHIR_TYPES_INTERFACE_ELEMENT_TYPE, ); diff --git a/src/Version/Definition/Property.php b/src/Version/Definition/Property.php index e59084a0..a17eb3a8 100644 --- a/src/Version/Definition/Property.php +++ b/src/Version/Definition/Property.php @@ -511,8 +511,9 @@ public function isSerializableAsXMLAttribute(): bool return false; } return $propType->hasPrimitiveOrListParent() + || $propType->isPrimitiveOrListType() || $propType->isPrimitiveContainer() - || $propType->isPrimitiveOrListType(); + || ($this->_memberOf->isValueContainer() && $this->isValueProperty()); } /** diff --git a/src/Version/Definition/Type.php b/src/Version/Definition/Type.php index a9c28387..d187bed3 100644 --- a/src/Version/Definition/Type.php +++ b/src/Version/Definition/Type.php @@ -843,10 +843,10 @@ public function getDirectlyImplementedInterfaces(): array ->getCoreFileByEntityName(PHPFHIR_TYPES_INTERFACE_PRIMITIVE_TYPE) ->getFullyQualifiedNamespace(false); } - } else if ($this->isPrimitiveContainer()) { - if (!$this->hasPrimitiveContainerParent()) { - $interfaces[PHPFHIR_TYPES_INTERFACE_PRIMITIVE_CONTAINER_TYPE] = $coreFiles - ->getCoreFileByEntityName(PHPFHIR_TYPES_INTERFACE_PRIMITIVE_CONTAINER_TYPE) + } else if ($this->isValueContainer()) { + if (!$this->hasValueContainerParent()) { + $interfaces[PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE] = $coreFiles + ->getCoreFileByEntityName(PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE) ->getFullyQualifiedNamespace(false); } } else if ($this->isResourceType()) { diff --git a/template/core/types/interface_element_type.php b/template/core/types/interface_element_type.php index 4d317e97..c9f5b9fb 100644 --- a/template/core/types/interface_element_type.php +++ b/template/core/types/interface_element_type.php @@ -53,33 +53,33 @@ interface getEntityName(); ?> extends getFullyQualifiedName(true); ?> $config * @param null|getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. - * @param null|getFullyQualifiedName(true); ?> $config * @return static */ - public static function xmlUnserialize(string|\SimpleXMLElement $element, - null|getEntityName(); ?> $type = null, - null|getEntityName() ?> $config = null): self; + public static function xmlUnserialize(\SimpleXMLElement $element, + getEntityName() ?> $config, + null|getEntityName(); ?> $type = null): self; /** - * @param null|getFullyQualifiedName(true); ?> $xw - * @param null|getFullyQualifiedName(true); ?> $config + * @param getFullyQualifiedName(true); ?> $xw + * @param getFullyQualifiedName(true); ?> $config * @return getFullyQualifiedName(true); ?> */ - public function xmlSerialize(null|getEntityName(); ?> $xw = null, - null|getEntityName(); ?> $config = null): getEntityName(); ?>; + public function xmlSerialize(getEntityName(); ?> $xw, + getEntityName(); ?> $config): getEntityName(); ?>; /** - * @param string|array|\stdClass $json Raw or already un-encoded JSON + * @param array $json Decoded JSON + * @param getFullyQualifiedName(true); ?> $config * @param null|getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. - * @param null|getFullyQualifiedName(true); ?> $config * @return static */ - public static function jsonUnserialize(string|array|\stdClass $json, - null|getEntityName(); ?> $type = null, - null|getEntityName(); ?> $config = null): self; + public static function jsonUnserialize(array $json, + getEntityName(); ?> $config, + null|getEntityName(); ?> $type = null): self; } getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. * @param null|getFullyQualifiedName(true); ?> $config + * @param null|getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. * @return static */ public static function xmlUnserialize(string|\SimpleXMLElement $element, - null|getEntityName(); ?> $type = null, - null|getEntityName() ?> $config = null): self; + null|getEntityName() ?> $config = null, + null|getEntityName(); ?> $type = null): self; /** * @param null|getFullyQualifiedName(true); ?> $xw @@ -73,13 +73,13 @@ public function xmlSerialize(null|getEntityName(); ? /** * @param string|array|\stdClass $json Raw or already un-encoded JSON - * @param null|getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. * @param null|getFullyQualifiedName(true); ?> $config + * @param null|getFullyQualifiedName(true); ?> $type Instance of this class to unserialize into. If left null, a new instance will be created. * @return static */ public static function jsonUnserialize(string|array|\stdClass $json, - null|getEntityName(); ?> $type = null, - null|getEntityName(); ?> $config = null): self; + null|getEntityName(); ?> $config = null, + null|getEntityName(); ?> $type = null): self; } getFullyQualifiedName(true); ?> $xw - * @param null|getFullyQualifiedName(true); ?> $config + * @param getFullyQualifiedName(true); ?> $xw + * @param getFullyQualifiedName(true); ?> $config * @param null|getFullyQualifiedName(true); ?> $valueLocation * @return getFullyQualifiedName(true); ?> */ - public function xmlSerialize(null|getEntityName(); ?> $xw = null, - null|getEntityName(); ?> $config = null, + public function xmlSerialize(getEntityName(); ?> $xw, + getEntityName(); ?> $config, null|getEntityName(); ?> $valueLocation = null): getEntityName(); ?>; } diff --git a/template/versions/types/class_default.php b/template/versions/types/class_default.php index 64f88b5c..b9e69805 100644 --- a/template/versions/types/class_default.php +++ b/template/versions/types/class_default.php @@ -17,6 +17,7 @@ */ use DCarbone\PHPFHIR\Enum\TypeKindEnum; +use DCarbone\PHPFHIR\Enum\XMLValueLocationUtils; use DCarbone\PHPFHIR\Utilities\DocumentationUtils; use DCarbone\PHPFHIR\Utilities\TypeHintUtils; @@ -90,11 +91,11 @@ /* */ private array $_valueXMLLocations = [ -getAllPropertiesIndexedIterator() as $property) : +getProperties()->getIterator() as $property) : if (!$property->isSerializableAsXMLAttribute()) { continue; } ?> - self::getFieldConstantName(); ?> => getEntityName(); ?>::ATTRIBUTE, + self::getFieldConstantName(); ?> => , ]; 0) { echo "\n"; } + +// start getter methods ?> /** @@ -81,7 +84,12 @@ public function getIterator(): iterable return new \ArrayIterator($this->); } + endif; + +// end getter methods + +// start setter methods +?> /** @@ -96,7 +104,8 @@ public function getIterator(): iterable * @return static */ public function getSetterName(); ?>(isCollection(), true); ?> $isSerializableAsXMLAttribute()) : ?>, - getSetterName())); echo $valueXMLLocationEnum->getEntityName(); ?> $valueXMLLocation = getEntityName(); ?>::ATTRIBUTE): self + getSetterName())); + echo $valueXMLLocationEnum->getEntityName(); ?> $valueXMLLocation = ): self { isCollection()) : ?> if (null === $) { diff --git a/template/versions/types/serialization/json/unserialize/header.php b/template/versions/types/serialization/json/unserialize/header.php index 9a36881b..6ee40986 100644 --- a/template/versions/types/serialization/json/unserialize/header.php +++ b/template/versions/types/serialization/json/unserialize/header.php @@ -36,16 +36,16 @@ ob_start(); ?> /** - * @param string|array|\stdClass $json + * @param isResourceType() || $type->hasResourceTypeParent()) : ?>string|\stdClass|array $json + * @param isResourceType() || $type->hasResourceTypeParent()) : ?>null|getFullyQualifiedName(true); ?> $config * @param null|getFullyQualifiedClassName(true); ?> $type - * @param null|getFullyQualifiedName(true); ?> $config * @return getFullyQualifiedClassName(true); ?> * @throws \Exception */ - public static function jsonUnserialize(string|array|\stdClass $json, - null|getEntityName(); ?> $type = null, - null|getEntityName() ?> $config = null): self + public static function jsonUnserialize(isResourceType() || $type->hasResourceTypeParent()) : ?>string|\stdClass|array $json, + isResourceType() || $type->hasResourceTypeParent()) : ?>null|getEntityName() ?> $configisResourceType() || $type->hasResourceTypeParent()) : ?> = null, + null|getEntityName(); ?> $type = null): self { isAbstract()) : // abstract types may not be instantiated directly ?> if (null === $type) { diff --git a/template/versions/types/serialization/xml/serialize/body.php b/template/versions/types/serialization/xml/serialize/body.php index 86bb27d3..31001aa9 100644 --- a/template/versions/types/serialization/xml/serialize/body.php +++ b/template/versions/types/serialization/xml/serialize/body.php @@ -37,8 +37,9 @@ // if this is the "value" property on a primitive container, the value may be serialized to the parent's root node, // to the local node's attributes, or as an element on the local node. - if ($type->isPrimitiveContainer() && $property->isValueProperty()) : ?> + if ($type->isValueContainer() && $property->isValueProperty()) : ?> if (isset($this->getName(); ?>) + && getEntityName(); ?>::PARENT_ATTRIBUTE !== $valueLocation && (getEntityName(); ?>::LOCAL_ATTRIBUTE === $valueLocation || (null === $valueLocation && $this->_valueXMLLocations[self::getFieldConstantName(); ?>] === getEntityName(); ?>::LOCAL_ATTRIBUTE))) { $xw->writeAttribute(self::getFieldConstantName(); ?>, $this->getName(); ?>->_getFormattedValue()); diff --git a/template/versions/types/serialization/xml/serialize/header.php b/template/versions/types/serialization/xml/serialize/header.php index ed9bbd12..4a0544cf 100644 --- a/template/versions/types/serialization/xml/serialize/header.php +++ b/template/versions/types/serialization/xml/serialize/header.php @@ -42,7 +42,7 @@ */ public function xmlSerialize(null|getEntityName(); ?> $xw = null, - null|getEntityName(); ?> $config = nullisPrimitiveContainer() || $type->hasPrimitiveContainerParent()) : ?>, + null|getEntityName(); ?> $config = nullisValueContainer() || $type->hasValueContainerParent()) : ?>, null|getEntityName(); ?> $valueLocation = null): getEntityName(); ?> { diff --git a/template/versions/types/serialization/xml/unserialize/body.php b/template/versions/types/serialization/xml/unserialize/body.php index 01690ca0..b755d9be 100644 --- a/template/versions/types/serialization/xml/unserialize/body.php +++ b/template/versions/types/serialization/xml/unserialize/body.php @@ -17,6 +17,7 @@ */ use DCarbone\PHPFHIR\Enum\TypeKindEnum; +use DCarbone\PHPFHIR\Enum\XMLValueLocationUtils; /** @var \DCarbone\PHPFHIR\Version $version */ /** @var \DCarbone\PHPFHIR\Version\Definition\Type $type */ @@ -46,55 +47,67 @@ } else { $value = (string)$n; } - $type->(getName(); ?>: $value, valueXMLLocation: getEntityName(); ?>::ELEMENT); + $type->($value, valueXMLLocation: getEntityName(); ?>::ELEMENT); isResourceContainer($version)) : ?> foreach ($n->children() as $nn) { /** @var getFullyQualifiedName(true); ?> $cn */ $cn = ::getContainedTypeClassNameFromXML($nn); - $type->(getName(); ?>: $cn::xmlUnserialize($nn, null, $config)); + $type->($cn::xmlUnserialize($nn, $config)); } $type->($n); getMemberOf()->getImports()->getImportByType($propType); ?> - $type->(getName(); ?>: ::xmlUnserialize($n, null, $config)isSerializableAsXMLAttribute()) : ?>, valueXMLLocation: getEntityName(); ?>::ELEMENT); + $type->(::xmlUnserialize($n, $config)); } } $attributes = $element->attributes(); -getAllPropertiesIndexedIterator() as $i => $property) : +getAllPropertiesIndexedIterator() as $i => $property) : + if (!$property->isSerializableAsXMLAttribute()) { + continue; + } + $propConst = $property->getFieldConstantName(); $propType = $property->getValueFHIRType(); $setter = $property->getSetterName(); - - if (null !== $propType) : - $propTypeKind = $propType->getKind(); - - if ($propType->hasPrimitiveOrListParent() || $propType->isPrimitiveOrListType() || $propType->isPrimitiveContainer()) : - $propTypeClassname = $property->getMemberOf()->getImports()->getImportByType($propType); ?> +?> if (isset($attributes[self::])) { -isCollection()) : ?> - $type->(getName(); ?>: (string)$attributes[self::]); - - $pt = $type->getGetterName(); ?>(); - if (null !== $pt) { - $pt->setValue(value: (string)$attributes[self::]); + + $type->((string)$attributes[self::], getEntityName(); ?>::LOCAL_ATTRIBUTE); + + if (isset($type->getName(); ?>)) { + $type->getName(); ?>->setValue((string)$attributes[self::]); } else { - $type->(getName(); ?>: (string)$attributes[self::]); + $type->((string)$attributes[self::]); } -isSerializableAsXMLAttribute()) : ?> - $type->_setgetName()); ?>ValueXMLLocation(getEntityName(); ?>::ATTRIBUTE); - - - } - - if (isset($attributes[self::getFieldConstantName(); ?>])) { - $type->setValue((string)$attributes[self::getFieldConstantName(); ?>]); - } isValueContainer() || $type->hasValueContainerParent()) : ?> + $type->_setgetName()); ?>ValueXMLLocation(getEntityName(); ?>::LOCAL_ATTRIBUTE); + + $type->_setgetName()); ?>ValueXMLLocation(getEntityName(); ?>::PARENT_ATTRIBUTE); + + } + /** - * @param string|\SimpleXMLElement $element + * @param isResourceType() || $type->hasResourceTypeParent()) : ?>string|\SimpleXMLElement $element + * @param isResourceType() || $type->hasResourceTypeParent()) : ?>null|getFullyQualifiedName(true); ?> $config * @param null|getFullyQualifiedClassName(true); ?> $type - * @param null|getFullyQualifiedName(true); ?> $config * @return getFullyQualifiedClassName(true); ?> * @throws \Exception */ - public static function xmlUnserialize(string|\SimpleXMLElement $element, - null|getEntityName(); ?> $type = null, - null|getEntityName() ?> $config = null): self + public static function xmlUnserialize(isResourceType() || $type->hasResourceTypeParent()) : ?>string|\SimpleXMLElement $element, + isResourceType() || $type->hasResourceTypeParent()) : ?>null|getEntityName() ?> $configisResourceType() || $type->hasResourceTypeParent()) : ?> = null, + null|getEntityName(); ?> $type = null): self { isAbstract()) : // abstract types may not be instantiated directly ?> if (null === $type) { @@ -60,6 +60,7 @@ public static function xmlUnserialize(string|\SimpleXMLElement $element, get_class($type) )); } +isResourceType() || $type->hasResourceTypeParent()) : ?> if (null === $config) { $config = (new getEntityName(); ?>())->getConfig()->getUnserializeConfig(); } @@ -69,4 +70,5 @@ public static function xmlUnserialize(string|\SimpleXMLElement $element, if (null !== ($ns = $element->getNamespaces()[''] ?? null)) { $type->_setSourceXMLNS((string)$ns); } -