Asserts that every declared :term:`specification` can actually be
        realized, meaning that all of its :term:`dependencies <dependency>` are
        present and there are no self-dependencies or :term:`dependency cycles
        <dependency cycle>`. If such a problem is found, a proper exception
        (deriving from :py:class:`GraphValidationError`) is raised.

        :raises:
            :py:exc:`MissingDependencyError`,
            :py:exc:`SelfDependencyError`,
            :py:exc:`DependencyCycleError`

def validate(self):
        """
        Asserts that every declared :term:`specification` can actually be
        realized, meaning that all of its :term:`dependencies <dependency>` are
        present and there are no self-dependencies or :term:`dependency cycles
        <dependency cycle>`. If such a problem is found, a proper exception
        (deriving from :py:class:`GraphValidationError`) is raised.

        :raises:
            :py:exc:`MissingDependencyError`,
            :py:exc:`SelfDependencyError`,
            :py:exc:`DependencyCycleError`
        """
        # This method uses Tarjan's strongly connected components algorithm
        # with added self-dependency check to find dependency cyclces.

        # Index is just an integer, it's wrapped in a list as a workaround for
        # Python 2's lack of `nonlocal` keyword, so the nested
        # `strongconnect()` may modify it.
        index = [0]

        indices = {}
        lowlinks = {}
        stack = []

        def strongconnect(specification):
            # Set the depth index for the node to the smallest unused index.
            indices[specification] = index[0]
            lowlinks[specification] = index[0]
            index[0] += 1
            stack.append(specification)
            provider = self.providers[specification]
            dependencies = six.itervalues(provider.dependencies)
            for dependency in dependencies:
                if isinstance(dependency, Factory):
                    dependency = dependency.specification
                if dependency not in self.providers:
                    raise MissingDependencyError(specification, dependency)
                if dependency == specification:
                    raise SelfDependencyError(specification)
                if dependency not in indices:
                    # Dependency has not yet been visited; recurse on it.
                    strongconnect(dependency)
                    lowlinks[specification] = min(
                        lowlinks[specification],
                        lowlinks[dependency]
                    )
                elif dependency in stack:
                    # Dependency is in stack and hence in the current strongly
                    # connected component.
                    lowlinks[specification] = min(
                        lowlinks[specification],
                        indices[dependency]
                    )
            if lowlinks[specification] == indices[specification]:
                component = []
                while True:
                    component.append(stack.pop())
                    if component[-1] == specification:
                        break
                if len(component) > 1:
                    raise DependencyCycleError(reversed(component))

        for specification, provider in six.iteritems(self.providers):
            if specification not in indices:
                strongconnect(specification)