From 9500f7eae4d9ab94dc4da9a56ade47e290fbae0f Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Tue, 28 May 2024 15:53:40 +0200 Subject: [PATCH 1/6] Collect meta attributes from XSD files --- .../Attribute/AbstractAttributeItem.php | 22 +++++++++ src/Schema/Attribute/AttributeSingle.php | 11 +++++ src/Schema/MetaInformation.php | 42 ++++++++++++++++ src/SchemaReader.php | 36 ++++++++++++++ tests/AttributesTest.php | 48 +++++++++++++++++++ 5 files changed, 159 insertions(+) create mode 100644 src/Schema/MetaInformation.php diff --git a/src/Schema/Attribute/AbstractAttributeItem.php b/src/Schema/Attribute/AbstractAttributeItem.php index 98a7fd47..e3702a3f 100644 --- a/src/Schema/Attribute/AbstractAttributeItem.php +++ b/src/Schema/Attribute/AbstractAttributeItem.php @@ -5,6 +5,7 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; use GoetasWebservices\XML\XSDReader\Schema\Item; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; abstract class AbstractAttributeItem extends Item implements AttributeSingle { @@ -18,6 +19,11 @@ abstract class AbstractAttributeItem extends Item implements AttributeSingle protected string $use = self::USE_OPTIONAL; + /** + * @var list + */ + protected array $meta = []; + public function getFixed(): ?string { return $this->fixed; @@ -67,4 +73,20 @@ public function setUse(string $use): void { $this->use = $use; } + + /** + * @return list + */ + public function getMeta(): array + { + return $this->meta; + } + + /** + * @param list $meta + */ + public function setMeta(array $meta): void + { + $this->meta = $meta; + } } diff --git a/src/Schema/Attribute/AttributeSingle.php b/src/Schema/Attribute/AttributeSingle.php index 4f7114fa..88d51dd0 100644 --- a/src/Schema/Attribute/AttributeSingle.php +++ b/src/Schema/Attribute/AttributeSingle.php @@ -4,6 +4,7 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; interface AttributeSingle extends AttributeItem @@ -35,4 +36,14 @@ public function setNil(bool $nil): void; public function getUse(): ?string; public function setUse(string $use): void; + + /** + * @param list $meta + */ + public function setMeta(array $meta): void; + + /** + * @return list + */ + public function getMeta(): array; } diff --git a/src/Schema/MetaInformation.php b/src/Schema/MetaInformation.php new file mode 100644 index 00000000..9b3ca9b2 --- /dev/null +++ b/src/Schema/MetaInformation.php @@ -0,0 +1,42 @@ +schema = $schema; + $this->name = $name; + $this->value = $value; + } + + public function getSchema(): Schema + { + return $this->schema; + } + + public function getName(): string + { + return $this->name; + } + + public function getValue(): string + { + return $this->value; + } +} diff --git a/src/SchemaReader.php b/src/SchemaReader.php index 9cf259ae..3f33de77 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -28,12 +28,14 @@ use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetFixed; use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetMinMax; use GoetasWebservices\XML\XSDReader\Schema\Element\Sequence; +use GoetasWebservices\XML\XSDReader\Schema\Exception\SchemaException; use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Base; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Extension; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Restriction; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\RestrictionType; use GoetasWebservices\XML\XSDReader\Schema\Item; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; use GoetasWebservices\XML\XSDReader\Schema\Schema; use GoetasWebservices\XML\XSDReader\Schema\SchemaItem; use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType; @@ -236,6 +238,27 @@ private function fillAttribute(AttributeSingle $attribute, \DOMElement $node): v if ($node->hasAttribute('use')) { $attribute->setUse($node->getAttribute('use')); } + + $attribute->setMeta($this->loadMetaAttributesForElement($attribute, $node)); + } + + /** + * @return list + */ + private function loadMetaAttributesForElement(SchemaItem $item, \DOMElement $node): array + { + $meta = []; + foreach ($node->attributes as $attr) { + if (null !== $attr->namespaceURI && self::XSD_NS !== $attr->namespaceURI) { + $meta[] = new MetaInformation( + $this->findSchemaForNamespace($item->getSchema(), $attr->namespaceURI), + $attr->name, + $attr->value + ); + } + } + + return $meta; } private function loadAttributeOrElementDef( @@ -1093,6 +1116,19 @@ private function findType(Schema $schema, \DOMElement $node, string $typeName): throw new TypeException(sprintf("Can't find %s named {%s}#%s, at line %d in %s ", 'type', $namespace, $name, $node->getLineNo(), $node->ownerDocument->documentURI)); } + public function findSchemaForNamespace(Schema $currentSchema, string $namespace): Schema + { + if ($currentSchema->getTargetNamespace() === $namespace) { + return $currentSchema; + } + + if (array_key_exists($namespace, $this->loadedSchemas) && count($this->loadedSchemas[$namespace]) > 0) { + return $this->loadedSchemas[$namespace][0]; + } + + throw new SchemaException(sprintf("Can't find schema for namespace %s", $namespace)); + } + private function fillItem(Item $element, \DOMElement $node, ?\DOMElement $parentNode = null): void { if ($element instanceof ElementDef) { diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index ec1ec380..68b4f8de 100644 --- a/tests/AttributesTest.php +++ b/tests/AttributesTest.php @@ -144,4 +144,52 @@ public function testAttributeUseOverriding(): void self::assertEquals('language', $attribute->getType()->getName()); self::assertEquals(AttributeSingle::USE_REQUIRED, $attribute->getUse()); } + + public function testMetaInformation(): void + { + $schema = $this->reader->readString( + ' + + + ' + ); + + $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); + self::assertInstanceOf(AttributeDef::class, $myAttribute); + + $meta = $myAttribute->getMeta(); + self::assertCount(1, $meta); + self::assertEquals('meta', $meta[0]->getName()); + self::assertEquals('hello', $meta[0]->getValue()); + self::assertSame($myAttribute->getSchema(), $meta[0]->getSchema()); + } + + public function testExternalSchemaReferencingMetaInformation(): void + { + $dom = new \DOMDocument(); + $dom->loadXML( + ' + + + + + + + + + + '); + $schema = $this->reader->readNodes(iterator_to_array($dom->documentElement->childNodes), 'file.xsd'); + + $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); + self::assertInstanceOf(AttributeDef::class, $myAttribute); + + $meta = $myAttribute->getMeta(); + self::assertCount(1, $meta); + self::assertEquals('meta', $meta[0]->getName()); + self::assertEquals('hello', $meta[0]->getValue()); + + $refAttr = $schema->findAttribute('meta', 'http://www.ref.com'); + self::assertSame($refAttr->getSchema(), $meta[0]->getSchema()); + } } From 62d134f5a457bd0cdac19d4d26b2f4542437bdbd Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Fri, 31 May 2024 08:58:35 +0200 Subject: [PATCH 2/6] Also store the context-schema so that type-information can be resolved when requesting the meta data. --- src/Schema/MetaInformation.php | 28 +++++++++++++++++++++ src/SchemaReader.php | 1 + tests/AttributesTest.php | 45 +++++++++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/Schema/MetaInformation.php b/src/Schema/MetaInformation.php index 9b3ca9b2..e76e97a8 100644 --- a/src/Schema/MetaInformation.php +++ b/src/Schema/MetaInformation.php @@ -11,16 +11,39 @@ */ class MetaInformation { + /** + * Links to the schema in which this information is contained. + * This context schema can be used to resolve e.g. a type. + * + * Example: + * wsdl:arrayType="int" + * + * value = "int" + * contextSchema = xsd : "http://www.w3.org/2001/XMLSchema" + * schema = wsdl : "http://schemas.xmlsoap.org/wsdl/" + * + * The type would be xsd:int + */ + private Schema $contextSchema; + + /** + * Links to the schema that holds the declaration of the meta information type. + * The meta information would be located inside the "schema-prefix:name" attribute. + */ private Schema $schema; + private string $name; + private string $value; public function __construct( Schema $schema, + Schema $contextSchema, string $name, string $value ) { $this->schema = $schema; + $this->contextSchema = $contextSchema; $this->name = $name; $this->value = $value; } @@ -30,6 +53,11 @@ public function getSchema(): Schema return $this->schema; } + public function getContextSchema(): Schema + { + return $this->contextSchema; + } + public function getName(): string { return $this->name; diff --git a/src/SchemaReader.php b/src/SchemaReader.php index 3f33de77..52c28e89 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -252,6 +252,7 @@ private function loadMetaAttributesForElement(SchemaItem $item, \DOMElement $nod if (null !== $attr->namespaceURI && self::XSD_NS !== $attr->namespaceURI) { $meta[] = new MetaInformation( $this->findSchemaForNamespace($item->getSchema(), $attr->namespaceURI), + $this->findSchemaForNamespace($item->getSchema(), $attr->parentNode->namespaceURI), $attr->name, $attr->value ); diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index 68b4f8de..2ee7cdc8 100644 --- a/tests/AttributesTest.php +++ b/tests/AttributesTest.php @@ -11,6 +11,7 @@ use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group; use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType; use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType; +use GoetasWebservices\XML\XSDReader\SchemaReader; class AttributesTest extends BaseTest { @@ -164,18 +165,18 @@ public function testMetaInformation(): void self::assertSame($myAttribute->getSchema(), $meta[0]->getSchema()); } - public function testExternalSchemaReferencingMetaInformation(): void + public function testExternalSchemaReferencingMetaInformationPrefixed(): void { $dom = new \DOMDocument(); $dom->loadXML( ' - + - + '); @@ -186,10 +187,42 @@ public function testExternalSchemaReferencingMetaInformation(): void $meta = $myAttribute->getMeta(); self::assertCount(1, $meta); - self::assertEquals('meta', $meta[0]->getName()); - self::assertEquals('hello', $meta[0]->getValue()); + self::assertEquals('metaType', $meta[0]->getName()); + self::assertEquals('xs:string', $meta[0]->getValue()); + + $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); + self::assertSame($refAttr->getSchema(), $meta[0]->getSchema()); + self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + } + + public function testExternalSchemaReferencingMetaInformationUnprefixed(): void + { + $dom = new \DOMDocument(); + $dom->loadXML( + ' + + + + + + + + + + '); + $schema = $this->reader->readNodes(iterator_to_array($dom->documentElement->childNodes), 'file.xsd'); + + $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); + self::assertInstanceOf(AttributeDef::class, $myAttribute); + + $meta = $myAttribute->getMeta(); + + self::assertCount(1, $meta); + self::assertEquals('metaType', $meta[0]->getName()); + self::assertEquals('string', $meta[0]->getValue()); - $refAttr = $schema->findAttribute('meta', 'http://www.ref.com'); + $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); self::assertSame($refAttr->getSchema(), $meta[0]->getSchema()); + self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); } } From 63b29d4b3027837bc5cd034b15179f666745a7e6 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Fri, 31 May 2024 12:40:13 +0200 Subject: [PATCH 3/6] Collect target namespace instead of schema - cause there might not be a schema linked --- src/Schema/MetaInformation.php | 21 ++++++++------------- src/SchemaReader.php | 2 +- tests/AttributesTest.php | 7 ++++--- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Schema/MetaInformation.php b/src/Schema/MetaInformation.php index e76e97a8..fe3f6178 100644 --- a/src/Schema/MetaInformation.php +++ b/src/Schema/MetaInformation.php @@ -13,49 +13,44 @@ class MetaInformation { /** * Links to the schema in which this information is contained. - * This context schema can be used to resolve e.g. a type. + * This context schema can be used to resolve an un-prefixed qname type. * * Example: * wsdl:arrayType="int" * * value = "int" * contextSchema = xsd : "http://www.w3.org/2001/XMLSchema" - * schema = wsdl : "http://schemas.xmlsoap.org/wsdl/" * * The type would be xsd:int */ private Schema $contextSchema; - /** - * Links to the schema that holds the declaration of the meta information type. - * The meta information would be located inside the "schema-prefix:name" attribute. - */ - private Schema $schema; + private string $namespaceURI; private string $name; private string $value; public function __construct( - Schema $schema, Schema $contextSchema, + string $namespaceURI, string $name, string $value ) { - $this->schema = $schema; $this->contextSchema = $contextSchema; + $this->namespaceURI = $namespaceURI; $this->name = $name; $this->value = $value; } - public function getSchema(): Schema + public function getContextSchema(): Schema { - return $this->schema; + return $this->contextSchema; } - public function getContextSchema(): Schema + public function getNamespaceURI(): string { - return $this->contextSchema; + return $this->namespaceURI; } public function getName(): string diff --git a/src/SchemaReader.php b/src/SchemaReader.php index 52c28e89..5a93121e 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -251,8 +251,8 @@ private function loadMetaAttributesForElement(SchemaItem $item, \DOMElement $nod foreach ($node->attributes as $attr) { if (null !== $attr->namespaceURI && self::XSD_NS !== $attr->namespaceURI) { $meta[] = new MetaInformation( - $this->findSchemaForNamespace($item->getSchema(), $attr->namespaceURI), $this->findSchemaForNamespace($item->getSchema(), $attr->parentNode->namespaceURI), + $attr->namespaceURI, $attr->name, $attr->value ); diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index 2ee7cdc8..2a057fdc 100644 --- a/tests/AttributesTest.php +++ b/tests/AttributesTest.php @@ -162,7 +162,8 @@ public function testMetaInformation(): void self::assertCount(1, $meta); self::assertEquals('meta', $meta[0]->getName()); self::assertEquals('hello', $meta[0]->getValue()); - self::assertSame($myAttribute->getSchema(), $meta[0]->getSchema()); + self::assertEquals('http://www.example.com', $meta[0]->getNamespaceURI()); + self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); } public function testExternalSchemaReferencingMetaInformationPrefixed(): void @@ -191,7 +192,7 @@ public function testExternalSchemaReferencingMetaInformationPrefixed(): void self::assertEquals('xs:string', $meta[0]->getValue()); $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); - self::assertSame($refAttr->getSchema(), $meta[0]->getSchema()); + self::assertSame($refAttr->getSchema()->getTargetNamespace(), $meta[0]->getNamespaceURI()); self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); } @@ -222,7 +223,7 @@ public function testExternalSchemaReferencingMetaInformationUnprefixed(): void self::assertEquals('string', $meta[0]->getValue()); $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); - self::assertSame($refAttr->getSchema(), $meta[0]->getSchema()); + self::assertSame($refAttr->getSchema()->getTargetNamespace(), $meta[0]->getNamespaceURI()); self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); } } From ee6189fc690ce3848095a101ba4a7d786d7e663d Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Mon, 3 Jun 2024 19:27:28 +0200 Subject: [PATCH 4/6] Collect element metadata --- .../Attribute/AbstractAttributeItem.php | 25 +------ src/Schema/Attribute/AttributeSingle.php | 14 +--- src/Schema/Element/AbstractElementSingle.php | 3 + src/Schema/Element/ElementSingle.php | 3 +- .../MetaInformationContainerInterface.php | 18 +++++ src/Schema/MetaInformationContainerTrait.php | 29 ++++++++ src/SchemaReader.php | 2 + tests/ElementsTest.php | 67 +++++++++++++++++++ 8 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 src/Schema/MetaInformationContainerInterface.php create mode 100644 src/Schema/MetaInformationContainerTrait.php diff --git a/src/Schema/Attribute/AbstractAttributeItem.php b/src/Schema/Attribute/AbstractAttributeItem.php index e3702a3f..af874f45 100644 --- a/src/Schema/Attribute/AbstractAttributeItem.php +++ b/src/Schema/Attribute/AbstractAttributeItem.php @@ -5,10 +5,12 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; use GoetasWebservices\XML\XSDReader\Schema\Item; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerTrait; abstract class AbstractAttributeItem extends Item implements AttributeSingle { + use MetaInformationContainerTrait; + protected ?string $fixed = null; protected ?string $default = null; @@ -19,11 +21,6 @@ abstract class AbstractAttributeItem extends Item implements AttributeSingle protected string $use = self::USE_OPTIONAL; - /** - * @var list - */ - protected array $meta = []; - public function getFixed(): ?string { return $this->fixed; @@ -73,20 +70,4 @@ public function setUse(string $use): void { $this->use = $use; } - - /** - * @return list - */ - public function getMeta(): array - { - return $this->meta; - } - - /** - * @param list $meta - */ - public function setMeta(array $meta): void - { - $this->meta = $meta; - } } diff --git a/src/Schema/Attribute/AttributeSingle.php b/src/Schema/Attribute/AttributeSingle.php index 88d51dd0..883473bd 100644 --- a/src/Schema/Attribute/AttributeSingle.php +++ b/src/Schema/Attribute/AttributeSingle.php @@ -4,10 +4,10 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerInterface; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; -interface AttributeSingle extends AttributeItem +interface AttributeSingle extends AttributeItem, MetaInformationContainerInterface { public const USE_OPTIONAL = 'optional'; @@ -36,14 +36,4 @@ public function setNil(bool $nil): void; public function getUse(): ?string; public function setUse(string $use): void; - - /** - * @param list $meta - */ - public function setMeta(array $meta): void; - - /** - * @return list - */ - public function getMeta(): array; } diff --git a/src/Schema/Element/AbstractElementSingle.php b/src/Schema/Element/AbstractElementSingle.php index f933d3f5..918f5137 100644 --- a/src/Schema/Element/AbstractElementSingle.php +++ b/src/Schema/Element/AbstractElementSingle.php @@ -5,9 +5,12 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Element; use GoetasWebservices\XML\XSDReader\Schema\Item; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerTrait; class AbstractElementSingle extends Item implements ElementSingle, InterfaceSetAbstract { + use MetaInformationContainerTrait; + protected int $min = 1; protected int $max = 1; diff --git a/src/Schema/Element/ElementSingle.php b/src/Schema/Element/ElementSingle.php index 3fd1bf6e..2e6ba85e 100644 --- a/src/Schema/Element/ElementSingle.php +++ b/src/Schema/Element/ElementSingle.php @@ -4,9 +4,10 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Element; +use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerInterface; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; -interface ElementSingle extends ElementItem, InterfaceSetMinMax, InterfaceSetFixed, InterfaceSetDefault +interface ElementSingle extends ElementItem, InterfaceSetMinMax, InterfaceSetFixed, InterfaceSetDefault, MetaInformationContainerInterface { public function getType(): ?Type; diff --git a/src/Schema/MetaInformationContainerInterface.php b/src/Schema/MetaInformationContainerInterface.php new file mode 100644 index 00000000..b4078692 --- /dev/null +++ b/src/Schema/MetaInformationContainerInterface.php @@ -0,0 +1,18 @@ + $meta + */ + public function setMeta(array $meta): void; + + /** + * @return list + */ + public function getMeta(): array; +} diff --git a/src/Schema/MetaInformationContainerTrait.php b/src/Schema/MetaInformationContainerTrait.php new file mode 100644 index 00000000..fe754635 --- /dev/null +++ b/src/Schema/MetaInformationContainerTrait.php @@ -0,0 +1,29 @@ + + */ + protected array $meta = []; + + /** + * @return list + */ + public function getMeta(): array + { + return $this->meta; + } + + /** + * @param list $meta + */ + public function setMeta(array $meta): void + { + $this->meta = $meta; + } +} diff --git a/src/SchemaReader.php b/src/SchemaReader.php index 5a93121e..0f2999a5 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -1493,6 +1493,8 @@ private function fillElement(AbstractElementSingle $element, \DOMElement $node): $element->setLocal(true); } } + + $element->setMeta($this->loadMetaAttributesForElement($element, $node)); } private function addAttributeFromAttributeOrRef( diff --git a/tests/ElementsTest.php b/tests/ElementsTest.php index 6b94675b..3a0a1dc1 100644 --- a/tests/ElementsTest.php +++ b/tests/ElementsTest.php @@ -12,6 +12,7 @@ use GoetasWebservices\XML\XSDReader\Schema\Element\GroupRef; use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType; use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType; +use GoetasWebservices\XML\XSDReader\SchemaReader; class ElementsTest extends BaseTest { @@ -272,4 +273,70 @@ public function testSequenceElementDocs(): void $aloneElement = $myGroup->getElements()[0]; self::assertSame('Alone description', $aloneElement->getDoc()); } + + public function testMetaInformation(): void + { + $schema = $this->reader->readString( + ' + + + ' + ); + + $myElement = $schema->findElement('myElement', 'http://www.example.com'); + self::assertInstanceOf(ElementDef::class, $myElement); + + $meta = $myElement->getMeta(); + self::assertCount(1, $meta); + self::assertEquals('meta', $meta[0]->getName()); + self::assertEquals('hello', $meta[0]->getValue()); + self::assertEquals('http://www.example.com', $meta[0]->getNamespaceURI()); + self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + } + + public function testDfdlElementMetaInformation(): void + { + $schema = $this->reader->readString( + ' + + + ' + ); + + $myElement = $schema->findElement('myElement', 'http://www.example.com'); + self::assertInstanceOf(ElementDef::class, $myElement); + + $meta = $myElement->getMeta(); + $namespaceUri = 'http://www.ogf.org/dfdl/dfdl-1.0/extensions'; + + self::assertCount(5, $meta); + self::assertEquals($namespaceUri, $meta[0]->getNamespaceURI()); + self::assertEquals('encoding', $meta[0]->getName()); + self::assertEquals('iso-8859-1', $meta[0]->getValue()); + + self::assertEquals($namespaceUri, $meta[1]->getNamespaceURI()); + self::assertEquals('initiator', $meta[1]->getName()); + self::assertEquals('UNA', $meta[1]->getValue()); + + self::assertEquals($namespaceUri, $meta[2]->getNamespaceURI()); + self::assertEquals('length', $meta[2]->getName()); + self::assertEquals('6', $meta[2]->getValue()); + + self::assertEquals($namespaceUri, $meta[3]->getNamespaceURI()); + self::assertEquals('lengthKind', $meta[3]->getName()); + self::assertEquals('explicit', $meta[3]->getValue()); + + self::assertEquals($namespaceUri, $meta[4]->getNamespaceURI()); + self::assertEquals('terminator', $meta[4]->getName()); + self::assertEquals('%NL;%WSP*; %WSP*;', $meta[4]->getValue()); + } } From 1d031262bfb032b7a8e5e10a71659d1fb3d6e732 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Tue, 4 Jun 2024 08:15:33 +0200 Subject: [PATCH 5/6] Rework meta to custom attributes --- .../Attribute/AbstractAttributeItem.php | 4 +- src/Schema/Attribute/AttributeSingle.php | 4 +- src/Schema/CustomAttribute.php | 45 +++++++++++++ .../CustomAttributeContainerInterface.php | 18 +++++ src/Schema/CustomAttributeContainerTrait.php | 29 +++++++++ src/Schema/Element/AbstractElementSingle.php | 4 +- src/Schema/Element/ElementSingle.php | 4 +- src/Schema/MetaInformation.php | 65 ------------------- .../MetaInformationContainerInterface.php | 18 ----- src/Schema/MetaInformationContainerTrait.php | 29 --------- src/SchemaReader.php | 31 +++------ tests/AttributesTest.php | 54 +++++++-------- tests/ElementsTest.php | 52 +++++++-------- 13 files changed, 158 insertions(+), 199 deletions(-) create mode 100644 src/Schema/CustomAttribute.php create mode 100644 src/Schema/CustomAttributeContainerInterface.php create mode 100644 src/Schema/CustomAttributeContainerTrait.php delete mode 100644 src/Schema/MetaInformation.php delete mode 100644 src/Schema/MetaInformationContainerInterface.php delete mode 100644 src/Schema/MetaInformationContainerTrait.php diff --git a/src/Schema/Attribute/AbstractAttributeItem.php b/src/Schema/Attribute/AbstractAttributeItem.php index af874f45..ce75a25a 100644 --- a/src/Schema/Attribute/AbstractAttributeItem.php +++ b/src/Schema/Attribute/AbstractAttributeItem.php @@ -4,12 +4,12 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; +use GoetasWebservices\XML\XSDReader\Schema\CustomAttributeContainerTrait; use GoetasWebservices\XML\XSDReader\Schema\Item; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerTrait; abstract class AbstractAttributeItem extends Item implements AttributeSingle { - use MetaInformationContainerTrait; + use CustomAttributeContainerTrait; protected ?string $fixed = null; diff --git a/src/Schema/Attribute/AttributeSingle.php b/src/Schema/Attribute/AttributeSingle.php index 883473bd..e90449b5 100644 --- a/src/Schema/Attribute/AttributeSingle.php +++ b/src/Schema/Attribute/AttributeSingle.php @@ -4,10 +4,10 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Attribute; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerInterface; +use GoetasWebservices\XML\XSDReader\Schema\CustomAttributeContainerInterface; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; -interface AttributeSingle extends AttributeItem, MetaInformationContainerInterface +interface AttributeSingle extends AttributeItem, CustomAttributeContainerInterface { public const USE_OPTIONAL = 'optional'; diff --git a/src/Schema/CustomAttribute.php b/src/Schema/CustomAttribute.php new file mode 100644 index 00000000..b04833fb --- /dev/null +++ b/src/Schema/CustomAttribute.php @@ -0,0 +1,45 @@ + + */ +class CustomAttribute +{ + private string $namespaceURI; + + private string $name; + + private string $value; + + public function __construct( + string $namespaceURI, + string $name, + string $value + ) { + $this->namespaceURI = $namespaceURI; + $this->name = $name; + $this->value = $value; + } + + public function getNamespaceURI(): string + { + return $this->namespaceURI; + } + + public function getName(): string + { + return $this->name; + } + + public function getValue(): string + { + return $this->value; + } +} diff --git a/src/Schema/CustomAttributeContainerInterface.php b/src/Schema/CustomAttributeContainerInterface.php new file mode 100644 index 00000000..a62e3290 --- /dev/null +++ b/src/Schema/CustomAttributeContainerInterface.php @@ -0,0 +1,18 @@ + $customAttributes + */ + public function setCustomAttributes(array $customAttributes): void; + + /** + * @return list + */ + public function getCustomAttributes(): array; +} diff --git a/src/Schema/CustomAttributeContainerTrait.php b/src/Schema/CustomAttributeContainerTrait.php new file mode 100644 index 00000000..6df52e5e --- /dev/null +++ b/src/Schema/CustomAttributeContainerTrait.php @@ -0,0 +1,29 @@ + + */ + protected array $customAttributes = []; + + /** + * @return list + */ + public function getCustomAttributes(): array + { + return $this->customAttributes; + } + + /** + * @param list $customAttributes + */ + public function setCustomAttributes(array $customAttributes): void + { + $this->customAttributes = $customAttributes; + } +} diff --git a/src/Schema/Element/AbstractElementSingle.php b/src/Schema/Element/AbstractElementSingle.php index 918f5137..63646adb 100644 --- a/src/Schema/Element/AbstractElementSingle.php +++ b/src/Schema/Element/AbstractElementSingle.php @@ -4,12 +4,12 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Element; +use GoetasWebservices\XML\XSDReader\Schema\CustomAttributeContainerTrait; use GoetasWebservices\XML\XSDReader\Schema\Item; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerTrait; class AbstractElementSingle extends Item implements ElementSingle, InterfaceSetAbstract { - use MetaInformationContainerTrait; + use CustomAttributeContainerTrait; protected int $min = 1; diff --git a/src/Schema/Element/ElementSingle.php b/src/Schema/Element/ElementSingle.php index 2e6ba85e..9c0066e0 100644 --- a/src/Schema/Element/ElementSingle.php +++ b/src/Schema/Element/ElementSingle.php @@ -4,10 +4,10 @@ namespace GoetasWebservices\XML\XSDReader\Schema\Element; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformationContainerInterface; +use GoetasWebservices\XML\XSDReader\Schema\CustomAttributeContainerInterface; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; -interface ElementSingle extends ElementItem, InterfaceSetMinMax, InterfaceSetFixed, InterfaceSetDefault, MetaInformationContainerInterface +interface ElementSingle extends ElementItem, InterfaceSetMinMax, InterfaceSetFixed, InterfaceSetDefault, CustomAttributeContainerInterface { public function getType(): ?Type; diff --git a/src/Schema/MetaInformation.php b/src/Schema/MetaInformation.php deleted file mode 100644 index fe3f6178..00000000 --- a/src/Schema/MetaInformation.php +++ /dev/null @@ -1,65 +0,0 @@ -contextSchema = $contextSchema; - $this->namespaceURI = $namespaceURI; - $this->name = $name; - $this->value = $value; - } - - public function getContextSchema(): Schema - { - return $this->contextSchema; - } - - public function getNamespaceURI(): string - { - return $this->namespaceURI; - } - - public function getName(): string - { - return $this->name; - } - - public function getValue(): string - { - return $this->value; - } -} diff --git a/src/Schema/MetaInformationContainerInterface.php b/src/Schema/MetaInformationContainerInterface.php deleted file mode 100644 index b4078692..00000000 --- a/src/Schema/MetaInformationContainerInterface.php +++ /dev/null @@ -1,18 +0,0 @@ - $meta - */ - public function setMeta(array $meta): void; - - /** - * @return list - */ - public function getMeta(): array; -} diff --git a/src/Schema/MetaInformationContainerTrait.php b/src/Schema/MetaInformationContainerTrait.php deleted file mode 100644 index fe754635..00000000 --- a/src/Schema/MetaInformationContainerTrait.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ - protected array $meta = []; - - /** - * @return list - */ - public function getMeta(): array - { - return $this->meta; - } - - /** - * @param list $meta - */ - public function setMeta(array $meta): void - { - $this->meta = $meta; - } -} diff --git a/src/SchemaReader.php b/src/SchemaReader.php index 0f2999a5..8642865f 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -15,6 +15,7 @@ use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeRef; use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeSingle; use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup; +use GoetasWebservices\XML\XSDReader\Schema\CustomAttribute; use GoetasWebservices\XML\XSDReader\Schema\Element\AbstractElementSingle; use GoetasWebservices\XML\XSDReader\Schema\Element\Choice; use GoetasWebservices\XML\XSDReader\Schema\Element\Element; @@ -28,14 +29,12 @@ use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetFixed; use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetMinMax; use GoetasWebservices\XML\XSDReader\Schema\Element\Sequence; -use GoetasWebservices\XML\XSDReader\Schema\Exception\SchemaException; use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Base; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Extension; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Restriction; use GoetasWebservices\XML\XSDReader\Schema\Inheritance\RestrictionType; use GoetasWebservices\XML\XSDReader\Schema\Item; -use GoetasWebservices\XML\XSDReader\Schema\MetaInformation; use GoetasWebservices\XML\XSDReader\Schema\Schema; use GoetasWebservices\XML\XSDReader\Schema\SchemaItem; use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType; @@ -239,19 +238,18 @@ private function fillAttribute(AttributeSingle $attribute, \DOMElement $node): v $attribute->setUse($node->getAttribute('use')); } - $attribute->setMeta($this->loadMetaAttributesForElement($attribute, $node)); + $attribute->setCustomAttributes($this->loadCustomAttributesForElement($attribute, $node)); } /** - * @return list + * @return list */ - private function loadMetaAttributesForElement(SchemaItem $item, \DOMElement $node): array + private function loadCustomAttributesForElement(SchemaItem $item, \DOMElement $node): array { - $meta = []; + $customAttributes = []; foreach ($node->attributes as $attr) { if (null !== $attr->namespaceURI && self::XSD_NS !== $attr->namespaceURI) { - $meta[] = new MetaInformation( - $this->findSchemaForNamespace($item->getSchema(), $attr->parentNode->namespaceURI), + $customAttributes[] = new CustomAttribute( $attr->namespaceURI, $attr->name, $attr->value @@ -259,7 +257,7 @@ private function loadMetaAttributesForElement(SchemaItem $item, \DOMElement $nod } } - return $meta; + return $customAttributes; } private function loadAttributeOrElementDef( @@ -1117,19 +1115,6 @@ private function findType(Schema $schema, \DOMElement $node, string $typeName): throw new TypeException(sprintf("Can't find %s named {%s}#%s, at line %d in %s ", 'type', $namespace, $name, $node->getLineNo(), $node->ownerDocument->documentURI)); } - public function findSchemaForNamespace(Schema $currentSchema, string $namespace): Schema - { - if ($currentSchema->getTargetNamespace() === $namespace) { - return $currentSchema; - } - - if (array_key_exists($namespace, $this->loadedSchemas) && count($this->loadedSchemas[$namespace]) > 0) { - return $this->loadedSchemas[$namespace][0]; - } - - throw new SchemaException(sprintf("Can't find schema for namespace %s", $namespace)); - } - private function fillItem(Item $element, \DOMElement $node, ?\DOMElement $parentNode = null): void { if ($element instanceof ElementDef) { @@ -1494,7 +1479,7 @@ private function fillElement(AbstractElementSingle $element, \DOMElement $node): } } - $element->setMeta($this->loadMetaAttributesForElement($element, $node)); + $element->setCustomAttributes($this->loadCustomAttributesForElement($element, $node)); } private function addAttributeFromAttributeOrRef( diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index 2a057fdc..90ab0f3f 100644 --- a/tests/AttributesTest.php +++ b/tests/AttributesTest.php @@ -11,7 +11,6 @@ use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group; use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType; use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType; -use GoetasWebservices\XML\XSDReader\SchemaReader; class AttributesTest extends BaseTest { @@ -146,38 +145,37 @@ public function testAttributeUseOverriding(): void self::assertEquals(AttributeSingle::USE_REQUIRED, $attribute->getUse()); } - public function testMetaInformation(): void + public function testCustomAttributesInformation(): void { $schema = $this->reader->readString( ' - + ' ); $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); self::assertInstanceOf(AttributeDef::class, $myAttribute); - $meta = $myAttribute->getMeta(); - self::assertCount(1, $meta); - self::assertEquals('meta', $meta[0]->getName()); - self::assertEquals('hello', $meta[0]->getValue()); - self::assertEquals('http://www.example.com', $meta[0]->getNamespaceURI()); - self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + $customAttributes = $myAttribute->getCustomAttributes(); + self::assertCount(1, $customAttributes); + self::assertEquals('customAttributes', $customAttributes[0]->getName()); + self::assertEquals('hello', $customAttributes[0]->getValue()); + self::assertEquals('http://www.example.com', $customAttributes[0]->getNamespaceURI()); } - public function testExternalSchemaReferencingMetaInformationPrefixed(): void + public function testExternalSchemaReferencingCustomAttributesInformationPrefixed(): void { $dom = new \DOMDocument(); $dom->loadXML( ' - + - + '); @@ -186,28 +184,27 @@ public function testExternalSchemaReferencingMetaInformationPrefixed(): void $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); self::assertInstanceOf(AttributeDef::class, $myAttribute); - $meta = $myAttribute->getMeta(); - self::assertCount(1, $meta); - self::assertEquals('metaType', $meta[0]->getName()); - self::assertEquals('xs:string', $meta[0]->getValue()); + $customAttributes = $myAttribute->getCustomAttributes(); + self::assertCount(1, $customAttributes); + self::assertEquals('customAttributesType', $customAttributes[0]->getName()); + self::assertEquals('xs:string', $customAttributes[0]->getValue()); - $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); - self::assertSame($refAttr->getSchema()->getTargetNamespace(), $meta[0]->getNamespaceURI()); - self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + $refAttr = $schema->findAttribute('customAttributesType', 'http://www.ref.com'); + self::assertSame($refAttr->getSchema()->getTargetNamespace(), $customAttributes[0]->getNamespaceURI()); } - public function testExternalSchemaReferencingMetaInformationUnprefixed(): void + public function testExternalSchemaReferencingCustomAttributesInformationUnprefixed(): void { $dom = new \DOMDocument(); $dom->loadXML( ' - + - + '); @@ -216,14 +213,13 @@ public function testExternalSchemaReferencingMetaInformationUnprefixed(): void $myAttribute = $schema->findAttribute('myAttribute', 'http://www.example.com'); self::assertInstanceOf(AttributeDef::class, $myAttribute); - $meta = $myAttribute->getMeta(); + $customAttributes = $myAttribute->getCustomAttributes(); - self::assertCount(1, $meta); - self::assertEquals('metaType', $meta[0]->getName()); - self::assertEquals('string', $meta[0]->getValue()); + self::assertCount(1, $customAttributes); + self::assertEquals('customAttributesType', $customAttributes[0]->getName()); + self::assertEquals('string', $customAttributes[0]->getValue()); - $refAttr = $schema->findAttribute('metaType', 'http://www.ref.com'); - self::assertSame($refAttr->getSchema()->getTargetNamespace(), $meta[0]->getNamespaceURI()); - self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + $refAttr = $schema->findAttribute('customAttributesType', 'http://www.ref.com'); + self::assertSame($refAttr->getSchema()->getTargetNamespace(), $customAttributes[0]->getNamespaceURI()); } } diff --git a/tests/ElementsTest.php b/tests/ElementsTest.php index 3a0a1dc1..2c9ca081 100644 --- a/tests/ElementsTest.php +++ b/tests/ElementsTest.php @@ -12,7 +12,6 @@ use GoetasWebservices\XML\XSDReader\Schema\Element\GroupRef; use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType; use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType; -use GoetasWebservices\XML\XSDReader\SchemaReader; class ElementsTest extends BaseTest { @@ -274,27 +273,26 @@ public function testSequenceElementDocs(): void self::assertSame('Alone description', $aloneElement->getDoc()); } - public function testMetaInformation(): void + public function testCustomAttributesInformation(): void { $schema = $this->reader->readString( ' - + ' ); $myElement = $schema->findElement('myElement', 'http://www.example.com'); self::assertInstanceOf(ElementDef::class, $myElement); - $meta = $myElement->getMeta(); - self::assertCount(1, $meta); - self::assertEquals('meta', $meta[0]->getName()); - self::assertEquals('hello', $meta[0]->getValue()); - self::assertEquals('http://www.example.com', $meta[0]->getNamespaceURI()); - self::assertSame(SchemaReader::XSD_NS, $meta[0]->getContextSchema()->getTargetNamespace()); + $customAttributes = $myElement->getCustomAttributes(); + self::assertCount(1, $customAttributes); + self::assertEquals('customAttributes', $customAttributes[0]->getName()); + self::assertEquals('hello', $customAttributes[0]->getValue()); + self::assertEquals('http://www.example.com', $customAttributes[0]->getNamespaceURI()); } - public function testDfdlElementMetaInformation(): void + public function testDfdlElementCustomAttributesInformation(): void { $schema = $this->reader->readString( ' @@ -315,28 +313,28 @@ public function testDfdlElementMetaInformation(): void $myElement = $schema->findElement('myElement', 'http://www.example.com'); self::assertInstanceOf(ElementDef::class, $myElement); - $meta = $myElement->getMeta(); + $customAttributes = $myElement->getCustomAttributes(); $namespaceUri = 'http://www.ogf.org/dfdl/dfdl-1.0/extensions'; - self::assertCount(5, $meta); - self::assertEquals($namespaceUri, $meta[0]->getNamespaceURI()); - self::assertEquals('encoding', $meta[0]->getName()); - self::assertEquals('iso-8859-1', $meta[0]->getValue()); + self::assertCount(5, $customAttributes); + self::assertEquals($namespaceUri, $customAttributes[0]->getNamespaceURI()); + self::assertEquals('encoding', $customAttributes[0]->getName()); + self::assertEquals('iso-8859-1', $customAttributes[0]->getValue()); - self::assertEquals($namespaceUri, $meta[1]->getNamespaceURI()); - self::assertEquals('initiator', $meta[1]->getName()); - self::assertEquals('UNA', $meta[1]->getValue()); + self::assertEquals($namespaceUri, $customAttributes[1]->getNamespaceURI()); + self::assertEquals('initiator', $customAttributes[1]->getName()); + self::assertEquals('UNA', $customAttributes[1]->getValue()); - self::assertEquals($namespaceUri, $meta[2]->getNamespaceURI()); - self::assertEquals('length', $meta[2]->getName()); - self::assertEquals('6', $meta[2]->getValue()); + self::assertEquals($namespaceUri, $customAttributes[2]->getNamespaceURI()); + self::assertEquals('length', $customAttributes[2]->getName()); + self::assertEquals('6', $customAttributes[2]->getValue()); - self::assertEquals($namespaceUri, $meta[3]->getNamespaceURI()); - self::assertEquals('lengthKind', $meta[3]->getName()); - self::assertEquals('explicit', $meta[3]->getValue()); + self::assertEquals($namespaceUri, $customAttributes[3]->getNamespaceURI()); + self::assertEquals('lengthKind', $customAttributes[3]->getName()); + self::assertEquals('explicit', $customAttributes[3]->getValue()); - self::assertEquals($namespaceUri, $meta[4]->getNamespaceURI()); - self::assertEquals('terminator', $meta[4]->getName()); - self::assertEquals('%NL;%WSP*; %WSP*;', $meta[4]->getValue()); + self::assertEquals($namespaceUri, $customAttributes[4]->getNamespaceURI()); + self::assertEquals('terminator', $customAttributes[4]->getName()); + self::assertEquals('%NL;%WSP*; %WSP*;', $customAttributes[4]->getValue()); } } From 52e3f6344fbdac1a469e3d74c8e12d056409f65b Mon Sep 17 00:00:00 2001 From: Github Actions Bot <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 06:22:35 +0000 Subject: [PATCH 6/6] Update code coverage badge --- clover.xml | 2129 ++++++++++++++++++++++++++-------------------------- 1 file changed, 1085 insertions(+), 1044 deletions(-) diff --git a/clover.xml b/clover.xml index 05f71659..2bb0e8c8 100644 --- a/clover.xml +++ b/clover.xml @@ -1,6 +1,6 @@ - - + + @@ -8,17 +8,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -37,42 +37,42 @@ - - - + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -87,8 +87,8 @@ - - + + @@ -106,9 +106,9 @@ - - - + + + @@ -118,7 +118,7 @@ - + @@ -126,43 +126,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -185,8 +214,8 @@ - - + + @@ -210,19 +239,19 @@ - - - + + + - - + + - + @@ -234,17 +263,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -277,14 +306,14 @@ - - - - - - - - + + + + + + + + @@ -311,9 +340,9 @@ - - - + + + @@ -326,8 +355,8 @@ - - + + @@ -341,158 +370,158 @@ - - - + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - - + + - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + @@ -502,12 +531,12 @@ - - + + - - + + @@ -522,9 +551,9 @@ - - - + + + @@ -537,866 +566,878 @@ - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + @@ -1442,6 +1483,6 @@ - +