Skip to content

Commit

Permalink
much better determination of 'special' dstu1 stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
dcarbone committed Dec 28, 2024
1 parent 13f73de commit 65074a3
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 63 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"ext-simplexml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"psr/log": "^3.0"
"psr/log": "^3.0",
"composer/semver": "^3.4"
},
"require-dev": {
"phpunit/phpunit": "^10.5 || ^11.0",
Expand Down
87 changes: 84 additions & 3 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 17 additions & 15 deletions src/Enum/TypeKindEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* limitations under the License.
*/

use DCarbone\PHPFHIR\Version;

enum TypeKindEnum: string
{
// this represents an actual value: string, int, etc.
Expand Down Expand Up @@ -46,20 +48,23 @@ enum TypeKindEnum: string
// treated a bit different
case PHPFHIR_XHTML = 'phpfhir_xhtml';

private const CONTAINER_TYPES = [
self::RESOURCE_CONTAINER,
self::RESOURCE_INLINE,
];
private const _DSTU1_CONTAINER_TYPE = self::RESOURCE_INLINE;

private const _CONTAINER_TYPE = self::RESOURCE_CONTAINER;

/**
* Returns true if the provided FHIR type name is the "container" type for the provided version.
*
* @param \DCarbone\PHPFHIR\Version $version
* @param string $fhirName
* @return bool
*/
public static function isContainerTypeName(string $fhirName): bool
public static function isContainerTypeName(Version $version, string $fhirName): bool
{
return in_array($fhirName, self::_containerTypeStrings(), true);
if ($version->getSourceMetadata()->isDSTU1()) {
return $fhirName === self::_DSTU1_CONTAINER_TYPE->value;
}
return $fhirName === self::_CONTAINER_TYPE->value;
}

/**
Expand All @@ -74,17 +79,14 @@ public function isOneOf(TypeKindEnum|string ...$other): bool
/**
* Returns true if this kind is the "container" kind for the provided FHIR version.
*
* @param \DCarbone\PHPFHIR\Version $version
* @return bool
*/
public function isContainer(): bool
{
return in_array($this, self::CONTAINER_TYPES, true);
}

private static function _containerTypeStrings(): array
public function isContainer(Version $version): bool
{
return array_map(function (TypeKindEnum $tk): string {
return $tk->value;
}, self::CONTAINER_TYPES);
if ($version->getSourceMetadata()->isDSTU1()) {
return $this === self::_DSTU1_CONTAINER_TYPE;
}
return $this === self::_CONTAINER_TYPE;
}
}
19 changes: 10 additions & 9 deletions src/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
* limitations under the License.
*/

use Composer\Semver\Semver;
use DCarbone\PHPFHIR\Enum\TestTypeEnum;
use DCarbone\PHPFHIR\Utilities\NameUtils;
use DCarbone\PHPFHIR\Version\SourceMetadata;
use DCarbone\PHPFHIR\Version\Definition;
use DCarbone\PHPFHIR\Version\VersionDefaultConfig;
use DCarbone\PHPFHIR\Version\DefaultConfig;

/**
* Class Version
Expand All @@ -36,8 +37,8 @@ class Version
/** @var \DCarbone\PHPFHIR\Version\SourceMetadata */
private SourceMetadata $_sourceMetadata;

/** @var \DCarbone\PHPFHIR\Version\VersionDefaultConfig */
private VersionDefaultConfig $_defaultConfig;
/** @var \DCarbone\PHPFHIR\Version\DefaultConfig */
private DefaultConfig $_defaultConfig;

/** @var string */
private string $_name;
Expand Down Expand Up @@ -106,7 +107,7 @@ public function __construct(Config $config, string $name, array $params = [])
}

if (!isset($this->_defaultConfig)) {
$this->_defaultConfig = new VersionDefaultConfig([]);
$this->_defaultConfig = new DefaultConfig([]);
}

$this->_sourceMetadata = new SourceMetadata($config, $this);
Expand Down Expand Up @@ -200,21 +201,21 @@ public function setNamespace(string $namespace): self
}

/**
* @return \DCarbone\PHPFHIR\Version\VersionDefaultConfig
* @return \DCarbone\PHPFHIR\Version\DefaultConfig
*/
public function getDefaultConfig(): VersionDefaultConfig
public function getDefaultConfig(): DefaultConfig
{
return $this->_defaultConfig;
}

/**
* @param array|\DCarbone\PHPFHIR\Version\VersionDefaultConfig $defaultConfig
* @param array|\DCarbone\PHPFHIR\Version\DefaultConfig $defaultConfig
* @return $this
*/
public function setDefaultConfig(array|VersionDefaultConfig $defaultConfig): self
public function setDefaultConfig(array|DefaultConfig $defaultConfig): self
{
if (is_array($defaultConfig)) {
$defaultConfig = new VersionDefaultConfig($defaultConfig);
$defaultConfig = new DefaultConfig($defaultConfig);
}
$this->_defaultConfig = $defaultConfig;
return $this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@
* limitations under the License.
*/

/**
* Class VersoinConfig
* @package DCarbone\PHPFHIR\Version
*/
class VersionDefaultConfig
class DefaultConfig
{
private const _UNSERIALIZE_CONFIG_KEYS = [
'libxmlOpts',
Expand All @@ -45,7 +41,7 @@ class VersionDefaultConfig
*/
public function __construct(array $config)
{
foreach (VersionDefaultConfigKeyEnum::cases() as $k) {
foreach (DefaultConfigKeyEnum::cases() as $k) {
if (isset($config[$k->value]) || array_key_exists($k->value, $config)) {
$this->{"set{$k->value}"}($config[$k->value]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* limitations under the License.
*/

enum VersionDefaultConfigKeyEnum: string
enum DefaultConfigKeyEnum: string
{
case UNSERIALIZE_CONFIG = 'unserializeConfig';
case SERIALIZE_CONFIG = 'serializeConfig';
Expand Down
2 changes: 1 addition & 1 deletion src/Version/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function buildDefinition(): void
$this->types = TypeExtractor::parseTypes($this->config, $this->version);

$log->info('Finding restriction base types');
TypeDecorator::findRestrictionBaseTypes($this->config, $this->types);
TypeDecorator::findRestrictionBaseTypes($this->version, $this->types);

$log->info('Finding parent types');
TypeDecorator::findParentTypes($this->config, $this->types);
Expand Down
26 changes: 14 additions & 12 deletions src/Version/Definition/TypeDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public static function findComponentOfTypes(Config $config, Types $types): void
}

/**
* @param \DCarbone\PHPFHIR\Config $config
* @param \DCarbone\PHPFHIR\Version $version
* @param \DCarbone\PHPFHIR\Version\Definition\Types $types
*/
public static function findRestrictionBaseTypes(Config $config, Types $types): void
public static function findRestrictionBaseTypes(Version $version, Types $types): void
{
$logger = $config->getLogger();
$logger = $version->getConfig()->getLogger();
foreach ($types->getIterator() as $type) {
$fhirName = $type->getFHIRName();

Expand All @@ -83,7 +83,10 @@ public static function findRestrictionBaseTypes(Config $config, Types $types): v

if (str_starts_with($rbName, 'xs:')) {
$rbName = substr($rbName, 3);
if ('token' === $rbName || ctype_upper($rbName[0])) {
// Found only in the DSTU1 "ResourceNamesPlusBinary" type as a restriction base, "NMTOKEN" is a string
// without whitespace. I do not feel like fussing with special logic around this, so force it to be
// a string.
if ($version->getSourceMetadata()->isDSTU1() && ('token' === $rbName || ctype_upper($rbName[0]))) {
$logger->warning(
sprintf(
'Type "%s" has restriction base "%s", setting to string...',
Expand Down Expand Up @@ -239,10 +242,9 @@ private static function setTypeKind(Config $config, Types $types, Type $type, Ty
*/
private static function determineParsedTypeKind(Config $config, Version $version, Types $types, Type $type): void
{
$logger = $config->getLogger();
$logger = $version->getConfig()->getLogger();
$fhirName = $type->getFHIRName();

$versionName = $version->getName();
$sourceMeta = $version->getSourceMetadata();

// there are a few specialty types kinds that are set during the parsing process, most notably for
// html value types and primitive value types
Expand All @@ -258,14 +260,14 @@ private static function determineParsedTypeKind(Config $config, Version $version
}

// check if this type is a DSTU1-specific primitive
if (in_array($fhirName, self::DSTU1_PRIMITIVES, true)) {
if ($sourceMeta->isDSTU1() && in_array($fhirName, self::DSTU1_PRIMITIVES, true)) {
$logger->debug(sprintf('Setting Type "%s" kind to "%s"', $type->getFHIRName(), TypeKindEnum::PRIMITIVE->value));
$type->setKind(TypeKindEnum::PRIMITIVE);
return;
}

// check if type is primitive...
if (str_contains($fhirName, PHPFHIR_PRIMITIVE_SUFFIX)) {
if (str_ends_with($fhirName, PHPFHIR_PRIMITIVE_SUFFIX)) {
$logger->debug(sprintf('Type "%s" has primitive suffix, setting kind to "%s"', $type->getFHIRName(), TypeKindEnum::PRIMITIVE->value));
self::setTypeKind($config, $types, $type, TypeKindEnum::PRIMITIVE);
return;
Expand All @@ -281,7 +283,7 @@ private static function determineParsedTypeKind(Config $config, Version $version
$rootType = $type->getRootType();

// if this is the "container" type for this FHIR version
if (TypeKindEnum::isContainerTypeName($fhirName)) {
if (TypeKindEnum::isContainerTypeName($version, $fhirName)) {
$logger->debug(sprintf('Type "%s" is a container type, setting kind to "%s"', $type->getFHIRName(), $fhirName));
self::setTypeKind($config, $types, $type, $fhirName);
return;
Expand All @@ -296,7 +298,7 @@ private static function determineParsedTypeKind(Config $config, Version $version
}

// check if type is list...
if (str_contains($fhirName, PHPFHIR_LIST_SUFFIX)) {
if (str_ends_with($fhirName, PHPFHIR_LIST_SUFFIX)) {
// for all intents and purposes, a List type is a multiple choice primitive type
$logger->debug(sprintf('Type "%s" has list suffix, setting kind to "%s"', $type->getFHIRName(), TypeKindEnum::LIST->value));
self::setTypeKind($config, $types, $type, TypeKindEnum::LIST);
Expand All @@ -306,7 +308,7 @@ private static function determineParsedTypeKind(Config $config, Version $version
// This block indicates the type is only present as the child of a Resource. Its name may (and in many
// cases does) conflict with a top level Element or Resource. Because of this, they are treated differently
// and must be marked as such.
if (str_contains($fhirName, '.') && TypeKindEnum::RESOURCE_INLINE->value !== $fhirName) {
if (str_contains($fhirName, '.') && !$sourceMeta->isDSTU1() && TypeKindEnum::RESOURCE_INLINE->value !== $fhirName) {
$logger->debug(sprintf('Type "%s" is not "%s" but has dot in name, setting kind to "%s"', $type->getFHIRName(), TypeKindEnum::RESOURCE_INLINE->value, TypeKindEnum::RESOURCE_COMPONENT->value));
self::setTypeKind($config, $types, $type, TypeKindEnum::RESOURCE_COMPONENT);
return;
Expand Down
9 changes: 5 additions & 4 deletions src/Version/Definition/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,14 @@ function (Type $t1, Type $t2) {
*
* Should be either "Resource.Inline" or "ResourceContainer" types.
*
* @param \DCarbone\PHPFHIR\Version $version
* @return \DCarbone\PHPFHIR\Version\Definition\Type|null
*/
public function getContainerType(): null|Type
public function getContainerType(Version $version): null|Type
{
if (!isset($this->containerType)) {
foreach ($this->types as $type) {
if ($type->getKind()->isContainer()) {
if ($type->getKind()->isContainer($version)) {
$this->containerType = $type;
break;
}
Expand All @@ -221,10 +222,10 @@ public function getContainerType(): null|Type
public function isContainedType(Type $type): bool
{
// only bother with actual Resource types.
if ($type->getKind()->isContainer()) {
if ($type->getKind()->isContainer($type->getVersion())) {
return false;
}
$container = $this->getContainerType();
$container = $this->getContainerType($type->getVersion());
if (null === $container) {
return false;
}
Expand Down
Loading

0 comments on commit 65074a3

Please sign in to comment.