def __init__(self, client_builder = None):

        self.application_href = None
        if (client_builder):
            assert_instance(client_builder, ClientBuilder, 'client_builder')
            self.client_builder = client_builder
        else:
            self.client_builder = ClientBuilder()
class ClientApplicationBuilder:
    """
    A "Builder design pattern":http://en.wikipedia.org/wiki/Builder_pattern implementation similar to
    the *ClientBuilder*, but focused on single-application interaction with Stormpath.

    Description

        The *ClientBuilder* produces a *Client* instance useful for interacting with any aspect
        of an entire Stormpath Tenant's data space.  However, a software application may only be interested in its own
        functionality and not the entire Stormpath Tenant data space.

        The *ClientApplicationBuilder* provides a means to more easily acquiring a single
        *Application* instance.  From this *Application* instance, everything a particular
        Application needs to perform can be based off of this instance and the wider-scoped concerns of an entire Tenant can be ignored.

    Default Usage

        this can be a file disk or url location as well:
        location = "/home/jsmith/.stormpath/apiKey.yml"

        app_href = "https://api.stormpath.com/v1/applications/YOUR_APP_UID_HERE"

        application = ClientApplicationBuilder().\
                      set_api_key_file_location(location).\
                      *set_application_href(app_href)*.\
                      build().\
                      application

    After acquiring the *Application* instance, you can interact with it to login accounts, reset passwords,
    etc.

    Service Provider Usage with only an Application URL

        Some hosting service providers (e.g. like "Heroku":http://www.heroku.com) do not allow easy access to
        a configuration file and therefore it might be difficult to reference an API Key File.  If you cannot reference an
        API Key File via the *YAML file* or *YAML string object* or *url*
        via *ClientBuilder().set_api_key_file_location(str)*, the Application HREF URL must contain the
        API Key embedded as the *"user info"http://en.wikipedia.org/wiki/URI_scheme* portion of the
        URL.  For example:

            https://apiKeyId:[email protected]/v1/applications/YOUR_APP_UID_HERE

        Notice this is just a normal Application HREF url with the *apiKeyId:apiKeySecret@* part added in.

        Example usage:

            appHref = "https://*****:*****@api.stormpath.com/v1/applications/YOUR_APP_UID_HERE"

            application = ClientApplicationBuilder().\
                          set_application_href(appHref).\
                          build().\
                          application

    *WARNING: ONLY use the embedded API Key technique if you do not have access to YAML file or
    YAML string object or url via ClientApplicationBuilder().set_api_key_file_location(str)*.
    File based API Key storage is a more secure technique than embedding the key in the URL itself.  Also, again,
    NEVER share your API Key Secret with *anyone* (not even co-workers).
    Stormpath staff will never ask for your API Key Secret.

    :see set_api_key_file_location(str)
    :see #set_application_href(str)
    """

    def __init__(self, client_builder = None):

        self.application_href = None
        if (client_builder):
            assert_instance(client_builder, ClientBuilder, 'client_builder')
            self.client_builder = client_builder
        else:
            self.client_builder = ClientBuilder()

    def set_api_key_properties(self, properties):
        """
        Allows usage of a YAML loadable string object
        instead of loading a YAML file via *set_api_key_file_location(apiKeyFileLocation)* configuration.

        The YAML contents and property name overrides function the same as described in the
        *set_api_key_file_location(setApiKeyFileLocation)* docstring.

        :param properties: the YAML string object to use to load the API Key ID and Secret.
        :returns this ClientApplicationBuilder instance for method chaining.
        """
        self.client_builder.set_api_key_properties(properties)
        return self

    def set_api_key_file_location(self, api_key_file_location):
        """
        Sets the location of the YAML file to load containing the API Key (Id and secret) used by the
        Client to communicate with the Stormpath REST API.

        You may load files from the filesystem, or URLs just specifying the file location.

        File Contents

            When the file is loaded, the following name/value pairs are expected to be present by default:


                    Key                 Value

                    apiKey.id           An individual account's API Key ID
                    apiKey.secret       The API Key Secret (password) that verifies the paired API Key ID.</td>


        Assuming you were using these default property names, your *ClientApplicationBuilder* usage might look like the
        following:

            location = "/home/jsmith/.stormpath/apiKey.yml";

            application_href = 'https://api.stormpath.com/v1/applications/YOUR_APP_UID_HERE'

            application = ClientApplicationBuilder().\
                          set_application_href(appHref).\
                          set_api_key_file_location(location).\
                          build().\
                          application

        Custom Property Names

            If you want to control the property names used in the file, you may configure them via
            *set_api_key_id_property_name(api_key_id_property_name)* and
            *set_api_key_secret_property_name(api_key_secret_property_name)*.

            For example, if you had a */home/jsmith/.stormpath/apiKey.yml* file with the following
            name/value pairs:

                myStormpathApiKeyId = 'foo'
                myStormpathApiKeySecret = 'mySuperSecretValue'

            Your *ClientApplicationBuilder* usage would look like the following:

                location = "/home/jsmith/.stormpath/apiKey.yml"

                application = ClientApplicationBuilder().\
                              set_application_href(application_href).\
                              set_api_key_file_location(location).\
                              set_api_key_id_property_name(myStormpathApiKeyId).\
                              set_api_key_secret_property_name(myStormpathApiKeySecret).\
                              build().\
                              application

        :param location: the file or url location of the API Key *.yml* file to load when
                        constructing the API Key to use for communicating with the Stormpath REST API.

        :returns the ClientApplicationBuilder instance for method chaining.
        """
        self.client_builder.set_api_key_file_location(api_key_file_location)
        return self

    def set_api_key_id_property_name(self, *api_key_id_property_name):
        """
        Sets the name used to query for the API Key ID from a YAML string instance.

        The *api_key_id_property_name* key can be as deep as needed, as long as it comes
        in the exact path order.

        Example: Having the file 'apiKey.yml' with the following content:

                  stormpath:
                    apiKey:
                    id: myStormpathApiKeyId

        The method should be called as follows:

                  ClientApplicationBuilder().set_api_key_id_property_name('stormpath', 'apiKey', 'id')

        :param api_key_id_property_name: the name used to query for the API Key ID from a YAML string/file.
        :returns the ClientApplicationBuilder instance for method chaining.
        """
        self.client_builder.set_api_key_id_property_name(*api_key_id_property_name)
        return self

    def set_api_key_secret_property_name(self, *api_key_secret_property_name):
        """
        Sets the name used to query for the API Key Secret from a YAML string instance.

        The *api_key_secret_property_name* key can be as deep as needed, as long as it comes
        in the exact path order.

        Example: Having the file 'apiKey.yml' with the following content:

                  stormpath:
                    apiKey:
                    secret: myStormpathApiKeySecret

        The method should be called as follows:

                  ClientApplicationBuilder().set_api_key_secret_property_name('stormpath', 'apiKey', 'secret')

        :param api_key_secret_property_name: the name used to query for the API Key Secret from a YAML string/file.
        :returns the ClientApplicationBuilder instance for method chaining.
        """
        self.client_builder.set_api_key_secret_property_name(*api_key_secret_property_name)
        return self

    def set_application_href(self, application_href):
        """
        Sets the fully qualified Stormpath Application HREF (a URL) to use to acquire the Application instance when
        *build()* is called.  See the Class-level docstring for usage scenarios.

        :param application_href: the fully qualified Stormpath Application HREF (a URL) to use to acquire the
                               Application instance when *build()* is called.
        :returns this ClientApplicationBuilder instance for method chaining.
        """
        self.application_href = application_href
        return self

    def build(self):
        """
        Builds a Client and Application wrapper instance based on the configured
        *set_application_href*. See the Class-level docstring for usage scenarios.

        :returns a Client and Application wrapper instance based on the configured *set_application_href*.
        """

        assert_not_none(self.application_href, "'application_href' property must be specified when using this builder implementation.")

        cleaned_href = self.application_href[0:len(self.application_href)] #just returning a copy

        at_sigh_index = cleaned_href.find('@')

        if at_sigh_index > 0: #otherwise an apiKey File/YAML/etc for the API Key is required

            parts = self._get_href_with_user_info_(cleaned_href, at_sigh_index)

            cleaned_href = parts[0] + parts[2]

            parts = parts[1].split(':', 1)

            api_key_properties = self._create_api_key_properties_(parts)

            self.set_api_key_properties(api_key_properties)

        assert_true(cleaned_href.find('http') == 0 and cleaned_href.find('://') > 0, 'Invalid application href URL')

        client = self._build_client_()

        application = client.data_store.get_resource(cleaned_href, Application)

        return ClientApplication(client, application)


    def _build_client_(self):
        return self.client_builder.build()

    def _get_href_with_user_info_(self, href, at_sign_index):
        assert_instance(href, str, 'href')
        assert_instance(at_sign_index, int, 'at_sign_index')

        double_slash_index = href.find('//')

        assert_true(double_slash_index > 0, 'Invalid application href URL')

        parts = {}
        parts[0] = href[0:double_slash_index + 2] #up to and including the double slash
        parts[1] = href[double_slash_index + 2:at_sign_index] #raw user info
        parts[2] = href[at_sign_index + 1:len(href)] #after the @ character

        return parts

    def _create_api_key_properties_(self, pair):
        assert_true(len(pair) == 2, 'application_href userInfo segment must consist' +
                                    ' of the following format: apiKeyId:apiKeySecret')

        properties = {'apiKey.id' : urllib.parse.unquote(pair[0]), 'apiKey.secret' : urllib.parse.unquote(pair[1])}

        return yaml.dump(properties)