@Override
    public ObjectiveTranslation doTranslate(NextObjective obj)
            throws FabricPipelinerException {

        final ObjectiveTranslation.Builder resultBuilder =
                ObjectiveTranslation.builder();

        switch (obj.type()) {
            case SIMPLE:
                simpleNext(obj, resultBuilder, false);
                break;
            case HASHED:
                hashedNext(obj, resultBuilder);
                break;
            case BROADCAST:
                if (isXconnect(obj)) {
                    xconnectNext(obj, resultBuilder);
                } else {
                    multicastNext(obj, resultBuilder);
                }
                break;
            default:
                log.warn("Unsupported NextObjective type '{}'", obj);
                return ObjectiveTranslation.ofError(ObjectiveError.UNSUPPORTED);
        }

        if (!isGroupModifyOp(obj)) {
            // Generate next MPLS and VLAN rules.
            nextMpls(obj, resultBuilder);
            nextVlan(obj, resultBuilder);
        }

        return resultBuilder.build();
    }
@Test
    public void testHashedOutput() throws Exception {
        PiAction piAction1 = PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
                .withParameter(new PiActionParam(
                        FabricConstants.SMAC, ROUTER_MAC.toBytes()))
                .withParameter(new PiActionParam(
                        FabricConstants.DMAC, HOST_MAC.toBytes()))
                .withParameter(new PiActionParam(
                        FabricConstants.PORT_NUM, PORT_1.toLong()))
                .build();
        PiAction piAction2 = PiAction.builder()
                .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
                .withParameter(new PiActionParam(
                        FabricConstants.SMAC, ROUTER_MAC.toBytes()))
                .withParameter(new PiActionParam(
                        FabricConstants.DMAC, HOST_MAC.toBytes()))
                .withParameter(new PiActionParam(
                        FabricConstants.PORT_NUM, PORT_1.toLong()))
                .build();
        TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
                .piTableAction(piAction1)
                .build();
        TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
                .piTableAction(piAction2)
                .build();

        NextObjective nextObjective = DefaultNextObjective.builder()
                .withId(NEXT_ID_1)
                .withPriority(PRIORITY)
                .withMeta(VLAN_META)
                .addTreatment(treatment1)
                .addTreatment(treatment2)
                .withType(NextObjective.Type.HASHED)
                .makePermanent()
                .fromApp(APP_ID)
                .add();

        ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);

        // Expected hashed table flow rule.
        PiCriterion nextIdCriterion = PiCriterion.builder()
                .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
                .build();
        TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
                .matchPi(nextIdCriterion)
                .build();
        PiActionProfileGroupId actionGroupId = PiActionProfileGroupId.of(NEXT_ID_1);
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .piTableAction(actionGroupId)
                .build();
        FlowRule expectedFlowRule = DefaultFlowRule.builder()
                .forDevice(DEVICE_ID)
                .fromApp(APP_ID)
                .makePermanent()
                // FIXME: currently next objective doesn't support priority, ignore this
                .withPriority(0)
                .forTable(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)
                .withSelector(nextIdSelector)
                .withTreatment(treatment)
                .build();

        // Expected group
        List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
        List<GroupBucket> buckets = treatments.stream()
                .map(DefaultGroupBucket::createSelectGroupBucket)
                .collect(Collectors.toList());
        GroupBuckets groupBuckets = new GroupBuckets(buckets);
        PiGroupKey groupKey = new PiGroupKey(FabricConstants.FABRIC_INGRESS_NEXT_HASHED,
                                             FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR,
                                             NEXT_ID_1);
        GroupDescription expectedGroup = new DefaultGroupDescription(
                DEVICE_ID,
                GroupDescription.Type.SELECT,
                groupBuckets,
                groupKey,
                NEXT_ID_1,
                APP_ID
        );

        ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
                .addFlowRule(expectedFlowRule)
                .addFlowRule(vlanMetaFlowRule)
                .addGroup(expectedGroup)
                .build();

        assertEquals(expectedTranslation, actualTranslation);

    }