<?php

/**
 * OpenKM, Open Knowledge Management System S.L.  (http://www.openkm.com)
 * Copyright (c) 2006-2023
 *
 * 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 getClientWithParams(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($taskJson) {
        $task = new Task();
        $task->setId($taskJson->id);
        $task->setOwner($taskJson->owner);
        $task->setSubject($taskJson->subject);
        $task->setDescription($taskJson->description);

        $task->setCreated($taskJson->created);
        $task->setLastModified($taskJson->lastModified);
        $task->setStart($taskJson->start);
        $task->setEnd($taskJson->end);

        $task->setStatus($this->phpTaskStatus($taskJson->status));
        $task->setProject($this->phpTaskProject($taskJson->project));
        $task->setType($this->phpTaskType($taskJson->type));

        $task->setProgress($taskJson->progress);
        $task->setRepeatGroup($taskJson->repeatGroup);
        $task->setReminderStartValue($taskJson->reminderStartValue);
        $task->setReminderEndValue($taskJson->reminderEndValue);
        $task->setReminderStartUnit($taskJson->reminderStartUnit);
        $task->setReminderEndUnit($taskJson->reminderEndUnit);

        $task->setUser($taskJson->users);
        $notificationUsers = [];
        foreach ($taskJson->notificationUsers as $notificationUser) {
            $notificationUsers[] = (string) $notificationUser;
        }
        $task->setNotificationUsers($notificationUsers);

        $externalUsers = [];
        foreach ($taskJson->externalUsers as $externalUser) {
            $externalUsers[] = (string) $externalUser;
        }
        $task->setExternalUsers($externalUsers);

        $documents = [];
        foreach ($taskJson->documents as $documentUuid) {
            $documents[] = $documentUuid;
        }
        $task->setDocuments($documents);

        $folders = [];
        foreach ($taskJson->folders as $folderUuid) {
            $folders[] = $folderUuid;
        }
        $task->setFolders($folders);

        $mails = [];
        foreach ($taskJson->mails as $mailUuid) {
            $mails[] = $mailUuid;
        }
        $task->setMails($mails);

        $records = [];
        foreach ($taskJson->records as $recordUuid) {
            $records[] = $recordUuid;
        }
        $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($queryParamsJSON) {
		$queryParams = new QueryParams();
		$queryParams->setAuthor((string)$queryParamsJSON->author);
		$queryParams->setContent((string)$queryParamsJSON->content);
		if ((string)$queryParamsJSON->dashboard == 'true') {
			$queryParams->setDashboard(true);
		} else {
			$queryParams->setDashboard(false);
		}
		$queryParams->setDomain((int)$queryParamsJSON->domain);
		$queryParams->setId((int)$queryParamsJSON->id);
		$queryParams->setLastModifiedFrom((string)$queryParamsJSON->lastModifiedFrom);
		$queryParams->setLastModifiedTo((string)$queryParamsJSON->lastModifiedTo);
		$queryParams->setMailFrom((string)$queryParamsJSON->mailFrom);
		$queryParams->setMailSubject((string)$queryParamsJSON->mailSubject);
		$queryParams->setMailTo((string)$queryParamsJSON->mailTo);
		$queryParams->setMimeType((string)$queryParamsJSON->mimeType);
		$queryParams->setName((string)$queryParamsJSON->name);
		$queryParams->setOperator((string)$queryParamsJSON->operator);
		$queryParams->setFolder((string)$queryParamsJSON->folder);
		if ((string)$queryParamsJSON->folderRecursive == 'true') {
			$queryParams->setFolderRecursive(true);
		} else {
			$queryParams->setFolderRecursive(false);
		}
		$queryParams->setQueryName((string)$queryParamsJSON->queryName);
		$queryParams->setUser((string)$queryParamsJSON->user);
		$queryParams->setNotes((string)$queryParamsJSON->notes);
		$categories = [];
		foreach ($queryParamsJSON->categories as $category) {
			$categories[] = (string)$category;
		}
		$queryParams->setCategories($categories);
		$keywords = [];
		foreach ($queryParamsJSON->keywords as $keyword) {
			$keywords[] = (string)$keyword;
		}
		$queryParams->setKeywords($keywords);
		$properties = [];
		foreach ($queryParamsJSON->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($queryResultJSON) {
		$type = '';
		foreach ($queryResultJSON->node as $key => $value) {
			if ($key == '@type') {
				$type = $value;
				break;
			}
		}

		$queryResult = new QueryResult();
		$queryResult->setAttachment((string)$queryResultJSON->attachment);
		$queryResult->setExcerpt((string)$queryResultJSON->excerpt);
		if (!empty($queryResultJSON->node)) {
			if ($type == QueryResult::TYPE_DOCUMENT) {
				$queryResult->setNode($this->phpDocument($queryResultJSON->node));
			} else if ($type == QueryResult::TYPE_FOLDER) {
				$queryResult->setNode($this->phpFolderComplete($queryResultJSON->node));
			} else {

			}
		}
		$queryResult->setScore((int)$queryResultJSON->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;
	}

}
