private function parseMapping(SimpleXMLElement $xml, PiBX_AST_Tree $part) { $nodes = $xml->xpath('./*'); foreach ($nodes as &$child) { $name = (string) $child->getName(); $attributes = $child->attributes(); if ($name == 'collection') { $name = (string) $attributes['name']; $setter = (string) $attributes['set-method']; $getter = (string) $attributes['get-method']; $newPart = new PiBX_AST_Collection($name); $newPart->setSetMethod($setter); $newPart->setGetMethod($getter); $class = (string) $attributes['class']; $this->classMap[$name] = $class; $this->elementAsts[$name] = $newPart; $this->parseMapping($child, $newPart); } elseif ($name == 'structure') { $name = (string) $attributes['name']; if ($part instanceof PiBX_AST_Collection) { // a structure in a collection is a reference to the actual structure $referencedType = (string) $attributes['map-as']; $type = $this->getClassnameForName($referencedType); $newPart = new PiBX_AST_Structure($name); $newPart->setType($type); $this->structuralReferences[$referencedType] = $name; } elseif ($part instanceof PiBX_AST_Type) { $referencedType = (string) $attributes['map-as']; $type = $this->getClassnameForName($referencedType); // a structure in a type is the structure "container" $newPart = new PiBX_AST_Structure($name, $type); $getMethod = (string) $attributes['get-method']; $setMethod = (string) $attributes['set-method']; $newPart->setGetMethod($getMethod); $newPart->setSetMethod($setMethod); } elseif ($part instanceof PiBX_AST_Structure) { $ordered = (string) $attributes['ordered']; $ordered = strtolower($ordered); $choice = (string) $attributes['choice']; $choice = strtolower($choice); if ($ordered == 'true' && $choice == 'false') { $part->setStructureType(PiBX_AST_StructureType::ORDERED()); } elseif ($ordered == 'false' && $choice == 'true') { $part->setStructureType(PiBX_AST_StructureType::CHOICE()); } else { throw new RuntimeException('Invalid structure state!'); } $structureValues = $child->xpath('./*'); // this handling is a bit clunky but needed, // since the choice structures are defined // somewhat redundant in the binding.xml foreach ($structureValues as &$struct) { $valueName = (string) $struct->getName(); if ($valueName != 'value') { throw new RuntimeException('No value-element within the structure.'); } $attributes = $struct->attributes(); $nameAttribute = (string) $attributes['name']; $newPart = new PiBX_AST_StructureElement($nameAttribute); $style = (string) $attributes['style']; $testMethod = (string) $attributes['test-method']; $getMethod = (string) $attributes['get-method']; $setMethod = (string) $attributes['set-method']; $newPart->setStyle($style); $newPart->setTestMethod($testMethod); $newPart->setGetMethod($getMethod); $newPart->setSetMethod($setMethod); $part->add($newPart); $this->elementAsts[$nameAttribute] = $newPart; } // no further processing needed // all structure values have been added break; } $this->elementAsts[$name] = $newPart; $this->parseMapping($child, $newPart); } elseif ($name == 'value') { $name = (string) $attributes['name']; if ($part instanceof PiBX_AST_Collection) { $newPart = new PiBX_AST_CollectionItem($name); } elseif ($part instanceof PiBX_AST_Type) { $newPart = new PiBX_AST_TypeAttribute($name); $style = (string) $attributes['style']; $setMethod = (string) $attributes['set-method']; $getMethod = (string) $attributes['get-method']; $newPart->setStyle($style); $newPart->setSetMethod($setMethod); $newPart->setGetMethod($getMethod); } $this->elementAsts[$name] = $newPart; } else { throw new InvalidArgumentException('Unexpected binding element "' . $name . '"'); } $part->add($newPart); } }
/** * * @param SimpleXMLElement $xml * @param PiBX_AST_Structure $ast * @param object $parentObject */ private function parseStructure(SimpleXMLElement $xml, PiBX_AST_Structure $ast, $parentObject) { $name = $ast->getName(); $type = $ast->getType(); if ($type == '') { if ($ast->getStructureType() === PiBX_AST_StructureType::CHOICE()) { return $this->parseChoiceStructure($xml, $ast, $parentObject); } elseif ($ast->getStructureType() === PiBX_AST_StructureType::ORDERED()) { throw new RuntimeException('Not supported yet.'); } else { throw new RuntimeException('Invalid <structure>.'); } } else { // a structure with a type is a reference to the type if (!PiBX_ParseTree_BaseType::isBaseType($type)) { $structAst = $this->binding->getASTForClass($type); $newObject = new $type(); $parsedObject = $this->parseXml($xml, $structAst, $newObject); $setter = $ast->getSetMethod(); $parentObject->{$setter}($parsedObject); } else { return $parentObject; } } }
private function marshalStructure($object, PiBX_AST_Structure $ast) { $lastNode = $this->parentDomNode; if ($ast->getStructureType() === PiBX_AST_StructureType::CHOICE()) { $this->parentDomNode = $this->currentDomNode; if ($ast->hasChildren()) { $childrenCount = $ast->countChildren(); $currentChoice = null; for ($i = 0; $i < $childrenCount; $i++) { $child = $ast->get($i); $testMethod = $child->getTestMethod(); if ($object->{$testMethod}()) { $currentChoice = $child; break; } } $this->marshalObject($object, $currentChoice); } } elseif ($ast->getStructureType() === PiBX_AST_StructureType::ORDERED()) { throw new RuntimeException('Currently not supported.'); } else { $this->parentDomNode->removeChild($this->currentDomNode); // when a structure has no type, it is a referenced complex-type // used as a type-attribute $getter = $ast->getGetMethod(); $obj = $object->{$getter}(); $classname = $this->binding->getClassnameForName($ast->getName()); $structureAst = $this->binding->getASTForClass($classname); $this->marshalObject($obj, $structureAst); } $this->parentDomNode = $lastNode; }