/**
  * Create the OperatorProcessor relevant to the given $expression.
  *
  * @param \qtism\data\expressions\Expression $expression The Operator object you want to get the processor.
  * @param \qtism\runtime\expressions\operators\OperandsCollection $operands The operands to be involved in the Operator object.
  * @return \qtism\runtime\expressions\operators\OperatorProcessor An OperatorProcessor object ready to process $expression.
  * @throws \qtism\runtime\expressions\operators\OperatorProcessingException If the $operands count is not compliant with the Operator object to be processed.
  * @throws \InvalidArgumentException If $expression is not an Operator object.
  * @throws \RuntimeException If no relevant OperatorProcessor is found for the given $expression.
  */
 public function createProcessor(QtiComponent $expression, OperandsCollection $operands = null)
 {
     if ($expression instanceof Operator) {
         if ($expression instanceof CustomOperator) {
             // QTI custom operator. Try to load an autoloaded class by using
             // its class attribute value.
             if ($expression->hasClass() === true) {
                 $className = Utils::customOperatorClassToPhpClass($expression->getClass());
                 if (class_exists($className) === true) {
                     return new $className($expression, $operands);
                 } else {
                     $msg = "No custom operator implementation found for class '" . $expression->getClass() . "'.";
                     throw new RuntimeException($msg);
                 }
             } else {
                 $msg = "Only custom operators with a 'class' attribute value can be processed.";
                 throw new RuntimeException($msg);
             }
         } else {
             // QTI built-in operator.
             $qtiClassName = ucfirst($expression->getQtiClassName());
             $nsPackage = 'qtism\\runtime\\expressions\\operators\\';
             $className = $nsPackage . $qtiClassName . 'Processor';
             if (class_exists($className)) {
                 if (is_null($operands) === true) {
                     $operands = new OperandsCollection();
                 }
                 return new $className($expression, $operands);
             } else {
                 $msg = "No dedicated OperatorProcessor class found for QTI operator '{$qtiClassName}'.";
                 throw new RuntimeException($msg);
             }
         }
     } else {
         $msg = "The OperatorProcessorFactory only accepts to create processors for Operator objects.";
         throw new InvalidArgumentException($msg);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::marshallChildrenKnown()
  */
 protected function marshallChildrenKnown(QtiComponent $component, array $elements)
 {
     $element = self::getDOMCradle()->createElement($component->getQtiClassName());
     foreach ($elements as $elt) {
         $element->appendChild($elt);
     }
     if ($component instanceof CustomOperator) {
         if ($component->hasClass() === true) {
             self::setDOMElementAttribute($element, 'class', $component->getClass());
         }
         if ($component->hasDefinition() === true) {
             self::setDOMElementAttribute($element, 'definition', $component->getDefinition());
         }
         // Now, we have to extract the LAX content of the custom operator and put it into
         // what we are putting out. (It is possible to have no LAX content at all, it is not mandatory).
         $xml = $component->getXml();
         $operatorElt = $xml->documentElement->cloneNode(true);
         $qtiOperatorElts = self::getChildElementsByTagName($operatorElt, array_merge(self::getOperators(), self::getExpressions()));
         foreach ($qtiOperatorElts as $qtiOperatorElt) {
             $operatorElt->removeChild($qtiOperatorElt);
         }
         Utils::importChildNodes($operatorElt, $element);
         Utils::importAttributes($operatorElt, $element);
     }
     return $element;
 }