function doCall($method, $parameters, $instance, $serverKey)
{
    $callParameters = validateCallParameters($method, $parameters, $instance);
    $reflectedClass = new ReflectionClass(get_class($instance));
    $reflectedMethod = $reflectedClass->getMethod($method->getName());
    $result;
    $result = $reflectedMethod->invokeArgs($instance, $callParameters);
    $resultJson = "";
    //Print custom errors
    $reflectedErrorMethod = $reflectedClass->getMethod("getErrors");
    $reflectedErrors = $reflectedErrorMethod->invoke($instance);
    if (!empty($reflectedErrors)) {
        $resultJson .= "[";
        foreach ($reflectedErrors as $reflectedError) {
            $reflectedErrorClass = new ReflectionClass(get_class($reflectedError));
            $code = $reflectedErrorClass->getMethod("getCode")->invoke($reflectedError);
            $message = $reflectedErrorClass->getMethod("getMessage")->invoke($reflectedError);
            $resultJson .= '{"code":' . JsonUtils::encodeToJson($code) . ',"message":' . JsonUtils::encodeToJson($message) . '},';
        }
        $resultJson = JsonUtils::removeLastChar($reflectedErrors, $resultJson);
        $resultJson .= "]";
    } else {
        $resultJson .= serializeMethodResult($method, $result, $instance, $serverKey);
    }
    return $resultJson;
}
function serializeArray($result, $instance, $isSimpleResult, $serverKey)
{
    $json = "";
    if (is_array($result)) {
        if (ArrayUtils::isAssociative($result)) {
            $json .= "{";
            foreach ($result as $key => $value) {
                $json .= '"' . $key . '":';
                if (is_object($value)) {
                    $json .= serializeObject($value, $instance, false, $serverKey);
                } else {
                    if (is_array($value)) {
                        $json .= serializeArray($value, $instance, $isSimpleResult, $serverKey);
                    } else {
                        $json .= serializeObject($value, $instance, !is_object($value), $serverKey);
                    }
                }
                $json .= ",";
            }
        } else {
            $json .= "[";
            for ($i = 0; $i < count($result); $i++) {
                $json .= serializeObject($result[$i], $instance, $isSimpleResult, $serverKey) . ",";
            }
        }
        $json = JsonUtils::removeLastChar($result, $json);
        if (ArrayUtils::isAssociative($result)) {
            $json .= "}";
        } else {
            $json .= "]";
        }
    }
    return $json;
}
function discoverObjects($configuration, $objectsFound)
{
    $result = "";
    $objects = $configuration->getObjects();
    $objectsDone = array();
    foreach ($objects as $object) {
        $result .= "\t<object ";
        $className = $object->getClassName();
        $result .= "name=\"" . $className . "\" >\n";
        foreach ($object->getFields() as $field) {
            $result .= "\t\t<field";
            $objectName = $field->getObject();
            if ($objectName != null) {
                if (!in_array($objectName, $objectsFound) && !in_array($objectName, $objectsDone)) {
                    array_push($objectsFound, $objectName);
                }
            }
            if (!empty($objectName)) {
                $result .= " object=\"" . $objectName . "\"";
            }
            $result .= " array=\"" . ($field->isArray() ? "true" : "false") . "\"";
            $result .= " optional=\"" . ($field->isOptional() ? "true" : "false") . "\"";
            $fieldName = $field->getName();
            $result .= ">" . $fieldName . "</field>\n";
        }
        $result .= "\t</object>\n";
        array_push($objectsDone, $className);
        $objectsFound = array_diff($objectsFound, array($className));
    }
    $result .= "\t<object name=\"StandardMashapeError\">\n\t\t<field>code</field>\n\t\t<field>message</field>\n\t</object>\n";
    // Check that all objects exist
    if (!empty($objectsFound)) {
        $missingObjects = "";
        foreach ($objectsFound as $requiredObject) {
            $missingObjects .= $requiredObject . ",";
        }
        $missingObjects = JsonUtils::removeLastChar($objectsFound, $missingObjects);
        throw new MashapeException(sprintf(EXCEPTION_MISSING_OBJECTS, $missingObjects), EXCEPTION_XML_CODE);
    }
    return $result;
}
function serializeObject($result, $instance, $isSimpleResult, $serverKey)
{
    $json = "";
    if ($isSimpleResult) {
        // It's a simple result, just serialize it
        $json = JsonUtils::encodeToJson($result);
    } else {
        // It's a custom object, let's serialize recursively every field
        $className = get_class($result);
        $reflectedClass = new ReflectionClass($className);
        $xmlObject = RESTConfigurationLoader::getObject($className, $serverKey);
        if (empty($xmlObject)) {
            throw new MashapeException(sprintf(EXCEPTION_UNKNOWN_OBJECT, $className), EXCEPTION_GENERIC_LIBRARY_ERROR_CODE);
        }
        // Start element
        $json .= "{";
        // Serialize fields
        $fields = $xmlObject->getFields();
        for ($i = 0; $i < count($fields); $i++) {
            $field = $fields[$i];
            $fieldName = $field->getName();
            $fieldMethod = $field->getMethod();
            $fieldValue = null;
            if (empty($fieldMethod)) {
                if ($reflectedClass->hasProperty($fieldName)) {
                    $reflectedProperty = $reflectedClass->getProperty($fieldName);
                    if ($reflectedProperty->isPublic()) {
                        $fieldValue = $reflectedProperty->getValue($result);
                    } else {
                        // Try using the __get magic method
                        $fieldValue = $reflectedClass->getMethod("__get")->invokeArgs($result, array($fieldName));
                    }
                } else {
                    if (ArrayUtils::existKey($fieldName, get_object_vars($result))) {
                        $fieldValue = $result->{$fieldName};
                    } else {
                        throw new MashapeException(sprintf(EXCEPTION_FIELD_NOTFOUND, $fieldName), EXCEPTION_GENERIC_LIBRARY_ERROR_CODE);
                    }
                }
            } else {
                $fieldValue = $reflectedClass->getMethod($fieldMethod)->invoke($result);
            }
            if ($fieldValue === null && $field->isOptional()) {
                // Don't serialize the field
                continue;
            }
            $json .= '"' . $fieldName . '":';
            if ($fieldValue === null) {
                $json .= JsonUtils::encodeToJson($fieldValue);
            } else {
                $isSimpleField = isSimpleField($field);
                if ($field->isArray()) {
                    if (is_array($fieldValue)) {
                        $json .= serializeArray($fieldValue, $instance, isSimpleField($field), $serverKey);
                    } else {
                        // The result it's not an array although it was described IT WAS an array
                        throw new MashapeException(sprintf(EXCEPTION_EXPECTED_ARRAY_RESULT, $fieldName, $className), EXCEPTION_GENERIC_LIBRARY_ERROR_CODE);
                    }
                } else {
                    if (is_array($fieldValue)) {
                        // The result it's an array although it was described IT WAS NOT an array
                        throw new MashapeException(sprintf(EXCEPTION_UNEXPECTED_ARRAY_RESULT, $fieldName, $className), EXCEPTION_GENERIC_LIBRARY_ERROR_CODE);
                    } else {
                        $json .= serializeObject($fieldValue, $instance, $isSimpleField, $serverKey);
                    }
                }
            }
            $json .= ",";
        }
        if (substr($json, strlen($json) - 1, 1) != "{") {
            $json = JsonUtils::removeLastChar($fields, $json);
        }
        // Close element
        $json .= "}";
    }
    return $json;
}
function serializeParametersQueryString($method, $instance, $routeParameters = null)
{
    $reflectedClass = new ReflectionClass(get_class($instance));
    $reflectedMethod = $reflectedClass->getMethod($method->getName());
    $reflectedParameters = $reflectedMethod->getParameters();
    $result = "";
    for ($i = 0; $i < count($reflectedParameters); $i++) {
        $param = $reflectedParameters[$i];
        if (!empty($routeParameters)) {
            if (in_array($param->name, $routeParameters)) {
                continue;
            }
        }
        if ($i == 0) {
            $result .= "&";
        }
        $result .= $param->name . "={" . $param->name . "}&";
    }
    $result = JsonUtils::removeLastChar($reflectedParameters, $result);
    return $result;
}