Skip to content

Commit

Permalink
fix some stuff, break some other stuff, weeeeeee
Browse files Browse the repository at this point in the history
  • Loading branch information
dcarbone committed Jan 31, 2025
1 parent 8686546 commit 70c7868
Show file tree
Hide file tree
Showing 17 changed files with 274 additions and 112 deletions.
4 changes: 2 additions & 2 deletions files/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@
// Core types entities
const PHPFHIR_TYPES_INTERFACE_TYPE = 'TypeInterface';
const PHPFHIR_TYPES_INTERFACE_PRIMITIVE_TYPE = 'PrimitiveTypeInterface';
const PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE = 'ValueContainerTypeInterface';
const PHPFHIR_TYPES_INTERFACE_ELEMENT_TYPE = 'ElementTypeInterface';
const PHPFHIR_TYPES_INTERFACE_PRIMITIVE_CONTAINER_TYPE = 'PrimitiveContainerTypeInterface';
const PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE = 'ValueContainerTypeInterface';
const PHPFHIR_TYPES_INTERFACE_RESOURCE_TYPE = 'ResourceTypeInterface';

const PHPFHIR_TYPES_INTERFACE_CONTAINED_TYPE = 'ContainedTypeInterface';
const PHPFHIR_TYPES_INTERFACE_COMMENT_CONTAINER = 'CommentContainerInterface';
const PHPFHIR_TYPES_TRAIT_COMMENT_CONTAINER = 'CommentContainerTrait';
Expand Down
3 changes: 0 additions & 3 deletions src/Enum/TypeKindEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ enum TypeKindEnum: string
// this represents an actual value: string, int, etc.
case PRIMITIVE = 'primitive';

// these represent types that exist to wrap a primitive
case PRIMITIVE_CONTAINER = 'primitive_container';

// primitive type with limited possible value set
case LIST = 'list';

Expand Down
18 changes: 11 additions & 7 deletions src/Utilities/ImportUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public static function buildVersionPrimitiveTypeImports(Version $version, Type $

public static function buildVersionTypeImports(Version $version, Type $type): void
{
$logger = $version->getConfig()->getLogger();

$logger->debug(sprintf('Compiling imports for Type "%s"...', $type->getFHIRName()));

$imports = $type->getImports();

// immediately add self
Expand Down Expand Up @@ -183,13 +187,13 @@ public static function buildVersionTypeImports(Version $version, Type $type): vo
$imports->addVersionCoreFileImportsByName($type->getVersion(), PHPFHIR_VERSION_CLASSNAME_VERSION_TYPE_MAP);
$imports->addVersionCoreFileImportsByName($type->getVersion(), PHPFHIR_VERSION_CLASSNAME_VERSION);
} else {
if ($propertyType->isValueContainer() || $propertyType->hasValueContainerParent()) {
$valType = $propertyType
->getProperties()
->getProperty(PHPFHIR_VALUE_PROPERTY_NAME)->getValueFHIRType();
$imports->addImport(
$valType->getFullyQualifiedNamespace(false), $valType->getClassName()
);
$valProp = $propertyType->isValueContainer()
? $propertyType->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME)
: $propertyType->getParentProperty(PHPFHIR_VALUE_PROPERTY_NAME);

if (null !== $valProp) {
$valType = $valProp->getValueFHIRType();
$imports->addImport($valType->getFullyQualifiedNamespace(false), $valType->getClassName());
}

$imports->addImport(
Expand Down
7 changes: 4 additions & 3 deletions src/Utilities/TypeHintUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ public static function buildBaseHintParts(Version $version, Type $type, bool $fu
if ($type->isPrimitiveOrListType() || $type->hasPrimitiveOrListParent()) {
$hintTypes = $type->getPrimitiveType()->getPHPReceiveValueTypeHints();
} else if ($type->isValueContainer() || $type->hasValueContainerParent()) {
$ptp = $type->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME)->getValueFHIRType();
$valProp = $type->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME) ?? $type->getParentProperty(PHPFHIR_VALUE_PROPERTY_NAME);
$ptp = $valProp->getValueFHIRType();
$hintTypes = [];
if ($ptp->isPrimitiveOrListType() || $ptp->hasPrimitiveOrListParent()) {
$hintTypes = $ptp->getPrimitiveType()->getPHPReceiveValueTypeHints();
Expand Down Expand Up @@ -265,7 +266,7 @@ public static function buildSetterParameterDocHint(Version $version,


if ($pt->isValueContainer() || $pt->hasValueContainerParent()) {
$vp = $pt->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME);
$vp = $pt->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME) ?? $pt->getParentProperty(PHPFHIR_VALUE_PROPERTY_NAME);
array_push(
$hintTypes,
$vp->getValueFHIRType()->getFullyQualifiedClassName(true),
Expand Down Expand Up @@ -311,7 +312,7 @@ public static function buildSetterParameterHint(Version $version,
$hintTypes = self::buildBaseHintParts($version, $pt, false);

if ($pt->isValueContainer() || $pt->hasValueContainerParent()) {
$vp = $pt->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME);
$vp = $pt->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME) ?? $pt->getParentProperty(PHPFHIR_VALUE_PROPERTY_NAME);
array_push(
$hintTypes,
$vp->getValueFHIRType()->getClassName(),
Expand Down
5 changes: 4 additions & 1 deletion src/Version/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,11 @@ public function buildDefinition(): void
$log->info('Setting contained type flags');
TypeDecorator::setContainedTypeFlag($this->_config, $this->_version, $this->_types);

$log->info('Setting primitive container flags');
TypeDecorator::setPrimitiveContainerFlag($this->_version, $this->_types);

$log->info('Setting value container flags');
TypeDecorator::setValueContainerFlag($this->_config, $this->_types);
TypeDecorator::setValueContainerFlag($this->_version, $this->_types);

$log->info('Setting comment container flags');
TypeDecorator::setCommentContainerFlag($this->_config, $this->_types);
Expand Down
47 changes: 45 additions & 2 deletions src/Version/Definition/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class Type
/** @var bool */
private bool $_containedType = false;
/** @var bool */
private bool $_primitiveContainer = false;
/** @var bool */
private bool $_valueContainer = false;
/** @var bool */
private bool $_commentContainer = false;
Expand Down Expand Up @@ -352,6 +354,16 @@ public function getProperties(): Properties
return $this->_properties;
}

public function getParentProperty(string $name) : null|Property
{
foreach($this->getParentPropertiesIterator() as $property) {
if ($property->getName() === $name) {
return $property;;
}
}
return null;
}

/**
* Returns true if this type has any locally defined properties.
*
Expand Down Expand Up @@ -544,9 +556,28 @@ public function hasPrimitiveOrListParent(): bool
return false;
}

/**
* @return bool
*/
public function isPrimitiveContainer(): bool
{
return $this->getKind() === TypeKindEnum::PRIMITIVE_CONTAINER;
return $this->_primitiveContainer;
}

/**
* @param bool $primitiveContainer
* @return $this
*/
public function setPrimitiveContainer(bool $primitiveContainer): Type
{
if ($primitiveContainer && $this->_valueContainer) {
throw new \LogicException(sprintf(
'Cannot mark Type "%s" as primitive container as it is already marked as a value container',
$this->getFHIRName()
));
}
$this->_primitiveContainer = $primitiveContainer;
return $this;
}

/**
Expand Down Expand Up @@ -806,6 +837,12 @@ public function isValueContainer(): bool
*/
public function setValueContainer(bool $valueContainer): Type
{
if ($valueContainer && $this->_primitiveContainer) {
throw new \LogicException(sprintf(
'Cannot mark Type "%s" as value container as it is already marked as a primitive container',
$this->getFHIRName(),
));
}
$this->_valueContainer = $valueContainer;
return $this;
}
Expand Down Expand Up @@ -836,7 +873,7 @@ public function isQuantity(): bool
*/
public function hasQuantityParent(): bool
{
foreach($this->getParentTypes() as $parent) {
foreach ($this->getParentTypes() as $parent) {
if ($parent->isQuantity()) {
return true;
}
Expand Down Expand Up @@ -864,6 +901,12 @@ public function getDirectlyImplementedInterfaces(): array
->getCoreFileByEntityName(PHPFHIR_TYPES_INTERFACE_PRIMITIVE_TYPE)
->getFullyQualifiedNamespace(false);
}
} else if ($this->isPrimitiveContainer()) {
if (!$this->hasPrimitiveContainerParent()) {
$interfaces[PHPFHIR_TYPES_INTERFACE_PRIMITIVE_TYPE] = $coreFiles
->getCoreFileByEntityName(PHPFHIR_TYPES_INTERFACE_PRIMITIVE_CONTAINER_TYPE)
->getFullyQualifiedNamespace(false);
}
} else if ($this->isValueContainer()) {
if (!$this->hasValueContainerParent()) {
$interfaces[PHPFHIR_TYPES_INTERFACE_VALUE_CONTAINER_TYPE] = $coreFiles
Expand Down
8 changes: 4 additions & 4 deletions src/Version/Definition/TypeDecorationValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static function validateDecoration(Config $config, Version $version, Type
if (!NameUtils::isValidNSName($version->getFullyQualifiedName(false))) {
throw ExceptionUtils::createInvalidVersionNamespaceException($version);
}

$seenClasses = [];
foreach ($types->getIterator() as $type) {
$typeKind = $type->getKind();
Expand Down Expand Up @@ -68,7 +68,7 @@ public static function validateDecoration(Config $config, Version $version, Type
}

if ($typeKind === TypeKindEnum::PRIMITIVE) {
if (null === $type->getPrimitiveType()) {
if (null === $type->getPrimitiveType()) {
throw ExceptionUtils::createUnknownPrimitiveTypeException($type);
}
}
Expand All @@ -80,8 +80,8 @@ public static function validateDecoration(Config $config, Version $version, Type
}
}

if ($typeKind === TypeKindenum::PRIMITIVE_CONTAINER) {
$valueProperty = $type->getProperties()->getProperty('value');
if ($type->isPrimitiveContainer()) {
$valueProperty = $type->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME);
if (null === $valueProperty) {
throw ExceptionUtils::createPrimitiveValuePropertyNotFound($type);
}
Expand Down
68 changes: 52 additions & 16 deletions src/Version/Definition/TypeDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ abstract class TypeDecorator
*/
public static function findNamelessProperties(Config $config, Types $types): void
{
foreach($types->getIterator() as $type) {
foreach($type->getProperties()->getIterator() as $property) {
foreach ($types->getIterator() as $type) {
foreach ($type->getProperties()->getIterator() as $property) {
$name = $property->getName();
if ('' === $name || null === $name) {
$property->setName($property->getRef());
Expand Down Expand Up @@ -216,6 +216,10 @@ public static function determinePrimitiveTypes(Config $config, Types $types): vo
continue;
}

if (!str_ends_with($ptn, '-primitive')) {
continue;
}

$logger->debug(sprintf('Setting assumed primitive Type "%s" kind to "%s"', $type->getFHIRName(), $ptn));
$ptn = str_replace('-primitive', '', $ptn);
$pt = PrimitiveTypeEnum::from($ptn);
Expand Down Expand Up @@ -331,13 +335,6 @@ private static function determineParsedTypeKind(Config $config, Version $version
return;
}

// this is for primitive "wrapper" types, e.g. String -> 'string-primitive'
if (null !== $types->getTypeByName(sprintf('%s-primitive', $fhirName))) {
$logger->debug(sprintf('Type "%s" has primitive counterpart, setting kind to "%s"', $type->getFHIRName(), TypeKindEnum::PRIMITIVE_CONTAINER->value));
self::setTypeKind($config, $types, $type, TypeKindEnum::PRIMITIVE_CONTAINER);
return;
}

// special block for xhtml type
if (PHPFHIR_XHTML_TYPE_NAME === $type->getFHIRName()) {
$logger->debug(sprintf('Setting Type "%s" kind to itself ("%s")', $type->getFHIRName(), TypeKindEnum::PHPFHIR_XHTML->value));
Expand Down Expand Up @@ -380,23 +377,59 @@ public static function setContainedTypeFlag(Config $config, Version $version, Ty
}

/**
* A "value container" type is any non-primitive type with a "value" property.
* Once parsing has been completed, we must do a final pass to identify types that are primitive containers by
* another name.
*
* @param \DCarbone\PHPFHIR\Config $config
* @param \DCarbone\PHPFHIR\Version $version
* @param \DCarbone\PHPFHIR\Version\Definition\Types $types
*/
public static function setValueContainerFlag(Config $config, Types $types): void
public static function setPrimitiveContainerFlag(Version $version, Types $types): void
{
// TODO: handle valueString, valueQuantity, etc. types?
$logger = $version->getConfig()->getLogger();
foreach ($types->getIterator() as $type) {
// skip primitives
if ($type->isPrimitiveOrListType() || $type->hasPrimitiveOrListParent()) {
continue;
}

// mark types that have a "$n-primitive" counterpart as primitive containers explicitly.
if (null !== $types->getTypeByName(sprintf('%s-primitive', $type->getFHIRName()))) {
$logger->debug(sprintf('Type "%s" has primitive counterpart, marking as Primitive Container', $type->getFHIRName()));
$type->setPrimitiveContainer(true);
continue;
}

// skip types that do not have a directly implmeented "value" property
$vp = $type->getProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME);
if (null === $vp) {
continue;
}

$vpt = $vp->getValueFHIRType();
if ($vpt->isPrimitiveOrListType() || $vpt->hasPrimitiveOrListParent()) {
$logger->debug(sprintf('Type "%s" has primtive "value" property, marking as Primitive Container', $type->getFHIRName()));
$type->setPrimitiveContainer(true);
}
}
}

/**
* A "value container" type is any type with a "value" property that isn't a primitive or primitive-container.
*
* @param \DCarbone\PHPFHIR\Version $version
* @param \DCarbone\PHPFHIR\Version\Definition\Types $types
*/
public static function setValueContainerFlag(Version $version, Types $types): void
{
$logger = $version->getConfig()->getLogger();
foreach ($types->getIterator() as $type) {
// primitive types have special handling and must not be marked as "value containers"
if ($type->isPrimitiveOrListType() || $type->hasPrimitiveOrListParent()) {
continue;
}

// skip "quantity" types, as their "value" is always applied as an element
if ($type->isQuantity()) {
// skip "primitive container" types.
if ($type->isPrimitiveContainer() || $type->hasPrimitiveContainerParent()) {
continue;
}

Expand All @@ -405,7 +438,10 @@ public static function setValueContainerFlag(Config $config, Types $types): void
continue;
}

$type->setValueContainer($type->getProperties()->hasProperty(PHPFHIR_VALUE_PROPERTY_NAME));
if ($type->getProperties()->hasProperty(PHPFHIR_VALUE_PROPERTY_NAME)) {
$logger->debug(sprintf('Type "%s" has "value" property, marking as Value Container', $type->getFHIRName()));
$type->setValueContainer(true);
}
}
}

Expand Down
Loading

0 comments on commit 70c7868

Please sign in to comment.