public static function parse( array $headers, $body, $raw = false )
    {
        $response = $raw === true ? $body : json_decode( $body, true );

        // To detect the type of the response from the couch DB server we use
        // the response status which indicates the return type.
        switch ( $headers['status'] )
        {
            case 200:
                // The HTTP status code 200 - OK indicates, that we got a document
                // or a set of documents as return value.
                //
                // To check whether we received a set of documents or a single
                // document we can check for the document properties _id or
                // _rev, which are always available for documents and are only
                // available for documents.
                if ( $raw === true )
                {
                    return new phpillowDataResponse( $headers['content-type'], $response );
                }
                elseif ( $body[0] === '[' )
                {
                    return new phpillowArrayResponse( $response );
                }
                elseif ( isset( $response['_id'] ) )
                {
                    return new phpillowResponse( $response );
                }
                elseif ( isset( $response['rows'] ) )
                {
                    return new phpillowResultSetResponse( $response );
                }

                // Otherwise fall back to a plain status response. No break.

            case 201:
            case 202:
                // The following status codes are given for status responses
                // depending on the request type - which does not matter here any
                // more.
                return new phpillowStatusResponse( $response );

            case 404:
                // The 404 and 409 (412) errors are using custom exceptions
                // extending the base error exception, because they are often
                // required to be handled in a special way by the application.
                //
                // Feel free to extend this for other errors as well.
                throw new phpillowResponseNotFoundErrorException( $response );

            case 409: // Conflict
            case 412: // Precondition Failed - we just consider this as a conflict.
                throw new phpillowResponseConflictErrorException( $response );

            default:
                // All other unhandled HTTP codes are for now handled as an error.
                // This may not be true, as lots of other status code may be used
                // for valid responses.
                throw new phpillowResponseErrorException( $headers['status'], $response );
        }
    }