class MultiPointToSinglePointIntentCompiler implements IntentCompiler<MultiPointToSinglePointIntent> {

    @Override
    public List<Intent> compile(MultiPointToSinglePointIntent intent, List<Intent> installable) {
        Map<DeviceId, Link> links = new HashMap<>();
        ConnectPoint egressPoint = intent.egressPoint();

        final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
        boolean partialTree = false;
        boolean anyMissingPaths = false;
        for (ConnectPoint ingressPoint : intent.ingressPoints()) {
            if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
                if (deviceService.isAvailable(ingressPoint.deviceId())) {
                    partialTree = true;
                } else {
                    anyMissingPaths = true;
                }

                continue;
            }

            Path path = getPath(ingressPoint, intent.egressPoint());
            if (path != null) {
                partialTree = true;

                for (Link link : path.links()) {
                    if (links.containsKey(link.dst().deviceId())) {
                        // We've already reached the existing tree with the first
                        // part of this path. Add the merging point with different
                        // incoming port, but don't add the remainder of the path
                        // in case it differs from the path we already have.
                        links.put(link.src().deviceId(), link);
                        break;
                    }
                    links.put(link.src().deviceId(), link);
                }
            } else {
                anyMissingPaths = true;
            }
        }

        if (!partialTree) {
            throw new IntentException("Could not find any paths between ingress and egress points.");
        } else if (!allowMissingPaths && anyMissingPaths) {
            throw new IntentException("Missing some paths between ingress and egress ports.");
        }

        Intent result = LinkCollectionIntent.builder()
                .appId(intent.appId())
                .selector(intent.selector())
                .treatment(intent.treatment())
                .links(Sets.newHashSet(links.values()))
                .ingressPoints(intent.ingressPoints())
                .egressPoints(ImmutableSet.of(intent.egressPoint()))
                .priority(intent.priority())
                .constraints(intent.constraints())
                .build();

        return Collections.singletonList(result);
    }

}