<commit_before><?php
/* This class is part of the XP framework's experiments
 *
 * $Id$ 
 */

  uses('xml.XPath', 'xml.XMLFormatException');

  /**
   * Creates objects from XML by using annotations.
   *
   * Example:
   * <code>
   *   // [...load $xml from a file or a stream...]
   *
   *   try(); {
   *     $t= &Unmarshaller::unmarshal($xml, 'com.1and1.qf.xml.types.TransmissionType');
   *   } if (catch('Exception', $e)) {
   *     $e->printStackTrace();
   *     exit(-1);
   *   }
   *
   *   echo $t->toString();
   * </code>
   *
   * @test     xp://net.xp_framework.unittest.xml.UnmarshallerTest
   * @ext      dom
   * @see      http://castor.org/xml-mapping.html
   * @purpose  XML databinding
   */
  class Unmarshaller extends Object {

    /**
     * Retrieve content of a DomElement
     *
     * @model   static
     * @access  protected
     * @param   &php.DomElement element
     * @return  string
     */
    function contentOf(&$element) {
      switch ($element->type) {
        case 1:   // Nodeset
          return empty($element->nodeset) ? NULL : utf8_decode($element->nodeset[0]->get_content());
          break;

        case 3:   // Text
          return utf8_decode($element->content);

        case 2:   // Attribute
        case 4:   // String
          return utf8_decode($element->value);
          break;

        default:
          return NULL;
      }
    }

    /**
     * Recursively unmarshal
     *
     * @model   static
     * @access  protected
     * @param   &xml.XPath xpath
     * @param   &php.DomElement context
     * @param   string classname
     * @return  &lang.Object
     * @throws  lang.ClassNotFoundException
     * @throws  xml.XPathException
     */
    function &recurse(&$xpath, &$context, $classname) {
      try(); {
        $class= &XPClass::forName($classname);
      } if (catch('ClassNotFoundException', $e)) {
        return throw($e);
      }

      $instance= &$class->newInstance();
      foreach ($class->getMethods() as $method) {
        if (!$method->hasAnnotation('xmlmapping', 'element')) continue;

        // Perform XPath query
        try(); {
          $result= &$xpath->query($method->getAnnotation('xmlmapping', 'element'), $context);
        } if (catch('XPathException', $e)) {
          return throw($e);
        }

        // Iterate over results, invoking the method for each node.
        foreach ($result->nodeset as $node) {
          if ($method->hasAnnotation('xmlmapping', 'class')) {

            // * If the xmlmapping annotation has a key "class", call recurse()
            //   with the given XPath, the node as context and the key's value
            //   as classname
            $arguments= array(Unmarshaller::recurse(
              $xpath, 
              $node, 
              $method->getAnnotation('xmlmapping', 'class')
            ));
          } else if ($method->hasAnnotation('xmlmapping', 'factory')) {

            // * If the xmlmapping annotation has a key "factory", call recurse()
            //   with the given XPath, the node as context and the results from
            //   the specified method as class name. The specified factory method 
            //   is passed the node's tag name if no "pass" key is available.
            //   In case it is, call the factory method with the arguments 
            //   constructed from the "pass" key.
            if ($method->getAnnotation('xmlmapping', 'pass')) {
              $factoryArgs= array();
              foreach ($method->getAnnotation('xmlmapping', 'pass') as $pass) {
                $factoryArgs[]= Unmarshaller::contentOf($xpath->query($pass, $node));
              }
            } else {
              $factoryArgs= array($node->tagname);
            }
            $arguments= array(Unmarshaller::recurse(
              $xpath, 
              $node, 
              call_user_func_array(
                array(&$instance, $method->getAnnotation('xmlmapping', 'factory')), 
                $factoryArgs
              )
            ));
          } else if ($method->hasAnnotation('xmlmapping', 'pass')) {
          <commit_msg>- Use hasAnnotation() to check for whether an annotation is available   rather than getAnnotation()<commit_after><?php
/* This class is part of the XP framework's experiments
 *
 * $Id$ 
 */

  uses('xml.XPath', 'xml.XMLFormatException');

  /**
   * Creates objects from XML by using annotations.
   *
   * Example:
   * <code>
   *   // [...load $xml from a file or a stream...]
   *
   *   try(); {
   *     $t= &Unmarshaller::unmarshal($xml, 'com.1and1.qf.xml.types.TransmissionType');
   *   } if (catch('Exception', $e)) {
   *     $e->printStackTrace();
   *     exit(-1);
   *   }
   *
   *   echo $t->toString();
   * </code>
   *
   * @test     xp://net.xp_framework.unittest.xml.UnmarshallerTest
   * @ext      dom
   * @see      http://castor.org/xml-mapping.html
   * @purpose  XML databinding
   */
  class Unmarshaller extends Object {

    /**
     * Retrieve content of a DomElement
     *
     * @model   static
     * @access  protected
     * @param   &php.DomElement element
     * @return  string
     */
    function contentOf(&$element) {
      switch ($element->type) {
        case 1:   // Nodeset
          return empty($element->nodeset) ? NULL : utf8_decode($element->nodeset[0]->get_content());
          break;

        case 3:   // Text
          return utf8_decode($element->content);

        case 2:   // Attribute
        case 4:   // String
          return utf8_decode($element->value);
          break;

        default:
          return NULL;
      }
    }

    /**
     * Recursively unmarshal
     *
     * @model   static
     * @access  protected
     * @param   &xml.XPath xpath
     * @param   &php.DomElement context
     * @param   string classname
     * @return  &lang.Object
     * @throws  lang.ClassNotFoundException
     * @throws  xml.XPathException
     */
    function &recurse(&$xpath, &$context, $classname) {
      try(); {
        $class= &XPClass::forName($classname);
      } if (catch('ClassNotFoundException', $e)) {
        return throw($e);
      }

      $instance= &$class->newInstance();
      foreach ($class->getMethods() as $method) {
        if (!$method->hasAnnotation('xmlmapping', 'element')) continue;

        // Perform XPath query
        try(); {
          $result= &$xpath->query($method->getAnnotation('xmlmapping', 'element'), $context);
        } if (catch('XPathException', $e)) {
          return throw($e);
        }

        // Iterate over results, invoking the method for each node.
        foreach ($result->nodeset as $node) {
          if ($method->hasAnnotation('xmlmapping', 'class')) {

            // * If the xmlmapping annotation has a key "class", call recurse()
            //   with the given XPath, the node as context and the key's value
            //   as classname
            $arguments= array(Unmarshaller::recurse(
              $xpath, 
              $node, 
              $method->getAnnotation('xmlmapping', 'class')
            ));
          } else if ($method->hasAnnotation('xmlmapping', 'factory')) {

            // * If the xmlmapping annotation has a key "factory", call recurse()
            //   with the given XPath, the node as context and the results from
            //   the specified method as class name. The specified factory method 
            //   is passed the node's tag name if no "pass" key is available.
            //   In case it is, call the factory method with the arguments 
            //   constructed from the "pass" key.
            if ($method->hasAnnotation('xmlmapping', 'pass')) {
              $factoryArgs= array();
              foreach ($method->getAnnotation('xmlmapping', 'pass') as $pass) {
                $factoryArgs[]= Unmarshaller::contentOf($xpath->query($pass, $node));
              }
            } else {
              $factoryArgs= array($node->tagname);
            }
            $arguments= array(Unmarshaller::recurse(
              $xpath, 
              $node, 
              call_user_func_array(
                array(&$instance, $method->getAnnotation('xmlmapping', 'factory')), 
                $factoryArgs
              )
            ));
          } else if ($method->hasAnnotation('xmlmapping', 'pass')) {
          
{'fraction_non_alphanumeric': 0.1365824308062575, 'fraction_numerical': 0.002647412755716005, 'mean_word_length': 1.8668506381510865, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 40}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2876287', 'n_tokens_mistral': 2382, 'n_tokens_neox': 2321, 'n_words': 599}