def jvm_dependency_map(self):
    """A map of each JvmTarget in the context to the set of JvmTargets it depends on "directly".

    "Directly" is in quotes here because it isn't quite the same as its normal use, which would be
    filter(self._is_jvm_target, target.dependencies).

    For this method, we define the set of dependencies which `target` depends on "directly" as:

    { dep | dep is a JvmTarget and exists a directed path p from target to dep such that |p| = 1 }

    Where |p| is computed as the weighted sum of all edges in the path, where edges to a JvmTarget
    have weight 1, and all other edges have weight 0.

    In other words, a JvmTarget 'A' "directly" depends on a JvmTarget 'B' iff there exists a path in
    the directed dependency graph from 'A' to 'B' such that there are no internal vertices in the
    path that are JvmTargets.

    This set is a (not necessarily proper) subset of the set of all JvmTargets that the target
    transitively depends on. The algorithms using this map *would* operate correctly on the full
    transitive superset, but it is more efficient to use this subset.

    The intuition for why we can get away with using this subset: Consider targets A, b, C, D,
    such that A depends on b, which depends on C, which depends on D. Say A,C,D are JvmTargets.

    If A is on java 6 and C is on java 7, we obviously have a problem, and this will be correctly
    identified when verifying the jvm dependencies of A, because the path A->b->C has length 1.

    If instead, A is on java 6, and C is on java 6, but D is on java 7, we still have a problem.
    It will not be detected when processing A, because A->b->C->D has length 2. But when we process
    C, it will be picked up, because C->D has length 1.

    Unfortunately, we can't do something as simple as just using actual direct dependencies, because
    it's perfectly legal for a java 6 A to depend on b (which is a non-JvmTarget), and legal for
    b to depend on a java 7 C, so the transitive information is needed to correctly identify the
    problem.

    :return: the dict mapping JvmTarget -> set of JvmTargets.
    """
    jvm_deps = self._unfiltered_jvm_dependency_map()
    return {target: deps for target, deps in jvm_deps.items()
            if deps and self._is_jvm_target(target)}
A map of each JvmTarget in the context to the set of JvmTargets it depends on "directly".

    "Directly" is in quotes here because it isn't quite the same as its normal use, which would be
    filter(self._is_jvm_target, target.dependencies).

    For this method, we define the set of dependencies which `target` depends on "directly" as:

    { dep | dep is a JvmTarget and exists a directed path p from target to dep such that |p| = 1 }

    Where |p| is computed as the weighted sum of all edges in the path, where edges to a JvmTarget
    have weight 1, and all other edges have weight 0.

    In other words, a JvmTarget 'A' "directly" depends on a JvmTarget 'B' iff there exists a path in
    the directed dependency graph from 'A' to 'B' such that there are no internal vertices in the
    path that are JvmTargets.

    This set is a (not necessarily proper) subset of the set of all JvmTargets that the target
    transitively depends on. The algorithms using this map *would* operate correctly on the full
    transitive superset, but it is more efficient to use this subset.

    The intuition for why we can get away with using this subset: Consider targets A, b, C, D,
    such that A depends on b, which depends on C, which depends on D. Say A,C,D are JvmTargets.

    If A is on java 6 and C is on java 7, we obviously have a problem, and this will be correctly
    identified when verifying the jvm dependencies of A, because the path A->b->C has length 1.

    If instead, A is on java 6, and C is on java 6, but D is on java 7, we still have a problem.
    It will not be detected when processing A, because A->b->C->D has length 2. But when we process
    C, it will be picked up, because C->D has length 1.

    Unfortunately, we can't do something as simple as just using actual direct dependencies, because
    it's perfectly legal for a java 6 A to depend on b (which is a non-JvmTarget), and legal for
    b to depend on a java 7 C, so the transitive information is needed to correctly identify the
    problem.

    :return: the dict mapping JvmTarget -> set of JvmTargets.