@Test
  public void testBadOperatorUsage() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");
    final ClauseContext context1 = createContextForProjects(1, 2);
    final ClauseContext context2 = createContextForProjects(5);
    final ClauseContext context3 = createContextForProjects(1292);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);
    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));

    operatorUsageValidator = mock(OperatorUsageValidator.class);
    when(operatorUsageValidator.check(theUser, testClause)).thenReturn(false);
    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context1, context2);
    when(contextSetUtil.union(CollectionBuilder.newBuilder(context1, context2).asSet()))
        .thenReturn(context3);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator);

    assertEquals(context3, factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testGlobalSchemeConfig() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.LIKE, "fine");
    final ClauseContext context3 = createContextForProjects(64);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);

    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme, scheme));
    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context3);
    when(scheme.isGlobal()).thenReturn(false, true);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator);

    assertEquals(
        ClauseContextImpl.createGlobalClauseContext(),
        factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testNegativeQueryWithPositiveAndNegativeOptions() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.NOT_EQUALS, "fine");
    final MockOption option1 = new MockOption(null, null, null, null, null, 25L);
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final MockOption option2child2 = new MockOption(option2, null, null, null, null, 28L);
    final MockOption option2child1 = new MockOption(option2, null, null, null, null, 27L);
    option2.setChildOptions(Arrays.asList(option2child1, option2child2));

    final ClauseContext context1 = createContextForProjects(1, 2);
    final ClauseContext context2 = createContextForProjects(3);
    final ClauseContext context3 = createContextForProjects(3);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);
    when(scheme.isGlobal()).thenReturn(false);

    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));

    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context1, context2);

    // The second scheme should not be included because it only has options that we are to exclude.
    when(jqlSelectOptionsUtil.getOptionsForScheme(scheme))
        .thenReturn(Arrays.<Option>asList(option1, option2))
        .thenReturn(Arrays.<Option>asList(option2, option2child1, option2child2));

    when(contextSetUtil.union(CollectionBuilder.newBuilder(context1, context2).asSet()))
        .thenReturn(context3);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {

            assertEquals(theUser, user);
            assertEquals(testClause, clause);

            positiveOption.add(option2);
            negativeOption.add(option2child1);
          }
        };

    assertEquals(context3, factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testPositiveQueryWithPositiveAndNegativeOptions() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");
    final MockOption option1 = new MockOption(null, null, null, null, null, 25L);
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final MockOption option2child2 = new MockOption(option2, null, null, null, null, 28L);
    final MockOption option2child1 = new MockOption(option2, null, null, null, null, 27L);
    option2.setChildOptions(Arrays.asList(option2child1, option2child2));

    final ClauseContext context1 = createContextForProjects(1, 56);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);
    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));

    // The second scheme has no options in the scheme not in the exclude list.
    when(jqlSelectOptionsUtil.getOptionsForScheme(scheme))
        .thenReturn(Arrays.<Option>asList(option1, option2))
        .thenReturn(Arrays.<Option>asList(option2, option2child1, option2child2));
    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context1);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {
            assertEquals(theUser, user);
            assertEquals(testClause, clause);

            positiveOption.add(option1);
            negativeOption.add(option2);
          }
        };

    assertEquals(context1, factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testNoGeneratedContext() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");
    final MockOption option1 = new MockOption(null, null, null, null, null, 25L);
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final ClauseContext context1 = createContextForProjects(1, 2);
    final ClauseContext context2 = createContextForProjects(5);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);
    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));
    when(jqlSelectOptionsUtil.getOptionsForScheme(scheme))
        .thenReturn(Arrays.<Option>asList(option1, option2));
    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context1, context2);
    when(contextSetUtil.union(CollectionBuilder.newBuilder(context1, context2).asSet()))
        .thenReturn(new ClauseContextImpl());

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {

            assertEquals(theUser, user);
            assertEquals(testClause, clause);

            positiveOption.add(option1);
          }
        };

    assertEquals(
        ClauseContextImpl.createGlobalClauseContext(),
        factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testNegativeQueryWithNoOptions() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.NOT_IN, "fine");
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final MockOption option2child2 = new MockOption(option2, null, null, null, null, 28L);
    final MockOption option2child1 = new MockOption(option2, null, null, null, null, 27L);
    option2.setChildOptions(Arrays.asList(option2child1, option2child2));

    final ClauseContext context2 = createContextForProjects(3);
    final ClauseContext context3 = createContextForProjects(64);
    final ClauseContext context4 = createContextForProjects(34938);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);
    when(scheme.isGlobal()).thenReturn(false);

    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));

    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context3, context2);
    when(contextSetUtil.union(CollectionBuilder.newBuilder(context2, context3).asSet()))
        .thenReturn(context4);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {
            assertEquals(theUser, user);
            assertEquals(testClause, clause);
          }
        };

    assertEquals(context4, factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testNullSchemes() throws Exception {
    final TerminalClause clause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");

    when(customField.getConfigurationSchemes()).thenReturn(null);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator);
    final ClauseContext clauseContext = factory.getClauseContext(theUser, clause);

    assertEquals(ClauseContextImpl.createGlobalClauseContext(), clauseContext);
  }
  @Test
  public void testPositiveQueryWithNoPositive() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");
    final MockOption option1 = new MockOption(null, null, null, null, null, 25L);
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final MockOption option2child2 = new MockOption(option2, null, null, null, null, 28L);
    final MockOption option2child1 = new MockOption(option2, null, null, null, null, 27L);
    option2.setChildOptions(Arrays.asList(option2child1, option2child2));

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);

    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));
    when(scheme.isGlobal()).thenReturn(true);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {
            assertEquals(theUser, user);
            assertEquals(testClause, clause);

            negativeOption.add(option2);
            negativeOption.add(option1);
          }
        };

    assertEquals(
        ClauseContextImpl.createGlobalClauseContext(),
        factory.getClauseContext(theUser, testClause));
  }
  @Test
  public void testPositiveQueryWithPositiveAndEmpty() throws Exception {
    final TerminalClause testClause = new TerminalClauseImpl("one", Operator.EQUALS, "fine");
    final ClauseContext context1 = createContextForProjects(1, 56);

    final FieldConfigScheme scheme = mock(FieldConfigScheme.class);

    when(customField.getConfigurationSchemes()).thenReturn(Arrays.asList(scheme, scheme));
    when(scheme.isGlobal()).thenReturn(false, true);
    when(fieldConfigSchemeClauseContextUtil.getContextForConfigScheme(theUser, scheme))
        .thenReturn(context1);

    final CascadingSelectCustomFieldClauseContextFactory factory =
        new CascadingSelectCustomFieldClauseContextFactory(
            customField,
            contextSetUtil,
            jqlSelectOptionsUtil,
            fieldConfigSchemeClauseContextUtil,
            jqlOperandResolver,
            jqlCascadingSelectLiteralUtil,
            operatorUsageValidator) {
          @Override
          void fillOptions(
              final User user,
              final TerminalClause clause,
              final Set<Option> positiveOption,
              final Set<Option> negativeOption) {
            assertEquals(theUser, user);
            assertEquals(testClause, clause);

            positiveOption.add(null);
          }
        };

    assertEquals(
        ClauseContextImpl.createGlobalClauseContext(),
        factory.getClauseContext(theUser, testClause));
  }