private static boolean canSatisfyConstraints(ApplicationId appId,
      PlacementConstraint constraint, SchedulerNode node,
      AllocationTagsManager atm,
      Optional<DiagnosticsCollector> dcOpt)
      throws InvalidAllocationTagsQueryException {
    if (constraint == null) {
      LOG.debug("Constraint is found empty during constraint validation for"
          + " app:{}", appId);
      return true;
    }

    // If this is a single constraint, transform to SingleConstraint
    SingleConstraintTransformer singleTransformer =
        new SingleConstraintTransformer(constraint);
    constraint = singleTransformer.transform();
    AbstractConstraint sConstraintExpr = constraint.getConstraintExpr();

    // TODO handle other type of constraints, e.g CompositeConstraint
    if (sConstraintExpr instanceof SingleConstraint) {
      SingleConstraint single = (SingleConstraint) sConstraintExpr;
      return canSatisfySingleConstraint(appId, single, node, atm, dcOpt);
    } else if (sConstraintExpr instanceof And) {
      And and = (And) sConstraintExpr;
      return canSatisfyAndConstraint(appId, and, node, atm, dcOpt);
    } else if (sConstraintExpr instanceof Or) {
      Or or = (Or) sConstraintExpr;
      return canSatisfyOrConstraint(appId, or, node, atm, dcOpt);
    } else {
      throw new InvalidAllocationTagsQueryException(
          "Unsupported type of constraint: "
              + sConstraintExpr.getClass().getSimpleName());
    }
  }
@Test
  public void testORConstraintAssignment()
      throws InvalidAllocationTagsQueryException {
    AllocationTagsManager tm = new AllocationTagsManager(rmContext);
    PlacementConstraintManagerService pcm =
        new MemoryPlacementConstraintManager();
    // Register App1 with anti-affinity constraint map.
    pcm.registerApplication(appId1, constraintMap4);
    RMNode n0r1 = rmNodes.get(0);
    RMNode n1r1 = rmNodes.get(1);
    RMNode n2r2 = rmNodes.get(2);
    RMNode n3r2 = rmNodes.get(3);

    /**
     * Place container:
     *  n0: hbase-m(1)
     *  n1: ""
     *  n2: hbase-rs(1)
     *  n3: ""
     */
    tm.addContainer(n0r1.getNodeID(),
        newContainerId(appId1, 1), ImmutableSet.of("hbase-m"));
    tm.addContainer(n2r2.getNodeID(),
        newContainerId(appId1, 2), ImmutableSet.of("hbase-rs"));
    Assert.assertEquals(1L, tm.getAllocationTagsWithCount(n0r1.getNodeID())
        .get("hbase-m").longValue());
    Assert.assertEquals(1L, tm.getAllocationTagsWithCount(n2r2.getNodeID())
        .get("hbase-rs").longValue());

    SchedulerNode schedulerNode0 =newSchedulerNode(n0r1.getHostName(),
        n0r1.getRackName(), n0r1.getNodeID());
    SchedulerNode schedulerNode1 =newSchedulerNode(n1r1.getHostName(),
        n1r1.getRackName(), n1r1.getNodeID());
    SchedulerNode schedulerNode2 =newSchedulerNode(n2r2.getHostName(),
        n2r2.getRackName(), n2r2.getNodeID());
    SchedulerNode schedulerNode3 =newSchedulerNode(n3r2.getHostName(),
        n3r2.getRackName(), n3r2.getNodeID());

    // n0 and n2 should be qualified for allocation as
    // they either have hbase-m or hbase-rs tag
    Assert.assertTrue(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag1), schedulerNode0, pcm, tm));
    Assert.assertFalse(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag1), schedulerNode1, pcm, tm));
    Assert.assertTrue(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag1), schedulerNode2, pcm, tm));
    Assert.assertFalse(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag1), schedulerNode3, pcm, tm));

    /**
     * Place container:
     *  n0: hbase-m(1)
     *  n1: ""
     *  n2: hbase-rs(1)
     *  n3: hbase-rs(1)
     */
    tm.addContainer(n3r2.getNodeID(),
        newContainerId(appId1, 2), ImmutableSet.of("hbase-rs"));
    // n3 is qualified now because it is allocated with hbase-rs tag
    Assert.assertTrue(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag1), schedulerNode3, pcm, tm));

    /**
     * Place container:
     *  n0: hbase-m(1)
     *  n1: ""
     *  n2: hbase-rs(1), spark(1)
     *  n3: hbase-rs(1)
     */
    // Place
    tm.addContainer(n2r2.getNodeID(),
        newContainerId(appId1, 3), ImmutableSet.of("spark"));
    // According to constraint, "zk" is allowed to be placed on a node
    // has "hbase-m" tag OR a node has both "hbase-rs" and "spark" tags.
    Assert.assertTrue(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag2), schedulerNode0, pcm, tm));
    Assert.assertFalse(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag2), schedulerNode1, pcm, tm));
    Assert.assertTrue(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag2), schedulerNode2, pcm, tm));
    Assert.assertFalse(PlacementConstraintsUtil.canSatisfyConstraints(appId1,
        createSchedulingRequest(sourceTag2), schedulerNode3, pcm, tm));
  }