package <%= entityAbsolutePackage %>.<%_ if(jpaMetamodelFiltering && reactive) { _%>domain<%_ } else { _%>service<%_ } _%>.criteria;

import java.io.Serializable;
import java.util.Objects;
import org.springdoc.<%= javaVersion === '17' ? 'core' : 'api'%>.annotations.ParameterObject;
import tech.jhipster.service.Criteria;
<%_ for (const field of fields) { if (field.fieldIsEnum === true) { _%>
import <%= packageName %>.domain.enumeration.<%= field.fieldType %>;
<%_ } } _%>
import tech.jhipster.service.filter.*;

<%_
var effectiveRelationships = reactive ? reactiveEagerRelations : relationships;
var filterVariables = [];
var extraFilters = {};
fields.filter(field => !field.transient && (!field.options || (!field.options.skipCriteria && !field.options.skipDto))).forEach((field) => {
  const fieldType = field.fieldType;
  if (field.filterableField) {
    var filterType;
    if (field.fieldIsEnum) {
      filterType = fieldType + 'Filter';
      extraFilters[fieldType] = {type: filterType, superType: 'Filter<' + fieldType + '>', fieldType: fieldType};
    } else if (field.fieldTypeDuration || field.fieldTypeTemporal || field.fieldTypeCharSequence || field.fieldTypeNumeric || field.fieldTypeBoolean) {
      filterType = fieldType + 'Filter';
    } else {
      filterType = 'Filter<' + fieldType + '>';
    }
    filterVariables.push({
      filterType : filterType,
      name: field.fieldName,
      type: fieldType,
      fieldInJavaBeanMethod: field.fieldInJavaBeanMethod
    });
  }
});
effectiveRelationships.forEach((relationship) => {
  const relationshipType = relationship.otherEntity.primaryKey.type;
  const referenceFilterType = '' + relationshipType + 'Filter';
  const bcConfig = relationship.bcConfig;
  // user has a String PK when using OAuth, so change relationships accordingly
  let oauthAwareReferenceFilterType = referenceFilterType;
  if (relationship.otherEntityUser && authenticationTypeOauth2 || relationship.pkType === 'String') {
    oauthAwareReferenceFilterType = 'StringFilter';
  }
  if (!((bcConfig && bcConfig.unidirectionSkip) || relationship.source && relationship.source.annotationOnSource && relationship.source.annotationOnSource.includes('countByPrimaryKey'))) { // add by begcode
    filterVariables.push(
      {
        filterType : oauthAwareReferenceFilterType,
        name: relationship.relationshipFieldName + relationship.otherEntity.primaryKey.nameCapitalized,
        type: relationshipType,
        fieldInJavaBeanMethod: relationship.relationshipNameCapitalized + relationship.otherEntity.primaryKey.nameCapitalized
      });
    // 加入关系的title 其实要先知道其字段类型。
    if (relationship.otherEntityField && relationship.otherEntityName && relationship.otherEntityField !== relationship.otherEntity.primaryKey.name) {
      if (relationship.otherEntityName === 'user') {
        switch (relationship.otherEntityField) {
          case 'firstName':
          case 'login':
          case 'lastName':
          case 'email':
          case 'imageUrl':
            filterVariables.push({
                filterType: 'StringFilter',
                name: relationship.relationshipFieldName + this._.upperFirst(relationship.otherEntityField),
                type: relationshipType,
                fieldInJavaBeanMethod: relationship.relationshipNameCapitalized + this._.upperFirst(relationship.otherEntityField)
            });
        }
      } else {
        const entityStorage = this.getEntityConfig(relationship.otherEntityName, true);
        const otherEntityData = entityStorage.createProxy();
        if (otherEntityData && otherEntityData.fields) {
          const otherField = otherEntityData.fields.find(field => field.fieldName === relationship.otherEntityField);
          if (otherField) {
            let otherFieldFilterType;
            switch (otherField.fieldType) {
              case 'byte[]':
                break;
              case 'Instant':
                otherFieldFilterType = 'InstantFilter';
                break;
              case 'String':
                otherFieldFilterType = 'StringFilter';
                break;
              case 'Long':
                otherFieldFilterType = 'LongFilter';
                break;
              case 'Integer':
                otherFieldFilterType = 'IntegerFilter';
                break;
              case 'Double':
                otherFieldFilterType = 'DoubleFilter';
                break;
              case 'Float':
                otherFieldFilterType = 'FloatFilter';
                break;
              case 'ZonedDateTime':
                otherFieldFilterType = 'ZonedDateTimeFilter';
                break;
              case 'LocalDate':
                otherFieldFilterType = 'LocalDateFilter';
                break;
              case 'Boolean':
                otherFieldFilterType = 'BooleanFilter';
                break;
              case 'BigDecimal':
                otherFieldFilterType = 'BigDecimalFilter';
                break;
            }
            if (otherFieldFilterType) {
              filterVariables.push({
                filterType: otherFieldFilterType,
                name: relationship.relationshipFieldName + this._.upperFirst(relationship.otherEntityField),
                type: relationshipType,
                fieldInJavaBeanMethod: relationship.relationshipNameCapitalized + this._.upperFirst(relationship.otherEntityField)
              });
            }
          }
        }
      }
    }
    if (bcConfig && bcConfig.addFilterFieldName) {
      if (relationship.otherEntityName === 'user') {
        switch (bcConfig.addFilterFieldName) {
          case 'firstName':
          case 'login':
          case 'lastName':
          case 'email':
          case 'imageUrl':
            filterVariables.push({
              filterType: 'StringFilter',
              name: relationship.relationshipFieldName + this._.upperFirst(bcConfig.addFilterFieldName),
              type: relationshipType,
              fieldInJavaBeanMethod: relationship.relationshipNameCapitalized + _.upperFirst(bcConfig.addFilterFieldName)
            });
        }
      } else {
        const entityStorageAddFilter = this.getEntityConfig(relationship.otherEntityName, true);
        const addFilterOtherEntityData = entityStorageAddFilter.createProxy();
        if (addFilterOtherEntityData && addFilterOtherEntityData.fields) {
          const addFilterOtherField = addFilterOtherEntityData.fields.find(field => field.fieldName === bcConfig.addFilterFieldName);
          if (addFilterOtherField) {
            let addFieldFilterType;
            switch (addFilterOtherField.fieldType) {
              case 'byte[]':
                break;
              case 'Instant':
                addFieldFilterType = 'InstantFilter';
                break;
              case 'String':
                addFieldFilterType = 'StringFilter';
                break;
              case 'Long':
                addFieldFilterType = 'LongFilter';
                break;
              case 'Integer':
                addFieldFilterType = 'IntegerFilter';
                break;
              case 'Double':
                addFieldFilterType = 'DoubleFilter';
                break;
              case 'Float':
                addFieldFilterType = 'FloatFilter';
                break;
              case 'ZonedDateTime':
                addFieldFilterType = 'ZonedDateTimeFilter';
                break;
              case 'LocalDate':
                addFieldFilterType = 'LocalDateFilter';
                break;
              case 'Boolean':
                addFieldFilterType = 'BooleanFilter';
                break;
            }
            if (addFieldFilterType) {
              filterVariables.push({
                filterType: addFieldFilterType,
                name: relationship.relationshipFieldName + _.upperFirst(bcConfig.addFilterFieldName),
                type: relationshipType,
                fieldInJavaBeanMethod: relationship.relationshipNameCapitalized + _.upperFirst(bcConfig.addFilterFieldName)
              });
            }
          }
        }
      }
    }
  }
});
// add by begcode end
_%>
/**
 * Criteria class for the {@link <%= entityAbsoluteClass %>} entity. This class is used
 * in {@link <%= entityAbsolutePackage %>.web.rest.<%= entityClass %>Resource} to receive all the possible filtering options from
 * the Http GET request parameters.
 * For example the following could be a valid request:
 * {@code /<%= entityApiUrl %>?id.greaterThan=5&attr1.contains=something&attr2.specified=false}
 * As Spring is unable to properly convert the types, unless specific {@link Filter} class are used, we need to use
 * fix type specific filters.
 */
@ParameterObject
@SuppressWarnings("common-java:DuplicatedBlocks")
public class <%= entityClass %>Criteria implements Serializable, Criteria {

    private String jhiCommonSearchKeywords;

    private Boolean useOr;

    private <%= entityClass %>Criteria and;

    private <%= entityClass %>Criteria or;

<%_ Object.keys(extraFilters).forEach((key) => {
  extraFilter = extraFilters[key]; _%>
    /**
     * Class for filtering <%= key %>
     */
    public static class <%= extraFilter.type %> extends <%- extraFilter.superType %> {

        public <%= extraFilter.type %>() {
        }

        public <%= extraFilter.type %>(String value) {
            <%= extraFilter.fieldType %> enumValue = <%= extraFilter.fieldType %>.getByValue(value);
            if (enumValue != null) {
                setEquals(enumValue);
            } else {
                enumValue = <%= extraFilter.fieldType %>.getByDesc(value);
                if (enumValue != null) {
                    setEquals(enumValue);
                }
            }
        }

        public <%= extraFilter.type %>(<%= extraFilter.type %> filter) {
            super(filter);
        }

        @Override
        public <%= extraFilter.type %> copy() {
            return new <%= extraFilter.type %>(this);
        }

    }
<%_ }); _%>

    private static final long serialVersionUID = 1L;
<%_ filterVariables.forEach((filterVariable) => { _%>

    private <%- filterVariable.filterType %> <%= filterVariable.name %>;
<%_ }); _%>

    private Boolean distinct;

    public <%= entityClass %>Criteria() {
    }

    public <%= entityClass %>Criteria(<%= entityClass %>Criteria other) {
<%_ filterVariables.forEach((filterVariable) => { _%>
        this.<%= filterVariable.name %> = other.<%= filterVariable.name %> == null ? null : other.<%= filterVariable.name %>.copy();
<%_ }); _%>
        this.distinct = other.distinct;
    }

    @Override
    public <%= entityClass %>Criteria copy() {
        return new <%= entityClass %>Criteria(this);
    }

    public void setAnd(<%= entityClass %>Criteria and) {
        this.and = and;
    }

    public <%= entityClass %>Criteria getAnd() {
        return and;
    }

    public <%= entityClass %>Criteria and() {
        if (and == null) {
            and = new <%= entityClass %>Criteria();
        }
        return and;
    }

    public void setOr(<%= entityClass %>Criteria or) {
        this.or = or;
    }

    public <%= entityClass %>Criteria getOr() {
        return or;
    }

    public <%= entityClass %>Criteria or() {
        if (or == null) {
            or = new <%= entityClass %>Criteria();
        }
        return or;
    }

<%_ filterVariables.forEach((filterVariable) => { _%>
    public <%- filterVariable.filterType %> get<%= filterVariable.fieldInJavaBeanMethod %>() {
        return <%= filterVariable.name %>;
    }

    public <%- filterVariable.filterType %> <%= filterVariable.name %>() {
        if (<%= filterVariable.name %> == null) {
            <%= filterVariable.name %> = new <%- filterVariable.filterType %>();
        }
        return <%= filterVariable.name %>;
    }

    public void set<%= filterVariable.fieldInJavaBeanMethod %>(<%- filterVariable.filterType %> <%= filterVariable.name %>) {
        this.<%= filterVariable.name %> = <%= filterVariable.name %>;
    }

<%_ }); _%>
    public String getJhiCommonSearchKeywords() {
        return jhiCommonSearchKeywords;
    }

    public void setJhiCommonSearchKeywords(String jhiCommonSearchKeywords) {
        this.jhiCommonSearchKeywords = jhiCommonSearchKeywords;
    }

    public Boolean getUseOr() {
        return useOr;
    }

    public void setUseOr(Boolean useOr) {
        this.useOr = useOr;
    }

    public Boolean getDistinct() {
        return distinct;
    }

    public void setDistinct(Boolean distinct) {
        this.distinct = distinct;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final <%= entityClass %>Criteria that = (<%= entityClass %>Criteria) o;
        return
<%_ filterVariables.forEach((filterVariable, index) => { _%>
            Objects.equals(<%= filterVariable.name %>, that.<%= filterVariable.name %>) &&
<%_ }); _%>
            Objects.equals(distinct, that.distinct);
    }

    @Override
    public int hashCode() {
        return Objects.hash(
<%_ filterVariables.forEach((filterVariable, index) => { _%>
        <%= filterVariable.name %>,
<%_ }); _%>
        distinct);
    }

    // prettier-ignore
    @Override
    public String toString() {
        return "<%= entityClass %>Criteria{" +
<%_ filterVariables.forEach((field) => { _%>
            (<%= field.name %> != null ? "<%= field.name %>=" + <%= field.name %> + ", " : "") +
<%_ }); _%>
            (jhiCommonSearchKeywords != null ? "jhiCommonSearchKeywords=" + jhiCommonSearchKeywords + ", " : "") +
            "useOr=" + useOr +
            (and != null ? "and=" + and + ", " : "") +
            (or != null ? "or=" + or + ", " : "") +
            (distinct != null ? "distinct=" + distinct + ", " : "") +
            "}";
    }

}
