PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/jira-project/jira-components/jira-core/src/main/java/com/atlassian/jira/jql/validator/ValidatorVisitor.java

https://bitbucket.org/ahmed_bilal_360factors/jira7-core
Java | 197 lines | 152 code | 26 blank | 19 comment | 18 complexity | d15a728cb38c7e64616039d72355bc19 MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.jira.jql.validator;
  2. import com.atlassian.jira.issue.search.optimizers.DeterminedProjectsExtractor;
  3. import com.atlassian.jira.jql.operand.JqlOperandResolver;
  4. import com.atlassian.jira.jql.query.QueryCreationContext;
  5. import com.atlassian.jira.jql.query.QueryCreationContextImpl;
  6. import com.atlassian.jira.user.ApplicationUser;
  7. import com.atlassian.jira.util.I18nHelper;
  8. import com.atlassian.jira.util.ListOrderedMessageSetImpl;
  9. import com.atlassian.jira.util.MessageSet;
  10. import com.atlassian.jira.util.dbc.Assertions;
  11. import com.atlassian.jira.web.bean.I18nBean;
  12. import com.atlassian.query.clause.AndClause;
  13. import com.atlassian.query.clause.ChangedClause;
  14. import com.atlassian.query.clause.Clause;
  15. import com.atlassian.query.clause.ClauseVisitor;
  16. import com.atlassian.query.clause.NotClause;
  17. import com.atlassian.query.clause.OrClause;
  18. import com.atlassian.query.clause.TerminalClause;
  19. import com.atlassian.query.clause.WasClause;
  20. import com.atlassian.query.operand.Operand;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.List;
  24. import java.util.Set;
  25. /**
  26. * Used to perform validation over a {@link com.atlassian.query.Query}. Uses
  27. * {@link com.atlassian.jira.jql.validator.ClauseValidator}'s to validate the individual clauses and
  28. * {@link com.atlassian.jira.jql.operand.OperandHandler#validate(User, com.atlassian.query.operand.Operand, com.atlassian.query.clause.TerminalClause)}
  29. * to validate the operands.
  30. *
  31. * @since v4.0
  32. */
  33. public class ValidatorVisitor implements ClauseVisitor<MessageSet> {
  34. private final ValidatorRegistry validatorRegistry;
  35. private final JqlOperandResolver operandResolver;
  36. private final OperatorUsageValidator operatorUsageValidator;
  37. private final ApplicationUser searcher;
  38. private final Long filterId;
  39. private final Clause parentClause;
  40. public ValidatorVisitor(final ValidatorRegistry validatorRegistry, final JqlOperandResolver operandResolver,
  41. final OperatorUsageValidator operatorUsageValidator, final ApplicationUser searcher, final Long filterId, final Clause parentClause) {
  42. this.validatorRegistry = validatorRegistry;
  43. this.operandResolver = operandResolver;
  44. this.operatorUsageValidator = operatorUsageValidator;
  45. this.searcher = searcher;
  46. this.filterId = filterId;
  47. this.parentClause = parentClause;
  48. }
  49. public MessageSet visit(final AndClause andClause) {
  50. return getMessagesFromSubClauses(andClause.getClauses(), andClause);
  51. }
  52. public MessageSet visit(final NotClause notClause) {
  53. return getMessagesFromSubClauses(Collections.singletonList(notClause.getSubClause()), notClause);
  54. }
  55. public MessageSet visit(final OrClause orClause) {
  56. return getMessagesFromSubClauses(orClause.getClauses(), orClause);
  57. }
  58. public MessageSet visit(final TerminalClause clause) {
  59. final Collection<ClauseValidator> validators = validatorRegistry.getClauseValidator(searcher, clause);
  60. final MessageSet messages = validateOperatorAndOperand(clause, validators);
  61. if (messages.hasAnyErrors()) {
  62. return messages;
  63. }
  64. // Now validate the clause itself
  65. validateClause(clause, validators, messages);
  66. return messages;
  67. }
  68. private MessageSet validateOperatorAndOperand(TerminalClause clause, Collection<ClauseValidator> validators) {
  69. final MessageSet messages = new ListOrderedMessageSetImpl();
  70. // JRA-18554 It does not make sense to validate the operands or operators if the clause does not exist
  71. if (!validators.isEmpty()) {
  72. // Validate the operator makes sense from a global perspective
  73. if (validateOperator(clause, messages)) {
  74. // Short-circuit if there are any errors, we are cool if there are warnings
  75. return messages;
  76. }
  77. // Validate the terminal clauses operands
  78. if (validateOperands(clause, messages)) {
  79. // Short-circuit if there are any errors, we are cool if there are warnings
  80. return messages;
  81. }
  82. }
  83. return messages;
  84. }
  85. @Override
  86. public MessageSet visit(WasClause clause) {
  87. final Collection<ClauseValidator> wasClauseValidators = validatorRegistry.getClauseValidator(searcher, clause);
  88. final MessageSet messages = validateOperatorAndOperand(clause, wasClauseValidators);
  89. if (messages.hasAnyMessages()) {
  90. return messages;
  91. }
  92. // Now validate the clause itself
  93. validateClause(clause, wasClauseValidators, messages);
  94. return messages;
  95. }
  96. @Override
  97. public MessageSet visit(ChangedClause clause) {
  98. final ChangedClauseValidator changedClauseValidator = validatorRegistry.getClauseValidator(searcher, clause);
  99. return changedClauseValidator.validate(searcher, clause);
  100. }
  101. private boolean validateOperator(final TerminalClause clause, final MessageSet messages) {
  102. messages.addMessageSet(operatorUsageValidator.validate(searcher, clause));
  103. return messages.hasAnyErrors();
  104. }
  105. private void validateClause(final TerminalClause clause, final Collection<ClauseValidator> validators, final MessageSet messages) {
  106. if (!validators.isEmpty()) {
  107. for (ClauseValidator validator : validators) {
  108. final MessageSet messageSet;
  109. if (validator instanceof SavedFilterClauseValidator) {
  110. messageSet = ((SavedFilterClauseValidator) validator).validate(searcher, clause, filterId);
  111. } else if (validator instanceof AbstractVersionValidator) {
  112. final DeterminedProjectsExtractor determinedProjectsExtractor = new DeterminedProjectsExtractor();
  113. final Set<String> determinedProjects = determinedProjectsExtractor.extractDeterminedProjectsFromClause(parentClause);
  114. final QueryCreationContext contextWithClause = new QueryCreationContextImpl(searcher, false, determinedProjects);
  115. messageSet = ((AbstractVersionValidator) validator).validate(clause, contextWithClause);
  116. } else {
  117. messageSet = validator.validate(searcher, clause);
  118. }
  119. messages.addMessageSet(messageSet);
  120. }
  121. } else {
  122. I18nHelper i18n = getI18n();
  123. //JRADEV-2649: Provide slighly more feedback about logged in/logged out state, so that clients can
  124. //display more useful error messages
  125. if (searcher != null) {
  126. messages.addErrorMessage(i18n.getText("jira.jql.validation.no.such.field", clause.getName()));
  127. } else {
  128. messages.addErrorMessage(i18n.getText("jira.jql.validation.no.such.field.anonymous", clause.getName()));
  129. }
  130. }
  131. }
  132. ///CLOVER:OFF
  133. I18nHelper getI18n() {
  134. return new I18nBean(searcher);
  135. }
  136. ///CLOVER:ON
  137. private boolean validateOperands(final TerminalClause clause, final MessageSet messages) {
  138. final Operand operand = clause.getOperand();
  139. messages.addMessageSet(operandResolver.validate(searcher, operand, clause));
  140. return messages.hasAnyErrors();
  141. }
  142. private MessageSet getMessagesFromSubClauses(List<Clause> subClauses, Clause parentClause) {
  143. final MessageSet messages = new ListOrderedMessageSetImpl();
  144. for (Clause subClause : subClauses) {
  145. final MessageSet subMessages = subClause.accept(createNewVisitor(parentClause));
  146. if (subMessages != null) {
  147. messages.addMessageSet(subMessages);
  148. }
  149. }
  150. return messages;
  151. }
  152. private ValidatorVisitor createNewVisitor(final Clause parentClause) {
  153. return new ValidatorVisitor(validatorRegistry, operandResolver, operatorUsageValidator, searcher, filterId, parentClause);
  154. }
  155. public static class ValidatorVisitorFactory {
  156. private final ValidatorRegistry validatorRegistry;
  157. private final JqlOperandResolver operandResolver;
  158. private final OperatorUsageValidator operatorUsageValidator;
  159. public ValidatorVisitorFactory(final ValidatorRegistry validatorRegistry, final JqlOperandResolver operandResolver, final OperatorUsageValidator operatorUsageValidator) {
  160. this.validatorRegistry = Assertions.notNull("validatorRegistry", validatorRegistry);
  161. this.operandResolver = Assertions.notNull("operandResolver", operandResolver);
  162. this.operatorUsageValidator = Assertions.notNull("operatorUsageValidator", operatorUsageValidator);
  163. }
  164. public ValidatorVisitor createVisitor(ApplicationUser searcher, Long filterId) {
  165. return new ValidatorVisitor(validatorRegistry, operandResolver, operatorUsageValidator, searcher, filterId, null);
  166. }
  167. public ValidatorVisitor createVisitor(ApplicationUser searcher, Long filterId, Clause parentClause) {
  168. return new ValidatorVisitor(validatorRegistry, operandResolver, operatorUsageValidator, searcher, filterId, parentClause);
  169. }
  170. }
  171. }