@Test
  public void testFillOptions() throws Exception {
    final Operand operand = new SingleValueOperand("one");
    final TerminalClause testClause = new TerminalClauseImpl("test", Operator.EQUALS, operand);
    final QueryLiteral literal1 = new QueryLiteral(operand, 1L);
    final QueryLiteral literal2 = new QueryLiteral(operand, 2L);
    final QueryLiteral literal3 = new QueryLiteral(operand, 3L);
    final MockOption option1 = new MockOption(null, null, null, null, null, 25L);
    final MockOption option2 = new MockOption(null, null, null, null, null, 26L);
    final MockOption option3 = new MockOption(null, null, null, null, null, 242L);
    final MockOption option4 = new MockOption(null, null, null, null, null, 27L);

    final List<QueryLiteral> testLiterals = Arrays.asList(literal1, literal2, literal3);

    when(jqlOperandResolver.getValues(theUser, operand, testClause)).thenReturn(testLiterals);

    jqlCascadingSelectLiteralUtil =
        new JqlCascadingSelectLiteralUtil(jqlSelectOptionsUtil) {
          @Override
          public void processPositiveNegativeOptionLiterals(
              final List<QueryLiteral> inputLiterals,
              final List<QueryLiteral> positiveLiterals,
              final List<QueryLiteral> negativeLiterals) {
            assertEquals(testLiterals, inputLiterals);
            positiveLiterals.add(literal1);
            positiveLiterals.add(literal2);
            negativeLiterals.add(literal3);
          }
        };

    when(jqlSelectOptionsUtil.getOptions(customField, literal1, true))
        .thenReturn(Collections.<Option>singletonList(option1));
    when(jqlSelectOptionsUtil.getOptions(customField, literal2, true))
        .thenReturn(Arrays.<Option>asList(option2, option3));
    when(jqlSelectOptionsUtil.getOptions(customField, literal3, true))
        .thenReturn(Arrays.<Option>asList(option4));

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

    Set<Option> posOpts = new HashSet<Option>();
    Set<Option> negOpts = new HashSet<Option>();

    factory.fillOptions(theUser, testClause, posOpts, negOpts);

    assertEquals(CollectionBuilder.<Option>newBuilder(option1, option2, option3).asSet(), posOpts);
    assertEquals(CollectionBuilder.<Option>newBuilder(option4).asSet(), negOpts);
  }
  @Test
  public void testGetClauseFromParamsValuesGetFiltered() throws Exception {
    final String clauseName = "clauseName";

    final CustomField customField = mockController.getMock(CustomField.class);
    EasyMock.expect(customField.getName()).andStubReturn("ABC");
    EasyMock.expect(customFieldInputHelper.getUniqueClauseName(theUser, clauseName, "ABC"))
        .andStubReturn(clauseName);

    final CustomFieldParamsImpl customFieldParams = new CustomFieldParamsImpl();
    customFieldParams.addValue(CollectionBuilder.newBuilder("55", "-1", "").asMutableSet());

    final Set<String> expectedFilteredValues = CollectionBuilder.newBuilder("55").asMutableSet();

    final Clause expectedClause = mockController.getMock(Clause.class);

    final IndexedInputHelper indexedInputHelper = mockController.getMock(IndexedInputHelper.class);
    indexedInputHelper.getClauseForNavigatorValues(clauseName, expectedFilteredValues);
    mockController.setReturnValue(expectedClause);

    transformer =
        new VersionCustomFieldSearchInputTransformer(
            clauseName,
            new ClauseNames(clauseName),
            customField,
            indexInfoResolver,
            operandResolver,
            fieldFlagOperandRegistry,
            searchContextVisibilityChecker,
            versionResolver,
            customFieldInputHelper,
            versionManager) {
          @Override
          IndexedInputHelper getIndexedInputHelper() {
            return indexedInputHelper;
          }

          @Override
          boolean isVersionsNotRelatedToProjects(
              final Set<String> versionIdsFromHolder, final FieldValuesHolder fieldValuesHolder) {
            return false;
          }
        };

    mockController.replay();

    FieldValuesHolder holderValues =
        new FieldValuesHolderImpl(MapBuilder.singletonMap(urlParameterName, customFieldParams));
    assertEquals(
        expectedClause, transformer.getClauseFromParams(theUser, customFieldParams, holderValues));

    mockController.verify();
  }
  /**
   * Make sure the correct search is performed when theh search request does contain "update date"
   * critera and we have determined that they be included in the comment search.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssuesUpdatedFromToDate() throws Exception {
    final String beforeDuration = "-3d";
    final Date beforeDate = dateSupport.convertToDate(beforeDuration);
    final Date afterDate = createDate(1981, Calendar.JANUARY, 12);
    final User user = new MockUser("me");

    final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
    builder
        .where()
        .updated()
        .ltEq(beforeDuration)
        .and()
        .updatedAfter(afterDate)
        .and()
        .priority("major");
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(6L, 3L, 13484L, 11111134L).asList();
    final BooleanQuery query = createIssueQuery(issueIds);

    final BooleanQuery dateQuery = new BooleanQuery();
    dateQuery.add(createBeforeQuery(beforeDate), BooleanClause.Occur.MUST);
    dateQuery.add(createAfterQuery(afterDate), BooleanClause.Occur.MUST);

    query.add(dateQuery, BooleanClause.Occur.MUST);

    _testGetRecentComments(issueIds, request, user, true, query);
  }
  @Test
  public void testTerminalClauseTwoSearchHandlersDifferent() throws Exception {
    final TerminalClause input1 = new TerminalClauseImpl("field", Operator.EQUALS, "Value1");
    final TerminalClause input2 = new TerminalClauseImpl("field", Operator.EQUALS, "Value2");
    final SearchHandlerManager manager = mockController.getMock(SearchHandlerManager.class);

    final ClausePermissionHandler permissionHandler =
        mockController.getMock(ClausePermissionHandler.class);
    EasyMock.expect(permissionHandler.sanitise(null, input1)).andReturn(input1);
    EasyMock.expect(permissionHandler.sanitise(null, input1)).andReturn(input2);

    final ClauseHandler handler1 = new MockClauseHandler(null, null, permissionHandler, null);
    final ClauseHandler handler2 = new MockClauseHandler(null, null, permissionHandler, null);

    EasyMock.expect(manager.getClauseHandler((User) null, "field"))
        .andReturn(CollectionBuilder.newBuilder(handler1, handler2).asList());

    final JqlOperandResolver jqlOperandResolver = mockController.getMock(JqlOperandResolver.class);

    mockController.replay();

    ClauseSanitisingVisitor visitor =
        new ClauseSanitisingVisitor(manager, jqlOperandResolver, null) {
          @Override
          TerminalClause sanitiseOperands(final TerminalClause clause) {
            return clause;
          }
        };

    final Clause expected = new OrClause(input1, input2);
    final Clause clause = input1.accept(visitor);
    assertEquals(expected, clause);

    mockController.verify();
  }
  @Test
  public void testAllTypes() {
    final ProjectPermissionPageTab projectPermissionPage =
        jira.gotoLoginPage().loginAsSysAdmin(ProjectPermissionPageTab.class, "CHOC");
    assertEquals("Choc Full Scheme", projectPermissionPage.getSchemeName());
    assertEquals("Choc Full Permission Scheme", projectPermissionPage.getSchemeDescription());

    final Permission permission = projectPermissionPage.getPermissionByName("Create Issues");
    final List<String> entities = permission.getEntities();
    final List<String> expectedEntities =
        CollectionBuilder.newBuilder(
                "Reporter",
                "Group (jira-administrators)",
                "Group (Anyone)",
                "Single User (admin)",
                "Project Lead",
                "Current Assignee",
                "Project Role (Administrators)",
                "User Custom Field Value (User Picker)",
                "Group Custom Field Value (Group Picker)")
            .asList();
    assertEquals(expectedEntities, entities);

    final ProjectSharedBy sharedBy = projectPermissionPage.getSharedBy();
    assertFalse(sharedBy.isPresent());
  }
  @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 testConstructor() throws Exception {
    try {
      new OrderByImpl((Collection<SearchSort>) null);
      fail("Expected an error");
    } catch (IllegalArgumentException e) {
    }

    try {
      new OrderByImpl((SearchSort[]) null);
      fail("Expected an error");
    } catch (IllegalArgumentException e) {
    }

    try {
      new OrderByImpl(new SearchSort("dumpper", SortOrder.DESC), null);
      fail("Expected an error");
    } catch (IllegalArgumentException e) {
    }

    try {
      new OrderByImpl(
          CollectionBuilder.newBuilder(new SearchSort("dump", SortOrder.ASC), null).asList());
      fail("Expected an error.");
    } catch (IllegalArgumentException e) {
    }
  }
 private Set<ProjectIssueTypeContext> getContextsForProjects(final Collection<Project> projects) {
   CollectionBuilder<ProjectIssueTypeContext> builder = CollectionBuilder.newBuilder();
   for (Project project : projects) {
     builder.add(
         new ProjectIssueTypeContextImpl(
             new ProjectContextImpl(project.getId()), AllIssueTypesContext.INSTANCE));
   }
   return builder.asMutableSet();
 }
  /**
   * Make sure a pure issue key search is given when issues are found. Also, make sure there are no
   * "updated date" critera added to the query.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssues() throws Exception {

    final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
    builder.where().updatedBetween(createDate(1996, Calendar.SEPTEMBER, 11), null);
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(1L, 2L, 4L, 5L).asList();
    _testGetRecentComments(issueIds, request, null, false, createIssueQuery(issueIds));
  }
  @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 testGetSorts() throws Exception {
    List<SearchSort> inputSorts =
        CollectionBuilder.newBuilder(new SearchSort("one"), new SearchSort("two")).asMutableList();
    List<SearchSort> expectedSorts = new ArrayList<SearchSort>(inputSorts);

    OrderByImpl impl = new OrderByImpl(inputSorts);
    inputSorts.clear();

    assertEquals(expectedSorts, impl.getSearchSorts());
  }
  @Test
  public void testGetClauseFromParamsFilteredValuesEmpty() throws Exception {
    final CustomFieldParams customFieldParams = mockController.getMock(CustomFieldParams.class);
    customFieldParams.getAllValues();
    mockController.setReturnValue(CollectionBuilder.newBuilder("").asMutableSet());

    final VersionCustomFieldSearchInputTransformer inputTransformer =
        createTransformer("cf[12345]");

    assertNull(inputTransformer.getClauseFromParams(theUser, customFieldParams, null));

    mockController.verify();
  }
  /**
   * Make sure the correct search is performed when theh search request does contain "update date"
   * critera and we have determined that they be included in the comment search.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssuesUpdatedToAbsoluteDate() throws Exception {
    final Date beforeDate = createDate(1994, Calendar.JANUARY, 26);

    final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
    builder.where().updated().ltEq(beforeDate);
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(5674L).asList();
    final BooleanQuery query = createIssueQuery(issueIds);

    final TermRangeQuery dateQuery = createBeforeQuery(beforeDate);
    query.add(dateQuery, BooleanClause.Occur.MUST);

    _testGetRecentComments(issueIds, request, null, true, query);
  }
  /**
   * Make sure the correct search is performed when theh search request does contain "update date"
   * critera and we have determined that they be included in the comment search.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssuesUpdatedFromAbsoluteDate() throws Exception {
    final Date afterDate = createDate(2006, Calendar.JANUARY, 26);

    builder = JqlQueryBuilder.newBuilder();
    builder.where().updatedAfter(afterDate);
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(5674L).asList();
    final BooleanQuery query = createIssueQuery(issueIds);

    final org.apache.lucene.search.Query dateQuery = createAfterQuery(afterDate);
    query.add(dateQuery, BooleanClause.Occur.MUST);

    _testGetRecentComments(issueIds, request, null, true, query);
  }
  /**
   * Make sure the correct search is performed when theh search request does contain "update date"
   * critera and we have determined that they be included in the comment search.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssuesUpdatedToRelativeDate() throws Exception {
    final String beforeDuration = "-3d";
    final Date beforeDate = dateSupport.convertToDate(beforeDuration);

    final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
    builder.where().updated().ltEq(beforeDuration);
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(5674L).asList();
    final BooleanQuery query = createIssueQuery(issueIds);

    final TermRangeQuery dateQuery = createBeforeQuery(beforeDate);
    query.add(dateQuery, BooleanClause.Occur.MUST);

    _testGetRecentComments(issueIds, request, null, true, query);
  }
  @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 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 testGetIndexedValuesStringHappyPath() throws Exception {
    final MockComponent mockComponent1 = new MockComponent(1L, "component1");
    final MockComponent mockComponent2 = new MockComponent(2L, "component1");

    final NameResolver<ProjectComponent> nameResolver = mockController.getMock(NameResolver.class);
    nameResolver.getIdsFromName("component1");
    mockController.setReturnValue(CollectionBuilder.newBuilder("1", "2").asList());
    mockController.replay();

    ComponentIndexInfoResolver resolver = new ComponentIndexInfoResolver(nameResolver);

    final List<String> result = resolver.getIndexedValues("component1");
    assertEquals(2, result.size());
    assertTrue(result.contains(mockComponent1.getId().toString()));
    assertTrue(result.contains(mockComponent2.getId().toString()));

    mockController.verify();
  }
  @Test
  public void testXSS() {
    final ProjectPermissionPageTab projectPermissionPage =
        jira.gotoLoginPage().loginAsSysAdmin(ProjectPermissionPageTab.class, "XSS");
    assertEquals("<script>alert(\"wtf\");</script>", projectPermissionPage.getSchemeName());
    assertEquals("<script>alert(\"wtf\");</script>", projectPermissionPage.getSchemeDescription());
    final Permission permission = projectPermissionPage.getPermissionByName("Administer Projects");

    final List<String> entities = permission.getEntities();
    final List<String> expectedEntities =
        CollectionBuilder.newBuilder("User Custom Field Value (<script>alert(\"wtf\");</script>)")
            .asList();
    assertEquals(expectedEntities, entities);

    final ProjectSharedBy sharedBy = projectPermissionPage.getSharedBy();
    assertTrue(sharedBy.isPresent());
    assertEquals("2 projects", sharedBy.getTriggerText());
    assertEquals(
        Arrays.asList("<script>alert(\"wtf\");</script>", "Another Shared project"),
        sharedBy.getProjects());
  }
  /**
   * Make sure the correct search is performed when theh search request does contain "update date",
   * but that criteria cannot be converted into a filter, that is, when all the "updated date"
   * clauses are not anded together.
   *
   * @throws Exception indicates some unexpected failure.
   */
  @Test
  public void testGetRecentCommentsIssuesBad() throws Exception {
    final String beforeDuration = "-3d";
    final Date afterDate = createDate(1981, Calendar.JANUARY, 12);
    final User user = new MockUser("me");

    final JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
    builder
        .where()
        .updatedAfter(afterDate)
        .and()
        .sub()
        .priority("minor")
        .or()
        .updated()
        .ltEq(beforeDuration)
        .endsub();
    final SearchRequest request = new SearchRequest(builder.buildQuery());

    final List<Long> issueIds = CollectionBuilder.newBuilder(6L, 3L, 13484L, 11111134L).asList();
    final BooleanQuery query = createIssueQuery(issueIds);

    _testGetRecentComments(issueIds, request, user, true, query);
  }
Пример #21
0
public class DefaultOfBizDelegator implements OfBizDelegator {
  private static final Logger log = Logger.getLogger(DefaultOfBizDelegator.class);
  private static final int DEFAULT_DATABASE_QUERY_BATCH_SIZE = 100;
  private static final String COUNT_FIELD_NAME = "count";
  private static final Collection<String> UNSUPPORTED_TYPES_FOR_FINDBY =
      CollectionBuilder.newBuilder("very-long", "extremely-long", "text", "blob").asCollection();

  public static int getQueryBatchSize() {
    String size = null;
    try {
      size =
          ComponentAccessor.getApplicationProperties()
              .getDefaultBackedString(APKeys.DATABASE_QUERY_BATCH_SIZE);
      return Integer.parseInt(size);
    } catch (final NumberFormatException e) {
      log.error(
          "Error while converting database query batch size '"
              + size
              + "'. Using default value of "
              + DEFAULT_DATABASE_QUERY_BATCH_SIZE);
      return DEFAULT_DATABASE_QUERY_BATCH_SIZE;
    }
  }

  private final DelegatorInterface delegatorInterface;
  private final FieldSupportValidator findByValidator;

  public DefaultOfBizDelegator(final DelegatorInterface delegatorInterface) {
    this.delegatorInterface = delegatorInterface;
    findByValidator =
        new FieldSupportValidator("findBy", UNSUPPORTED_TYPES_FOR_FINDBY, new FieldTypeResolver());
  }

  public List<GenericValue> findByField(
      final String entityName, final String fieldName, final Object fieldValue) {
    return findByAnd(entityName, new FieldMap(fieldName, fieldValue));
  }

  public List<GenericValue> findByField(
      final String entityName,
      final String fieldName,
      final Object fieldValue,
      final String orderBy) {
    return findByAnd(
        entityName, new FieldMap(fieldName, fieldValue), CollectionBuilder.list(orderBy));
  }

  public List<GenericValue> findByAnd(final String entityName, final Map<String, ?> fields)
      throws DataAccessException {
    findByValidator.checkAll(entityName, fields.keySet());
    try {
      return delegatorInterface.findByAnd(entityName, fields);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findByAnd(
      final String entityName, final Map<String, ?> fields, final List<String> orderBy)
      throws DataAccessException {
    findByValidator.checkAll(entityName, fields.keySet());
    try {
      return delegatorInterface.findByAnd(entityName, fields, orderBy);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findByAnd(
      final String entityName, final List<EntityCondition> expressions) throws DataAccessException {
    // cannot check EntityCondition instances as they don't give us a where condition
    try {
      return delegatorInterface.findByAnd(entityName, expressions);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findByOr(
      final String entityName, final List expressions, final List orderBy)
      throws DataAccessException {
    try {
      if (orderBy != null) {
        return delegatorInterface.findByOr(entityName, expressions, orderBy);
      } else {
        return delegatorInterface.findByOr(entityName, expressions);
      }
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findByLike(final String s, final Map<String, ?> map)
      throws DataAccessException {
    return findByLike(s, map, Collections.<String>emptyList());
  }

  public List<GenericValue> findByLike(
      final String s, final Map<String, ?> map, final List<String> orderBy)
      throws DataAccessException {
    try {
      return delegatorInterface.findByLike(s, map, orderBy);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public void removeAll(final List<GenericValue> genericValues) throws DataAccessException {
    try {
      delegatorInterface.removeAll(genericValues, false);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public int removeByCondition(String entityName, EntityCondition condition)
      throws DataAccessException {
    try {
      return delegatorInterface.removeByCondition(entityName, condition, false);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findByCondition(
      final String entityName,
      final EntityCondition entityCondition,
      final Collection<String> fieldsToSelect) {
    return findByCondition(
        entityName, entityCondition, fieldsToSelect, Collections.<String>emptyList());
  }

  public List<GenericValue> findByCondition(
      final String entityName,
      final EntityCondition entityCondition,
      final Collection<String> fieldsToSelect,
      final List<String> orderBy) {
    try {
      return delegatorInterface.findByCondition(
          entityName, entityCondition, fieldsToSelect, orderBy);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public int removeByOr(final String entityName, final String entityId, final List<Long> ids)
      throws DataAccessException, GenericModelException {
    int result = 0;

    final ModelEntity modelEntity = delegatorInterface.getModelEntity(entityName);

    if (modelEntity == null) {
      throw new GenericModelException("The entityName passed in was not valid: " + entityName);
    } else if (!modelEntity.isField(entityId)) {
      throw new GenericModelException(
          "The entityId passed in was not valid for the given entity: " + entityId);
    }
    final ModelField modelField = modelEntity.getField(entityId);

    try {
      final GenericHelper entityHelper = delegatorInterface.getEntityHelper(entityName);
      // Generate SQL
      final StringBuilder removeSql = new StringBuilder("DELETE FROM ");

      removeSql.append(modelEntity.getTableName(entityHelper.getHelperName()));
      removeSql.append(" WHERE ");
      removeSql.append(modelField.getColName());
      removeSql.append(" IN (");

      final int idsSize = ids.size();
      final ArrayList<Long> idParams = new ArrayList<Long>();
      StringBuilder idClause = new StringBuilder();

      // batch the update
      final int batchSize = getQueryBatchSize();
      int batchIndex = 0;
      for (int i = 0; i < idsSize; i++) {
        idParams.add(ids.get(i));
        idClause.append("?");

        final boolean isEndOfBatch = (batchIndex == batchSize - 1);
        final boolean isEndOfIdList = (i == idsSize - 1);

        if (isEndOfBatch || isEndOfIdList) {
          final SQLProcessor processor = new AutoCommitSQLProcessor(entityHelper.getHelperName());
          // finish batch
          idClause.append(")");
          try {
            processor.prepareStatement(removeSql.toString() + idClause.toString());
            for (final Long idParam : idParams) {
              processor.setValue(idParam);
            }
            // execute update
            result += processor.executeUpdate();

            // clean-up for the next batch
            idParams.clear();
            idClause = new StringBuilder();
            batchIndex = 0;
          } finally {
            try {
              processor.close();
            } catch (final GenericDataSourceException e) {
              log.warn("Could not close the SQLProcessor", e);
            }
          }
        } else {
          // add to this batch
          idClause.append(", ");
          batchIndex++;
        }
      }
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    } catch (final SQLException e) {
      throw new DataAccessException(e);
    }

    return result;
  }

  public int removeByAnd(final String entityName, final Map map) throws DataAccessException {
    try {
      return delegatorInterface.removeByAnd(entityName, map);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public int removeById(String entityName, Long id) {
    return removeByAnd(entityName, FieldMap.build("id", id));
  }

  public int removeValue(final GenericValue value) throws DataAccessException {
    try {
      return delegatorInterface.removeValue(value);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public void storeAll(final List genericValues) throws DataAccessException {
    try {
      delegatorInterface.storeAll(genericValues);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findAll(final String s) {
    try {
      return delegatorInterface.findAll(s);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public List<GenericValue> findAll(final String s, final List sortOrder)
      throws DataAccessException {
    try {
      return delegatorInterface.findAll(s, sortOrder);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public void store(final GenericValue gv) throws DataAccessException {
    try {
      delegatorInterface.store(gv);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public GenericValue createValue(final String entityName, final Map<String, Object> fields) {
    try {
      final Map<String, Object> params =
          (fields == null) ? new HashMap<String, Object>(2) : new HashMap<String, Object>(fields);
      if (params.get("id") == null) {
        final Long id = delegatorInterface.getNextSeqId(entityName);
        params.put("id", id);
      }

      final GenericValue v = delegatorInterface.makeValue(entityName, params);
      v.create();
      return v;
    } catch (final GenericEntityException ex) {
      throw new DataAccessException(ex);
    }
  }

  @Override
  public void createValueWithoutId(final String entityName, final Map<String, Object> fields)
      throws DataAccessException {
    try {
      final GenericValue v = delegatorInterface.makeValue(entityName, fields);
      v.create();
    } catch (final GenericEntityException ex) {
      throw new DataAccessException(ex);
    }
  }

  public GenericValue makeValue(final String entityName) {
    return delegatorInterface.makeValue(entityName, null);
  }

  @Override
  public GenericValue makeValue(String entityName, Map<String, Object> fields) {
    return delegatorInterface.makeValue(entityName, fields);
  }

  @Override
  public GenericValue findById(String entityName, Long id) throws DataAccessException {
    return findByPrimaryKey(entityName, id);
  }

  public GenericValue findByPrimaryKey(final String entityName, final Long id) {
    // Build up the Map for the caller
    final Map<String, Object> fields = new HashMap<String, Object>(2);
    fields.put("id", id);
    // and delegate to the original findByPrimaryKey() method.
    return findByPrimaryKey(entityName, fields);
  }

  public GenericValue findByPrimaryKey(final String entityName, final Map<String, ?> fields) {
    final long start = System.currentTimeMillis();
    try {
      return delegatorInterface.findByPrimaryKey(entityName, fields);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    } finally {
      ThreadLocalQueryProfiler.store(
          "OfBizDelegator", "findByPrimaryKey", System.currentTimeMillis() - start);
    }
  }

  public List<GenericValue> getRelated(final String relationName, final GenericValue gv) {
    try {
      return delegatorInterface.getRelated(relationName, gv);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public List<GenericValue> getRelated(
      final String relationName, final GenericValue gv, final List<String> orderBy)
      throws DataAccessException {
    try {
      return delegatorInterface.getRelatedOrderBy(relationName, orderBy, gv);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public long getCount(final String entityName) {
    // run a count with no where clause
    return getCountByAnd(entityName, new FieldMap());
  }

  @Override
  public long getCountByAnd(final String entityName, final Map<String, ?> fields) {
    try {
      final EntityCondition condition = new EntityFieldMap(fields, EntityOperator.AND);
      final GenericValue countGV =
          EntityUtil.getOnly(
              delegatorInterface.findByCondition(
                  entityName + "Count", condition, ImmutableList.of(COUNT_FIELD_NAME), null));
      return countGV.getLong(COUNT_FIELD_NAME);
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public OfBizListIterator findListIteratorByCondition(
      final String entityType, final EntityCondition condition) {
    try {
      return new DefaultOfBizListIterator(
          delegatorInterface.findListIteratorByCondition(entityType, condition, null, null));
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  /**
   * Always close the iterator returned from this method when finished.
   *
   * @return OfBizListIterator
   */
  public OfBizListIterator findListIteratorByCondition(
      final String entityName,
      final EntityCondition whereEntityCondition,
      final EntityCondition havingEntityCondition,
      final Collection fieldsToSelect,
      final List orderBy,
      final EntityFindOptions entityFindOptions) {
    try {
      return new DefaultOfBizListIterator(
          delegatorInterface.findListIteratorByCondition(
              entityName,
              whereEntityCondition,
              havingEntityCondition,
              fieldsToSelect,
              orderBy,
              entityFindOptions));
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  public int bulkUpdateByPrimaryKey(
      final String entityName, final Map<String, ?> updateValues, final List<Long> keys) {
    int result = 0;

    if ((entityName == null)
        || (updateValues == null)
        || updateValues.isEmpty()
        || (keys == null)
        || keys.isEmpty()) {
      return 0;
    }

    try {
      final GenericHelper entityHelper = delegatorInterface.getEntityHelper(entityName);
      final ModelEntity modelEntity = delegatorInterface.getModelEntity(entityName);

      final List<String> pks = modelEntity.getPkFieldNames();
      if (pks.size() != 1) {
        throw new DataAccessException(
            "BulkUpdateByPrimaryKey only works for single column keys at this moment.");
      }
      final String pkName = pks.get(0);

      final Updater updater =
          new Updater(
              ModelFieldTypeReader.getModelFieldTypeReader(entityHelper.getHelperName()),
              entityName);
      final List<Updater.Value> params = new ArrayList<Updater.Value>();

      final StringBuilder updateSql = new StringBuilder("UPDATE ");

      updateSql.append(modelEntity.getTableName(entityHelper.getHelperName()));
      updateSql.append(" SET ");
      // generate the update sql
      for (final Iterator<String> iterator = updateValues.keySet().iterator();
          iterator.hasNext(); ) {
        final String column = iterator.next();
        updateSql.append(" ");
        final ModelField field = modelEntity.getField(column);
        updateSql.append(field.getColName());
        updateSql.append(" = ");
        params.add(updater.create(field, updateValues.get(column)));
        updateSql.append("? ");
        if (iterator.hasNext()) {
          updateSql.append(", ");
        }
      }

      // generate the where clause
      updateSql.append(" WHERE ");

      // batch the update
      final int batchSize = getQueryBatchSize();

      int currentIndex = 0;

      while (currentIndex < keys.size()) {
        int i = 0;
        final StringBuilder idClause = new StringBuilder();
        final ArrayList<Long> idParams = new ArrayList<Long>();
        for (final Iterator<Long> iterator = keys.subList(currentIndex, keys.size()).iterator();
            iterator.hasNext() && (i < batchSize);
            i++) {
          final Long key = iterator.next();
          idClause.append(" ");
          idClause.append(pkName);
          idClause.append(" = ");
          idParams.add(key);
          idClause.append("? ");

          if (iterator.hasNext() && ((i + 1) < batchSize)) {
            idClause.append(" or ");
          }
        }

        final SQLProcessor processor = new AutoCommitSQLProcessor(entityHelper.getHelperName());
        processor.prepareStatement(updateSql.toString() + idClause.toString());
        for (final Updater.Value param : params) {
          param.setValue(processor);
        }
        for (final Long idParam : idParams) {
          processor.setValue(idParam);
        }

        try {
          result = processor.executeUpdate();
        } finally {
          processor.close();
        }
        currentIndex += i;
      }
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    } catch (final SQLException e) {
      throw new DataAccessException(e);
    } catch (final NoClassDefFoundError e) {
      // under JDK 1.3 unit tests - javax.sql.XADataSource cannot be found.
      // this shouldn't affect runtime - application servers should ship the jar
    }
    return result;
  }

  public int bulkUpdateByAnd(
      final String entityName, final Map<String, ?> updateValues, final Map<String, ?> criteria) {
    int result = 0;

    if ((entityName == null) || (updateValues == null) || updateValues.isEmpty()) {
      return 0;
    }

    try {
      final ModelEntity modelEntity = delegatorInterface.getModelEntity(entityName);

      final GenericHelper entityHelper = delegatorInterface.getEntityHelper(entityName);

      final ModelFieldTypeReader modelFieldTypeReader =
          ModelFieldTypeReader.getModelFieldTypeReader(entityHelper.getHelperName());

      final ArrayList<EntityConditionParam> params = new ArrayList<EntityConditionParam>();

      // generate the update sql
      final StringBuilder updateSql = new StringBuilder("UPDATE ");

      updateSql.append(modelEntity.getTableName(entityHelper.getHelperName()));
      updateSql.append(" SET ");

      if (!modelEntity.areFields(updateValues.keySet())) {
        throw new GenericModelException(
            "At least one of the passed fields for update is not valid: "
                + updateValues.keySet().toString());
      }

      for (final Iterator<String> iterator = updateValues.keySet().iterator();
          iterator.hasNext(); ) {
        final String fieldName = iterator.next();
        updateSql.append(" ");
        final ModelField modelField = modelEntity.getField(fieldName);
        updateSql.append(modelField.getColName());
        updateSql.append(" = ");
        params.add(new EntityConditionParam(modelField, updateValues.get(fieldName)));
        updateSql.append("? ");
        if (iterator.hasNext()) {
          updateSql.append(", ");
        }
      }

      if ((criteria != null) && !criteria.isEmpty()) {
        if (!modelEntity.areFields(criteria.keySet())) {
          throw new GenericModelException(
              "At least one of the passed fields is not valid: " + criteria.keySet().toString());
        }

        // generate the where clause
        final EntityFieldMap entityCondition = new EntityFieldMap(criteria, EntityOperator.AND);

        final String entityCondWhereString = entityCondition.makeWhereString(modelEntity, params);

        if (entityCondWhereString.length() > 0) {
          updateSql.append(" WHERE ");
          updateSql.append(entityCondWhereString);
        }
      }

      final SQLProcessor processor = new AutoCommitSQLProcessor(entityHelper.getHelperName());
      final String sql = updateSql.toString();

      if (log.isDebugEnabled()) {
        log.debug("Running bulk update SQL: '" + sql + "'");
      }

      processor.prepareStatement(sql);

      for (final EntityConditionParam conditionParam : params) {
        SqlJdbcUtil.setValue(
            processor,
            conditionParam.getModelField(),
            modelEntity.getEntityName(),
            conditionParam.getFieldValue(),
            modelFieldTypeReader);
      }

      try {
        result = processor.executeUpdate();
      } finally {
        processor.close();
      }
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    } catch (final NoClassDefFoundError e) {
      // under JDK 1.3 unit tests - javax.sql.XADataSource cannot be found.
      // this shouldn't affect runtime - application servers should ship the jar
    }

    return result;
  }

  public int bulkCopyColumnValuesByAnd(
      final String entityName, final Map updateColumns, final Map criteria) {
    int result = 0;

    if ((entityName == null) || (updateColumns == null) || updateColumns.isEmpty()) {
      return 0;
    }

    try {
      final ModelEntity modelEntity = delegatorInterface.getModelEntity(entityName);

      final GenericHelper entityHelper = delegatorInterface.getEntityHelper(entityName);

      final ModelFieldTypeReader modelFieldTypeReader =
          ModelFieldTypeReader.getModelFieldTypeReader(entityHelper.getHelperName());

      final ArrayList<EntityConditionParam> params = new ArrayList<EntityConditionParam>();

      // generate the update sql
      final StringBuilder updateSql = new StringBuilder("UPDATE ");

      updateSql.append(modelEntity.getTableName(entityHelper.getHelperName()));
      updateSql.append(" SET ");

      if (!modelEntity.areFields(updateColumns.keySet())) {
        throw new GenericModelException(
            "At least one of the passed fields for update is not valid: "
                + updateColumns.keySet().toString());
      }

      if (!modelEntity.areFields(updateColumns.values())) {
        throw new GenericModelException(
            "At least one of the passed fields for update is not valid: "
                + updateColumns.values().toString());
      }

      for (final Iterator iterator = updateColumns.keySet().iterator(); iterator.hasNext(); ) {
        final String column = (String) iterator.next();
        updateSql.append(" ");
        final ModelField toModelField = modelEntity.getField(column);
        updateSql.append(toModelField.getColName());
        updateSql.append(" = ");
        final ModelField fromModelField = modelEntity.getField((String) updateColumns.get(column));
        updateSql.append(fromModelField.getColName());
        if (iterator.hasNext()) {
          updateSql.append(", ");
        }
      }

      if ((criteria != null) && !criteria.isEmpty()) {
        if (!modelEntity.areFields(criteria.keySet())) {
          throw new GenericModelException(
              "At least one of the passed fields is not valid: " + criteria.keySet().toString());
        }

        // generate the where clause
        final EntityFieldMap entityCondition = new EntityFieldMap(criteria, EntityOperator.AND);

        final String entityCondWhereString = entityCondition.makeWhereString(modelEntity, params);

        if (entityCondWhereString.length() > 0) {
          updateSql.append(" WHERE ");
          updateSql.append(entityCondWhereString);
        }
      }

      final SQLProcessor processor = new AutoCommitSQLProcessor(entityHelper.getHelperName());
      final String sql = updateSql.toString();

      if (log.isDebugEnabled()) {
        log.debug("Running bulk update SQL: '" + sql + '\'');
      }

      processor.prepareStatement(sql);

      for (final EntityConditionParam conditionParam : params) {
        SqlJdbcUtil.setValue(
            processor,
            conditionParam.getModelField(),
            modelEntity.getEntityName(),
            conditionParam.getFieldValue(),
            modelFieldTypeReader);
      }

      try {
        result = processor.executeUpdate();
      } finally {
        processor.close();
      }
    } catch (final GenericEntityException e) {
      throw new DataAccessException(e);
    } catch (final NoClassDefFoundError e) {
      // under JDK 1.3 unit tests - javax.sql.XADataSource cannot be found.
      // this shouldn't affect runtime - application servers should ship the jar
    }

    return result;
  }

  @Override
  public ModelReader getModelReader() {
    return delegatorInterface.getModelReader();
  }

  @Override
  public void refreshSequencer() {
    delegatorInterface.refreshSequencer();
  }

  @Override
  public boolean removeRelated(String relationName, GenericValue schemeGv) {
    try {
      return delegatorInterface.removeRelated(relationName, schemeGv) > 0;
    } catch (GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public DelegatorInterface getDelegatorInterface() {
    return delegatorInterface;
  }

  @Override
  public List<GenericValue> transform(
      final String entityName,
      final EntityCondition entityCondition,
      final List<String> orderBy,
      final String lockField,
      final Transformation transformation) {
    try {
      return delegatorInterface.transform(
          entityName, entityCondition, orderBy, lockField, transformation);
    } catch (GenericEntityException e) {
      throw new DataAccessException(e);
    }
  }

  @Override
  public GenericValue transformOne(
      final String entityName,
      final EntityCondition entityCondition,
      final String lockField,
      final Transformation transformation) {
    final List<GenericValue> transformedValues =
        transform(entityName, entityCondition, null, lockField, transformation);
    Validate.validState(
        transformedValues.size() == 1,
        "Expected one match for %s but found %d: %s",
        entityCondition,
        transformedValues.size(),
        transformedValues);
    return transformedValues.get(0);
  }

  /**
   * Class that holds all the information necessary to update a value in a SQLProcessor. Instances
   * of {@link Value} are used to hold field values.
   */
  static final class Updater {
    final ModelFieldTypeReader modelFieldTypeReader;
    final String entityName;

    Updater(
        @Nonnull final ModelFieldTypeReader modelFieldTypeReader,
        @Nonnull final String entityName) {
      this.modelFieldTypeReader = notNull("modelFieldTypeReader", modelFieldTypeReader);
      this.entityName = notNull("entityName", entityName);
    }

    public Value create(final ModelField field, final Object value) {
      return new Value(field, value);
    }

    class Value {
      final ModelField field;
      final Object value;

      Value(final ModelField field, final Object value) {
        this.field = field;
        this.value = value;
      }

      void setValue(final SQLProcessor processor) throws GenericEntityException {
        SqlJdbcUtil.setValue(processor, field, entityName, value, modelFieldTypeReader);
      }
    }
  }

  /**
   * Get the field type given a table and field name. Returns a null function if the table can't be
   * found, and a null type string if the entity can't be found.
   */
  class FieldTypeResolver implements Function<String, Function<String, String>> {
    @Nullable
    public Function<String, String> get(final String entityName) {
      final ModelEntity table = delegatorInterface.getModelEntity(entityName);
      return (table != null) ? new FieldTypeResolverFunction(table) : null;
    }
  }

  static class FieldTypeResolverFunction implements Function<String, String> {
    private final ModelEntity table;

    FieldTypeResolverFunction(ModelEntity table) {
      this.table = table;
    }

    @Nullable
    @Override
    public String get(final String fieldName) {
      final ModelField field = table.getField(fieldName);
      return (field != null) ? field.getType() : null;
    }
  }
}
 /**
  * Make the correct search is performed when the search request does not contain any "updated
  * date" critera and we have determined that they can be included in the comment search.
  *
  * @throws Exception indicates some unexpected failure.
  */
 @Test
 public void testGetRecentCommentsIssuesNoDates() throws Exception {
   final SearchRequest request = new SearchRequest();
   final List<Long> issueIds = CollectionBuilder.newBuilder(5674L).asList();
   _testGetRecentComments(issueIds, request, null, true, createIssueQuery(issueIds));
 }