<?php

/**
 * OpenKM, Open Knowledge Management System S.L.  (http://www.openkm.com)
 * Copyright (c) 2006-2018
 *
 * No bytes were intentionally harmed during the development of this application.
 *
 * This program is commercial software; you can use it under the terms of the
 * EULA - OpenKM SDK End User License Agreement as published by OpenKM Knowledge Management System S.L.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * EULA - OpenKM SDK End User License Agreement for more details:
 * http://docs.openkm.com/kcenter/view/licenses/eula-openkm-sdk-end-user-license-agreement.html
 */

namespace openkm\impl;

use Httpful\Mime;
use Httpful\Request;
use openkm\bean\Document;
use openkm\bean\Mail;
use openkm\bean\Folder;
use openkm\bean\Record;
use openkm\bean\LockInfo;
use openkm\bean\Version;
use openkm\bean\Note;
use openkm\bean\ContentInfo;
use openkm\bean\FormElementComplex;
use openkm\bean\PropertyGroup;
use openkm\bean\form\Option;
use openkm\bean\form\Validator;
use openkm\bean\RelationGroup;
use openkm\bean\Relation;
use openkm\bean\RelationType;
use openkm\bean\Token;
use openkm\bean\Transition;
use openkm\bean\Comment;
use openkm\bean\Entry;
use openkm\bean\TaskNote;
use openkm\bean\TaskType;
use openkm\bean\TaskProject;
use openkm\bean\TaskStatus;
use openkm\bean\Task;
use openkm\bean\QueryParams;
use openkm\bean\QueryResult;
use openkm\bean\SimplePropertyGroup;
use openkm\bean\RestException;
use openkm\bean\LocalDateTime;
use openkm\bean\Node;
use openkm\bean\NoteHistory;

class ClientImpl {

    protected $host;
    protected $user;
    protected $password;
    protected $authorizationToken;

    /**
     * Construct
     */
    public function __construct($host) {
        $this->host = $host;
    }

    /**
     * setAuthenticationToken
     */
    public function setAuthorizationToken($authorizationToken) {
        $this->authorizationToken = $authorizationToken;
    }

    /**
     * getClient
     */
    public function getClient(Request $client) {
        $client->sends(Mime::JSON);
        $client->addHeader('Authorization', $this->authorizationToken);
        $client->expects(Mime::JSON);
        return $client->send();
    }

    /**
     * getClientWithUploadResponse
     */
    public function getClientWithUploadResponse(Request $client) {
        $client->sends(Mime::JSON);
        $client->expects(Mime::UPLOAD);
        $client->addHeader('Authorization', $this->authorizationToken);
        return $client->send();
    }

    /**
     * getClientWithHTMLResponse
     */
    public function getClientWithHTMLResponse(Request $client) {
        $client->sends(Mime::JSON);
        $client->expects(Mime::HTML);
        $client->addHeader('Authorization', $this->authorizationToken);
        return $client->send();
    }

    /**
     * getClientWithPlainResponse     
     */
    public function getClientWithPlainResponse(Request $client) {
        $client->sends(Mime::JSON);
        $client->expects(Mime::PLAIN);
        $client->addHeader('Authorization', $this->authorizationToken);
        return $client->send();
    }

    /**
     * getClientWithPlainResponse     
     */
    public function getClientWithṔarams(Request $client, $params) {
        $client->sends(Mime::FORM);
        $client->body($params);
        $client->expects(Mime::JSON);
        $client->addHeader('Authorization', $this->authorizationToken);
        return $client->send();
    }

    public function getClientWithBody(Request $client, $body) {
        $client->sends(Mime::JSON);
        $client->body(json_encode($body));
        $client->expects(Mime::JSON);
        $client->addHeader('Authorization', $this->authorizationToken);
        return $client->send();
    }

    public function phpNode($nodeJSON) {
        $node = new Node();
        $node->setCreated((string) $nodeJSON->created);
        $node->setLastModified((string) $nodeJSON->lastModified);
        $node->setPath((string) $nodeJSON->path);
        $node->setAuthor((string) $nodeJSON->author);
        $node->setPermissions((int) $nodeJSON->permissions);
        $node->setUuid((string) $nodeJSON->uuid);
        $node->setParent((string) $nodeJSON->parent);
        $node->setSubscribed((string) $nodeJSON->subscribed);
        $node->setNodeClass((int) $nodeJSON->nodeClass);
        $node->setDispositionCurrentStage((int) $nodeJSON->dispositionCurrentStage);

        if ($nodeJSON->hasRelations == 'true') {
            $node->setHasRelations(true);
        } else {
            $node->setHasRelations(true);
        }

        //Version        
        $node->setActualVersion($this->phpVersion($nodeJSON->actualVersion));

        $node->setCheckedOut((string) $nodeJSON->checkedOut);
        $node->setConvertibleToPdf((string) $nodeJSON->convertibleToPdf);
        $node->setDescription((string) $nodeJSON->description);
        $node->setLanguage((string) $nodeJSON->language);

        //LockInfo        
        if ($nodeJSON->lockInfo) {
            $node->setLockInfo($this->phpLockInfo($nodeJSON->lockInfo));
        }

        $node->setLocked((string) $nodeJSON->locked);
        $node->setMimeType((string) $nodeJSON->mimeType);
        $node->setSigned((string) $nodeJSON->signed);
        $node->setTitle((string) $nodeJSON->title);

        //categories
        $categories = [];
        foreach ($nodeJSON->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $node->setCategories($categories);
        //keywords
        $keywords = [];
        foreach ($nodeJSON->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $node->setKeywords($keywords);
        //notes
        $notes = [];
        foreach ($nodeJSON->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $node->setNotes($notes);

        $subscriptors = [];
        foreach ($nodeJSON->subscriptors as $subscriptor) {
            $subscriptors[] = $subscriptor;
        }
        $node->setSubscriptors($subscriptors);
        return $node;
    }

    /**
     * Parse XML a Document
     * 
     * @param type $documentJSON
     * @return \openkm\impl\Document Returns a Document
     */
    public function phpDocument($documentJSON) {
        $document = new Document();
        $document->setCreated((string) $documentJSON->created);
        $document->setLastModified((string) $documentJSON->lastModified);
        $document->setPath((string) $documentJSON->path);
        $document->setAuthor((string) $documentJSON->author);
        $document->setPermissions((int) $documentJSON->permissions);
        $document->setUuid((string) $documentJSON->uuid);
        $document->setParent((string) $documentJSON->parent);
        $document->setSubscribed((string) $documentJSON->subscribed);
        $document->setNodeClass((int) $documentJSON->nodeClass);
        $document->setDispositionCurrentStage((int) $documentJSON->dispositionCurrentStage);

        //Version        
        $document->setActualVersion($this->phpVersion($documentJSON->actualVersion));
        $document->setPromotedAsRecord($documentJSON->promotedAsRecord);
        $document->setHasRelations($documentJSON->hasRelations);
        $document->setDescription((string) $documentJSON->description);
        $document->setRestricted((string) $documentJSON->restricted);
        $document->setLocked((string) $documentJSON->locked);
        if ($documentJSON->template != null) {
            $document->setTemplate($documentJSON->template);
        }

        $document->setTitle((string) $documentJSON->title);
        $document->setLanguage((string) $documentJSON->language);
        $document->setMimeType((string) $documentJSON->mimeType);
        $document->setCheckedOut((string) $documentJSON->checkedOut);
        $document->setSigned((string) $documentJSON->signed);
        $document->setConvertibleToPdf((string) $documentJSON->convertibleToPdf);
        if ($documentJSON->cipherName) {
            $document->setCipherName((string) $documentJSON->cipherName);
        }

        //LockInfo        
        if ($documentJSON->lockInfo) {
            $document->setLockInfo($this->phpLockInfo($documentJSON->lockInfo));
        }

        //categories
        $categories = [];
        foreach ($documentJSON->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $document->setCategories($categories);
        //keywords
        $keywords = [];
        foreach ($documentJSON->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $document->setKeywords($keywords);
        //notes
        $notes = [];
        foreach ($documentJSON->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $document->setNotes($notes);
        $subscriptors = [];
        foreach ($documentJSON->subscriptors as $subscriptor) {
            $subscriptors[] = $subscriptor;
        }
        $document->setSubscriptors($subscriptors);
        return $document;
    }

    /**
     * Parse the XML a class
     * @param  \SimpleXMLElement $folderJSON
     * @return \openkm\bean\Folder
     */
    public function phpFolderComplete($folderJSON) {
        $folder = $this->phpFolder($folderJSON);
        $categories = [];
        foreach ($folderJSON->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $folder->setCategories($categories);
        $keywords = [];
        foreach ($folderJSON->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $folder->setKeywords($keywords);
        $notes = [];
        foreach ($folderJSON->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $folder->setNotes($notes);
        $subscriptors = [];
        foreach ($folderJSON->subscriptors as $subscriptor) {
            $subscriptors[] = $subscriptor;
        }
        $folder->setSubscriptors($subscriptors);
        if ($folderJSON->hasRelations == 'true') {
            $folder->setHasRelations(true);
        } else {
            $folder->setHasRelations(true);
        }
        return $folder;
    }

    public function phpMail($mailXML) {
        $mail = new Mail();
        $mail->setAuthor((string) $mailXML->author);
        $mail->setCreated((string) $mailXML->created);
        $mail->setNodeClass((int) $mailXML->nodeClass);
        $mail->setPath((string) $mailXML->path);
        $mail->setPermissions((int) $mailXML->permissions);
        $mail->setSubscribed((string) $mailXML->subscribed);
        $mail->setUuid((string) $mailXML->uuid);
        if ($mailXML->hasRelations == 'true') {
            $mail->setHasRelations(true);
        } else {
            $mail->setHasRelations(true);
        }

        $mail->setTitle((string) $mailXML->title);
        $mail->setFrom((string) $mailXML->from);
        $mail->setSentDate((string) $mailXML->sentDate);
        $mail->setReceivedDate((string) $mailXML->receivedDate);
        $mail->setSubject((string) $mailXML->subject);
        $mail->setContent((string) $mailXML->content);
        $mail->setMimeType((string) $mailXML->mimeType);
        $mail->setHeaders((string) $mailXML->headers);
        $mail->setRaw((string) $mailXML->raw);
        $mail->setOrigin((string) $mailXML->origin);
        $mail->setSize((int) $mailXML->size);
        $mail->setHasAttachments((string) $mailXML->hasAttachments);
        //reply
        $replyArray = [];
        foreach ($mailXML->reply as $reply) {
            $replyArray[] = $reply;
        }
        $mail->setReply($replyArray);
        //to
        $toArray = [];
        foreach ($mailXML->to as $to) {
            $toArray[] = $to;
        }
        $mail->setTo($toArray);
        //cc
        $ccArray = [];
        foreach ($mailXML->cc as $cc) {
            $ccArray[] = $cc;
        }
        $mail->setCc($ccArray);
        //bcc
        $bccArray = [];
        foreach ($mailXML->bcc as $bcc) {
            $bccArray[] = $bcc;
        }
        $mail->setBcc($bccArray);
        //categories
        $categories = [];
        foreach ($mailXML->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $mail->setCategories($categories);
        //keywords
        $keywords = [];
        foreach ($mailXML->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $mail->setKeywords($keywords);
        //notes
        $notes = [];
        foreach ($mailXML->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $mail->setNotes($notes);
        return $mail;
    }

    public function phpRecord($recordXML) {
        $record = new Record();
        $record->setAuthor((string) $recordXML->author);
        $record->setCreated((string) $recordXML->created);
        $record->setNodeClass((int) $recordXML->nodeClass);
        $record->setPath((string) $recordXML->path);
        $record->setPermissions((int) $recordXML->permissions);
        $record->setSubscribed((string) $recordXML->subscribed);
        $record->setUuid((string) $recordXML->uuid);
        if ($recordXML->hasRelations == 'true') {
            $record->setHasRelations(true);
        } else {
            $record->setHasRelations(true);
        }

        //LockInfo        
        $record->setLockInfo($this->phpLockInfo($recordXML->lockInfo));
        $record->setLocked((string) $recordXML->locked);
        $record->setTitle((string) $recordXML->title);

        //categories
        $categories = [];
        foreach ($recordXML->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $record->setCategories($categories);
        //keywords
        $keywords = [];
        foreach ($recordXML->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $record->setKeywords($keywords);
        //notes
        $notes = [];
        foreach ($recordXML->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $record->setNotes($notes);
        $subscriptors = [];
        foreach ($recordXML->subscriptors as $subscriptor) {
            $subscriptors[] = $subscriptor;
        }
        $record->setSubscriptors($subscriptors);
        return $record;
    }

    public function phpVersion($versionJSON) {
        $version = new Version();
        $version->setName((string) $versionJSON->name);
        $version->setCreated((string) $versionJSON->created);
        $version->setSize((string) $versionJSON->size);
        $version->setAuthor((string) $versionJSON->author);
        $version->setActual((string) $versionJSON->actual);
        if ($versionJSON->comment != null) {
            $version->setComment((string) $versionJSON->comment);
        }
        $version->setChecksum((string) $versionJSON->checksum);
        $version->setAction($versionJSON->action);
        if ($versionJSON->params != null) {
            $version->setParams($versionJSON->params);
        }
        $version->setUuid($versionJSON->uuid);
        $version->setParent($versionJSON->parent);
        return $version;
    }

    public function phpLockInfo($lockInfoXML) {
        $lockInfo = new LockInfo();
        $lockInfo->setNodePath((string) $lockInfoXML->nodePath);
        $lockInfo->setOwner((string) $lockInfoXML->owner);
        return $lockInfo;
    }

    public function phpFolder($folderJSON) {
        $folder = new Folder();
        $folder->setCreated((string) $folderJSON->created);
        $folder->setLastModified((string) $folderJSON->lastModified);
        $folder->setPath((string) $folderJSON->path);
        $folder->setAuthor((string) $folderJSON->author);
        $folder->setPermissions((int) $folderJSON->permissions);
        $folder->setUuid((string) $folderJSON->uuid);
        $folder->setParent((string) $folderJSON->parent);
        $folder->setSubscribed((string) $folderJSON->subscribed);
        $folder->setNodeClass((int) $folderJSON->nodeClass);
        $folder->setDispositionCurrentStage((int) $folderJSON->dispositionCurrentStage);

        $subscriptors = [];
        foreach ($folderJSON->subscriptors as $subscriptor) {
            $subscriptors[] = $subscriptor;
        }
        $folder->setSubscriptors($subscriptors);

        //keywords
        $keywords = [];
        foreach ($folderJSON->keywords as $keywordJSON) {
            $keywords[] = (string) $keywordJSON;
        }
        $folder->setKeywords($keywords);

        //categories
        $categories = [];
        foreach ($folderJSON->categories as $categoryJSON) {
            $categories[] = $this->phpFolder($categoryJSON);
        }
        $folder->setCategories($categories);

        //notes
        $notes = [];
        foreach ($folderJSON->notes as $noteJSON) {
            $notes[] = $this->phpNote($noteJSON);
        }
        $folder->setNotes($notes);

        // Version
        $folder->setActualVersion($this->phpVersion($folderJSON->actualVersion));
        $folder->setPromotedAsRecord($folderJSON->promotedAsRecord);
        $folder->setHasRelations($folderJSON->hasRelations);
        $folder->setDescription((string) $folderJSON->description);
        $folder->setRestricted((string) $folderJSON->restricted);
        $folder->setLocked((string) $folderJSON->locked);
        if ($folderJSON->template != null) {
            $folder->setTemplate($folderJSON->template);
        }
        //LockInfo        
        if ($folderJSON->lockInfo) {
            $folder->setLockInfo($this->phpLockInfo($folderJSON->lockInfo));
        }

        $nodeClassChildren = [];
        foreach ($folderJSON->nodeClassChildren as $nodeClassChildrenJSON) {
            $nodeClassChildren[] = (string) $nodeClassChildrenJSON;
        }
        $folder->setNodeClassChildren($nodeClassChildren);

        $folder->setHasChildren($folderJSON->hasChildren);
        if ($folderJSON->metadataLabel != null) {
            $folder->setMetadataLabel($folderJSON->metadataLabel);
        }
        $folder->setStyle((int) $folderJSON->style);
        return $folder;
    }

    public function phpContentInfo($contentInfoXML) {
        $contentInfo = new ContentInfo();
        $contentInfo->setFolders((int) $contentInfoXML->folders);
        $contentInfo->setDocuments((int) $contentInfoXML->documents);
        $contentInfo->setMails((int) $contentInfoXML->mails);
        $contentInfo->setRecords((int) $contentInfoXML->records);
        $contentInfo->setSize((int) $contentInfoXML->size);
        return $contentInfo;
    }

    public function phpNote($noteJSON) {
        $note = new Note();
        $note->setAuthor((string) $noteJSON->author);
        $note->setDate((string) $noteJSON->date);
        $note->setPath((string) $noteJSON->path);
        $note->setText((string) $noteJSON->text);
        return $note;
    }

    public function phpNoteHistory($noteHistoryJSON) {
        $noteHistory = new NoteHistory();
        $noteHistory->setId((string) $noteHistoryJSON->id);
        $noteHistory->setDate($noteHistoryJSON->date);
        $noteHistory->setAuthor($noteHistoryJSON->author);
        $noteHistory->setText($noteHistoryJSON->text);
        $noteHistory->setPath($noteHistoryJSON->path);
        $noteHistory->setAction((string) $noteHistoryJSON->action);
        return $noteHistory;
    }

    public function phpPropertyGroup($propertyGroupJson) {
        $propertyGroup = new PropertyGroup();
        $propertyGroup->setLabel((string) $propertyGroupJson->label);
        $propertyGroup->setName((string) $propertyGroupJson->name);
        if ((string) $propertyGroupJson->readonly == 'true') {
            $propertyGroup->setReadonly(true);
        } else {
            $propertyGroup->setReadonly(false);
        }
        if ($propertyGroupJson->visible == 'true') {
            $propertyGroup->setVisible(true);
        } else {
            $propertyGroup->setVisible(false);
        }
        $propertyGroup->setValidatorClassName($propertyGroupJson->validatorClassName);
        return $propertyGroup;
    }

    public function phpSimplePropertyGroup($simplePropertyGroupJson) {
        $simplepropertyGroup = new SimplePropertyGroup();
        $simplepropertyGroup->setName((string) $simplePropertyGroupJson->name);
        $simplepropertyGroup->setValue((string) $simplePropertyGroupJson->value);
        return $simplepropertyGroup;
    }

    public function phpFormElementComplex($formElementComplexJson) {
        $formElementComplex = new FormElementComplex();
        $formElementComplex->setObjClass((string) $formElementComplexJson->objClass);
        $formElementComplex->setLabel((string) $formElementComplexJson->label);
        $formElementComplex->setName((string) $formElementComplexJson->name);
        $formElementComplex->setWidth((string) $formElementComplexJson->width);
        $formElementComplex->setHeight((string) $formElementComplexJson->height);
        $formElementComplex->setType((string) $formElementComplexJson->type);
        $formElementComplex->setValue((string) $formElementComplexJson->value);
        if (!empty($formElementComplexJson->style)) {
            $formElementComplex->setStyle($formElementComplexJson->style);
        }
        $formElementComplex->setData($formElementComplexJson->data);
        if (!empty($formElementComplexJson->transition)) {
            $formElementComplex->setTransition((string) $formElementComplexJson->transition);
        }
        $formElementComplex->setPlaceholder((string) $formElementComplexJson->placeholder);
        $formElementComplex->setReadonly($formElementComplexJson->readonly);
        if (!empty($formElementComplexJson->parentElement)) {
            $formElementComplex->setParentElement((string) $formElementComplexJson->parentElement);
        }
        if (!empty($formElementComplexJson->folderPath)) {
            $formElementComplex->setFolderPath((string) $formElementComplexJson->folderPath);
        }
        if (!empty($formElementComplexJson->folderUuid)) {
            $formElementComplex->setFolderUuid((string) $formElementComplexJson->folderUuid);
        }
        if (!empty($formElementComplexJson->documentName)) {
            $formElementComplex->setDocumentName((string) $formElementComplexJson->documentName);
        }
        if (!empty($formElementComplexJson->documentUuid)) {
            $formElementComplex->setDocumentUuid((string) $formElementComplexJson->documentUuid);
        }
        if (!empty($formElementComplexJson->confirmation)) {
            $formElementComplex->setConfirmation((string) $formElementComplexJson->confirmation);
        }
        $options = [];
        foreach ($formElementComplexJson->options as $optionJson) {
            $option = new Option();
            $option->setLabel((string) $optionJson->label);
            $option->setValue((string) $optionJson->value);
            $option->setParentValue((string) $optionJson->parentValue);
            if ($optionJson->selected == 'true') {
                $option->setSelected(true);
            } else {
                $option->setSelected(false);
            }
            $option->setCssClass((string) $optionJson->cssClass);
            $options[] = $option;
        }
        $formElementComplex->setOptions($options);
        $validators = [];
        foreach ($formElementComplexJson->validators as $validatorJson) {
            $validator = new Validator();
            $validator->setType((string) $validatorJson->type);
            $validator->setParameter((string) $validatorJson->parameter);
            $validators[] = $validator;
        }
        $formElementComplex->setValidators($validators);
        return $formElementComplex;
    }

    public function phpRelationType($relationTypeXML) {
        $relationType = new RelationType();
        $relationType->setId((int) $relationTypeXML->id);
        $relationType->setTitle((string) $relationTypeXML->title);
        $relationType->setTitleAToB((string) $relationTypeXML->titleAToB);
        $relationType->setTitleBToA((string) $relationTypeXML->titleBToA);
        $relationType->setType((string) $relationTypeXML->type);
        return $relationType;
    }

    public function phpRelation($relationXML) {
        $relation = new Relation();
        $relation->setId((int) $relationXML->id);
        $relation->setUser((string) $relationXML->user);
        $relation->setNode((string) $relationXML->node);
        $relation->setType((string) $relationXML->type);
        $relation->setName((string) $relationXML->name);
        $relation->setRelationTitle((string) $relationXML->relationTitle);
        $relation->setRelationType((string) $relationXML->relationType);
        return $relation;
    }

    public function phpRelationGroup($relationGroupXML) {
        $relationGroup = new RelationGroup();
        $relationGroup->setId((int) $relationGroupXML->id);
        $relationGroup->setName((string) $relationGroupXML->name);
        $relationGroup->setRelationTitle((string) $relationGroupXML->relationTitle);
        $nodes = [];
        foreach ($relationGroupXML->nodes as $nodeXML) {
            $relationGroupNode = new RelationGroupNode();
            $relationGroupNode->setUuid($nodeXML->uuid);
            $relationGroupNode->setName($nodeXML->name);
            $relationGroupNode->setType($nodeXML->type);
            $nodes[] = $relationGroupNode;
        }
        $relationGroup->setNodes($nodes);
        return $relationGroup;
    }

    public function phpProcessDefinition($processDefinitionXML) {
        $processDefinition = new ProcessDefinition();
        $processDefinition->setId((int) $processDefinitionXML->id);
        $processDefinition->setName((string) $processDefinitionXML->name);
        $processDefinition->setVersion((int) $processDefinitionXML->version);
        $processDefinition->setDescription((string) $processDefinitionXML->description);
        $nodes = [];
        foreach ($processDefinitionXML->nodes as $nodesXML) {
            $nodes[] = (string) $nodesXML;
        }
        $processDefinition->setNodes($nodes);
        return $processDefinition;
    }

    public function phpToken($tokenXML) {
        $token = new Token();
        $token->setId((int) $tokenXML->id);
        $token->setName((string) $tokenXML->name);
        if ($tokenXML->suspended == 'true') {
            $token->setSuspended(true);
        } else {
            $token->setSuspended(false);
        }
        if (!empty($tokenXML->parent)) {
            $token->setParent($this->phpToken($tokenXML->parent));
        }
        $token->setNode((string) $tokenXML->node);
        $token->setStart((string) $tokenXML->start);
        $token->setEnd((string) $tokenXML->end);

        $transitons = [];
        foreach ($tokenXML->availableTransitions as $transitionXML) {
            $transition = new Transition();
            $transition->setId((int) $transitionXML->id);
            $transition->setName((string) $transitionXML->name);
            $transition->setFrom((string) $transitionXML->from);
            $transition->setTo((string) $transitionXML->to);
            $transitons[] = $transition;
        }
        $token->setAvailableTransitions($transitons);

        $comments = [];
        foreach ($tokenXML->comments as $commentXML) {
            $comment = new Comment();
            $comment->setTime((string) $commentXML->time);
            $comment->setActorId((string) $commentXML->actorId);
            $comment->setMessage((string) $commentXML->message);
            $comments[] = $comment;
        }
        $token->setComments($comments);
        if (!empty($tokenXML->processDefinition)) {
            $token->setProcessInstance($this->phpProcessDefinition($tokenXML->processDefinition));
        }
        return $token;
    }

    public function phpProcessInstance($processInstanceXML) {
        $processInstance = new ProcessInstance();
        $processInstance->setId((int) $processInstanceXML->id);
        $processInstance->setVersion((int) $processInstanceXML->version);
        $processInstance->setKey((string) $processInstanceXML->key);
        $processInstance->setStart((string) $processInstanceXML->start);
        $processInstance->setEnd((string) $processInstanceXML->end);
        $processInstance->setEnded((bool) $processInstanceXML->ended);
        if ($processInstanceXML->ended == 'true') {
            $processInstance->setEnded(true);
        } else {
            $processInstance->setEnded(false);
        }
        if ($processInstanceXML->suspended == 'true') {
            $processInstance->setSuspended(true);
        } else {
            $processInstance->setSuspended(false);
        }
        $processInstance->setRootToken($this->phpToken($processInstanceXML->rootToken));

        $variables = [];
        foreach ($processInstanceXML->variables->entry as $entryXML) {
            $entry = new Entry();
            $entry->setKey((string) $entryXML->key);
            $entry->setValue((string) $entryXML->value);
            $variables[] = $entry;
        }
        $processInstance->setVariables($variables);

        $tokens = [];
        foreach ($processInstanceXML->allTokens as $tokenXML) {
            $tokens[] = $this->phpToken($tokenXML);
        }
        $processInstance->setAllTokens($tokens);
        $processInstance->setProcessDefinition($this->phpProcessDefinition($processInstanceXML->processDefinition));

        return $processInstance;
    }

    public function phpTaskInstance($taskInstanceXML) {
        $taskInstance = new TaskInstance();
        $taskInstance->setId((int) $taskInstanceXML->id);
        $taskInstance->setProcessInstanceId((int) $taskInstanceXML->processInstanceId);
        $taskInstance->setProcessDefinitionId((int) $taskInstanceXML->processDefinitionId);
        $taskInstance->setStart((string) $taskInstanceXML->start);
        $taskInstance->setEnd((string) $taskInstanceXML->end);
        $taskInstance->setDueDate((string) $taskInstanceXML->dueDate);
        $taskInstance->setName((string) $taskInstanceXML->name);
        $taskInstance->setDescription((string) $taskInstanceXML->description);
        $taskInstance->setActorId((string) $taskInstanceXML->actorId);

        $pooledActors = [];
        foreach ($taskInstanceXML->pooledActors as $pooledActorXML) {
            $pooledActors[] = (string) $pooledActorXML;
        }
        $taskInstance->setPooledActors($pooledActors);

        $taskInstance->setCreate((string) $taskInstanceXML->create);
        if ($taskInstanceXML->open == 'true') {
            $taskInstance->setOpen(true);
        } else {
            $taskInstance->setOpen(false);
        }
        if ($taskInstanceXML->last == 'true') {
            $taskInstance->setLast(true);
        } else {
            $taskInstance->setLast(false);
        }
        if ($taskInstanceXML->suspendend == 'true') {
            $taskInstance->setSuspendend(true);
        } else {
            $taskInstance->setSuspendend(false);
        }
        if ($taskInstanceXML->suspendend == 'true') {
            $taskInstance->setSuspendend(true);
        } else {
            $taskInstance->setSuspendend(false);
        }
        if ($taskInstanceXML->startTaskInstance == 'true') {
            $taskInstance->setStartTaskInstance(true);
        } else {
            $taskInstance->setStartTaskInstance(false);
        }

        $comments = [];
        foreach ($taskInstanceXML->comments as $commentXML) {
            $comment = new Comment();
            $comment->setTime((string) $commentXML->time);
            $comment->setActorId((string) $commentXML->actorId);
            $comment->setMessage((string) $commentXML->message);
            $comments[] = $comment;
        }
        $taskInstance->setComments($comments);
        $taskInstance->setToken($this->phpToken($taskInstanceXML->token));

        $transitons = [];
        foreach ($taskInstanceXML->availableTransitions as $transitionXML) {
            $transition = new Transition();
            $transition->setId((int) $transitionXML->id);
            $transition->setName((string) $transitionXML->name);
            $transition->setFrom((string) $transitionXML->from);
            $transition->setTo((string) $transitionXML->to);
            $transitons[] = $transition;
        }
        $taskInstance->setAvailableTransitions($transitons);

        $variables = [];
        foreach ($taskInstanceXML->variables->entry as $entryXML) {
            $entry = new Entry();
            $entry->setKey((string) $entryXML->key);
            $entry->setValue((string) $entryXML->value);
            $variables[] = $entry;
        }
        $taskInstance->setVariables($variables);
        $taskInstance->setProcessInstance($this->phpProcessInstance($taskInstanceXML->processInstance));
        return $taskInstance;
    }

    public function phpTask($taskXML) {
        $task = new Task();
        $task->setId((int) $taskXML->id);
        $task->setOwner((string) $taskXML->owner);
        $task->setSubject((string) $taskXML->subject);
        $task->setDescription((string) $taskXML->description);
        $task->setStart((string) $taskXML->start);
        $task->setEnd((string) $taskXML->end);

        $task->setStatus($this->phpTaskStatus($taskXML->taskStatus));
        $task->setProject($this->phpTaskProject($taskXML->taskProject));
        $task->setType($this->phpTaskType($taskXML->taskType));

        $task->setProgress((int) $taskXML->progress);
        $task->setRepeatGroup((int) $taskXML->repeteGroup);
        $task->setReminderStartValue((int) $taskXML->reminderStartValue);
        $task->setReminderEndValue((int) $taskXML->reminderEndValue);
        $task->setReminderStartUnit((string) $taskXML->reminderStartUnit);
        $task->setReminderEndUnit((string) $taskXML->reminderEndUnit);

        $users = [];
        foreach ($taskXML->user as $userXML) {
            $users = (string) $userXML;
        }
        $task->setUsers($users);

        $roles = [];
        foreach ($taskXML->role as $roleXML) {
            $roles = (string) $roleXML;
        }
        $task->setRoles($roles);

        $documents = [];
        foreach ($taskXML->document as $documentXML) {
            $documents[] = $this->phpDocument($documentXML);
        }
        $task->setDocuments($documents);

        $folders = [];
        foreach ($taskXML->folder as $folderJSON) {
            $folders[] = $this->phpFolderComplete($folderJSON);
        }
        $task->setFolders($folders);

        $mails = [];
        foreach ($taskXML->mail as $mailXML) {
            $mails[] = $this->phpMail($mailXML);
        }
        $task->setMails($mails);

        $records = [];
        foreach ($taskXML->record as $recordXML) {
            $records[] = $this->phpRecord($recordXML);
        }
        $task->setRecords($records);

        return $task;
    }

    public function phpTaskStatus($taskStatusXML) {
        $taskStatus = new TaskStatus();
        $taskStatus->setId((int) $taskStatusXML->id);
        $taskStatus->setName((string) $taskStatusXML->name);
        if ((string) $taskStatusXML->finish == 'true') {
            $taskStatus->setFinish(true);
        } else {
            $taskStatus->setFinish(false);
        }
        return $taskStatus;
    }

    public function phpTaskProject($taskProjectXML) {
        $taskProject = new TaskProject();
        $taskProject->setId((int) $taskProjectXML->id);
        $taskProject->setName((string) $taskProjectXML->name);
        if ((string) $taskProjectXML->active == 'true') {
            $taskProject->setActive(true);
        } else {
            $taskProject->setActive(false);
        }
        $taskProject->setDescription((string) $taskProjectXML->description);
        return $taskProject;
    }

    public function phpTaskType($taskTypeXML) {
        $taskType = new TaskType();
        $taskType->setId((int) $taskTypeXML->id);
        $taskType->setName((string) $taskTypeXML->name);
        if ((string) $taskTypeXML->active == 'true') {
            $taskType->setActive(true);
        } else {
            $taskType->setActive(false);
        }
        $taskType->setDescription((string) $taskTypeXML->description);
        return $taskType;
    }

    public function phpTaskNote($taskNoteXML) {
        $taskNote = new TaskNote();
        $taskNote->setId((int) $taskNoteXML->id);
        $taskNote->setTask((string) $taskNoteXML->task);
        $taskNote->setAuthor((string) $taskNoteXML->author);
        $taskNote->setCreated((string) $taskNoteXML->created);
        $taskNote->setText((string) $taskNoteXML->text);
        return $taskNote;
    }

    public function phpQueryParams($queryParamsXML) {
        $queryParams = new QueryParams();
        $queryParams->setAuthor((string) $queryParamsXML->author);
        $queryParams->setContent((string) $queryParamsXML->content);
        if ((string) $queryParamsXML->dashboard == 'true') {
            $queryParams->setDashboard(true);
        } else {
            $queryParams->setDashboard(false);
        }
        $queryParams->setDomain((int) $queryParamsXML->domain);
        $queryParams->setId((int) $queryParamsXML->id);
        $queryParams->setLastModifiedFrom((string) $queryParamsXML->lastModifiedFrom);
        $queryParams->setLastModifiedTo((string) $queryParamsXML->lastModifiedTo);
        $queryParams->setMailFrom((string) $queryParamsXML->mailFrom);
        $queryParams->setMailSubject((string) $queryParamsXML->mailSubject);
        $queryParams->setMailTo((string) $queryParamsXML->mailTo);
        $queryParams->setMimeType((string) $queryParamsXML->mimeType);
        $queryParams->setName((string) $queryParamsXML->name);
        $queryParams->setOperator((string) $queryParamsXML->operator);
        $queryParams->setFolder((string) $queryParamsXML->folder);
        if ((string) $queryParamsXML->folderRecursive == 'true') {
            $queryParams->setFolderRecursive(true);
        } else {
            $queryParams->setFolderRecursive(false);
        }
        $queryParams->setQueryName((string) $queryParamsXML->queryName);
        $queryParams->setUser((string) $queryParamsXML->user);
        $queryParams->setNotes((string) $queryParamsXML->notes);
        $categories = [];
        foreach ($queryParamsXML->categories as $category) {
            $categories[] = (string) $category;
        }
        $queryParams->setCategories($categories);
        $keywords = [];
        foreach ($queryParamsXML->keywords as $keyword) {
            $keywords[] = (string) $keyword;
        }
        $queryParams->setKeywords($keywords);
        $properties = [];
        foreach ($queryParamsXML->properties->entry as $entryXML) {
            $entry = new Entry();
            $entry->setKey((string) $entryXML->key);
            $entry->setValue((string) $entryXML->value);
            $properties[] = $entry;
        }
        $queryParams->setProperties($properties);
        return $queryParams;
    }

    public function phpQueryResult($queryResultXML) {
        $queryResult = new QueryResult();
        $queryResult->setAttachment((string) $queryResultXML->attachment);
        $queryResult->setExcerpt((string) $queryResultXML->excerpt);
        if (!empty($queryResultXML->node)) {
            if (empty($queryResultXML->node->hasChildren)) {
                $queryResult->setNode($this->phpDocument($queryResultXML->node));
            } else {
                $queryResult->setNode($this->phpFolderComplete($queryResultXML->node));
            }
        }
        $queryResult->setScore((int) $queryResultXML->score);
        return $queryResult;
    }

    public function phpRestException($restExceptionJSON) {
        $restException = new RestException();
        $restException->setSimpleName($restExceptionJSON->simpleName);
        $restException->setMessage($restExceptionJSON->message);
        $restException->setStacktrace($restExceptionJSON->stacktrace);

        $timestamp = new LocalDateTime();
        $timestamp->setNano($restExceptionJSON->timestamp->nano);
        $timestamp->setHour($restExceptionJSON->timestamp->hour);
        $timestamp->setMinute($restExceptionJSON->timestamp->minute);
        $timestamp->setSecond($restExceptionJSON->timestamp->second);
        $timestamp->setYear($restExceptionJSON->timestamp->year);
        $timestamp->setMonth($restExceptionJSON->timestamp->month);
        $timestamp->setDayOfMonth($restExceptionJSON->timestamp->dayOfMonth);
        $timestamp->setDayOfWeek($restExceptionJSON->timestamp->dayOfWeek);
        $timestamp->setDayOfYear($restExceptionJSON->timestamp->dayOfYear);
        $timestamp->setMonthValue($restExceptionJSON->timestamp->monthValue);
        $timestamp->setType($restExceptionJSON->timestamp->chronology->calendarType);
        $timestamp->setId($restExceptionJSON->timestamp->chronology->id);
        $restException->setTimestamp($timestamp);

        if ($restExceptionJSON->errorList != null && count($restExceptionJSON->errorList) > 0) {
            
        }
        return $restException;
    }

}
