com.github.nomou.mybatis.builder.spi.internal.CriterionSource Maven / Gradle / Ivy
package com.github.nomou.mybatis.builder.spi.internal;
import lombok.Getter;
import java.beans.Introspector;
import java.util.*;
/**
* TODO DOC ME!.
*
* @author changhe.yang
* @since 20191101
*/
@Getter
public class CriterionSource {
private final Type type;
private final String property;
public CriterionSource(final String source) {
type = Type.fromProperty(source);
property = type.extractProperty(source);
}
/**
* The type of a method name part. Used to create query parts in various ways.
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Michael Cramer
*/
public enum Type {
BETWEEN(2, "IsBetween", "Between"),
IS_NOT_NULL(0, "IsNotNull", "NotNull"),
IS_NULL(0, "IsNull", "Null"),
LESS_THAN("IsLessThan", "LessThan"),
LESS_THAN_EQUAL("IsLessThanEqual", "LessThanEqual"),
GREATER_THAN("IsGreaterThan", "GreaterThan"),
GREATER_THAN_EQUAL("IsGreaterThanEqual", "GreaterThanEqual"),
BEFORE("IsBefore", "Before"),
AFTER("IsAfter", "After"),
NOT_LIKE("IsNotLike", "NotLike"),
LIKE("IsLike", "Like"),
STARTING_WITH("IsStartingWith", "StartingWith", "StartsWith"),
ENDING_WITH("IsEndingWith", "EndingWith", "EndsWith"),
IS_NOT_EMPTY(0, "IsNotEmpty", "NotEmpty"),
IS_EMPTY(0, "IsEmpty", "Empty"),
NOT_CONTAINING("IsNotContaining", "NotContaining", "NotContains"),
CONTAINING("IsContaining", "Containing", "Contains"),
NOT_IN("IsNotIn", "NotIn"),
IN("IsIn", "In"),
NEAR("IsNear", "Near"),
WITHIN("IsWithin", "Within"),
REGEX("MatchesRegex", "Matches", "Regex"),
EXISTS(0, "Exists"),
TRUE(0, "IsTrue", "True"),
FALSE(0, "IsFalse", "False"),
NEGATING_SIMPLE_PROPERTY("IsNot", "Not"),
SIMPLE_PROPERTY("Is", "Equals");
// Need to list them again explicitly as the order is important
// (esp. for IS_NULL, IS_NOT_NULL)
private static final List ALL = Arrays.asList(
IS_NOT_NULL, IS_NULL, BETWEEN, LESS_THAN, LESS_THAN_EQUAL,
GREATER_THAN, GREATER_THAN_EQUAL, BEFORE, AFTER, NOT_LIKE, LIKE, STARTING_WITH, ENDING_WITH, IS_NOT_EMPTY,
IS_EMPTY, NOT_CONTAINING, CONTAINING, NOT_IN, IN, NEAR, WITHIN, REGEX, EXISTS, TRUE, FALSE,
NEGATING_SIMPLE_PROPERTY, SIMPLE_PROPERTY
);
public static final Collection ALL_KEYWORDS;
static {
List allKeywords = new ArrayList();
for (Type type : ALL) {
allKeywords.addAll(type.keywords);
}
ALL_KEYWORDS = Collections.unmodifiableList(allKeywords);
}
private final List keywords;
private final int numberOfArguments;
/**
* Creates a new {@link Type} using the given keyword, number of arguments to be bound and operator. Keyword and
* operator can be {@literal null}.
*
* @param numberOfArguments
* @param keywords
*/
private Type(int numberOfArguments, String... keywords) {
this.numberOfArguments = numberOfArguments;
this.keywords = Arrays.asList(keywords);
}
private Type(String... keywords) {
this(1, keywords);
}
/**
* Returns the {@link Type} of the {@link Part} for the given raw propertyPath. This will try to detect e.g.
* keywords contained in the raw propertyPath that trigger special query creation. Returns {@link #SIMPLE_PROPERTY}
* by default.
*
* @param rawProperty
* @return
*/
public static Type fromProperty(String rawProperty) {
for (Type type : ALL) {
if (type.supports(rawProperty)) {
return type;
}
}
return SIMPLE_PROPERTY;
}
/**
* Returns all keywords supported by the current {@link Type}.
*
* @return
*/
public Collection getKeywords() {
return Collections.unmodifiableList(keywords);
}
/**
* Returns whether the the type supports the given raw property. Default implementation checks whether the property
* ends with the registered keyword. Does not support the keyword if the property is a valid field as is.
*
* @param property
* @return
*/
protected boolean supports(String property) {
for (String keyword : keywords) {
if (property.endsWith(keyword)) {
return true;
}
}
return false;
}
/**
* Returns the number of arguments the propertyPath binds. By default this exactly one argument.
*
* @return
*/
public int getNumberOfArguments() {
return numberOfArguments;
}
/**
* Callback method to extract the actual propertyPath to be bound from the given part. Strips the keyword from the
* part's end if available.
*
* @param part
* @return
*/
public String extractProperty(String part) {
final String candidate = Introspector.decapitalize(part);
for (String keyword : keywords) {
if (candidate.endsWith(keyword)) {
return candidate.substring(0, candidate.length() - keyword.length());
}
}
return candidate;
}
/*
* (non-Javadoc)
* @see java.lang.Enum#toString()
*/
@Override
public String toString() {
return String.format("%s (%s): %s", name(), getNumberOfArguments(), getKeywords());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy