
com.iofairy.pattern.Pattern Maven / Gradle / Ivy
/*
* Copyright (C) 2021 iofairy,
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.iofairy.pattern;
import com.iofairy.base.None;
import com.iofairy.lambda.R1;
import com.iofairy.pattern.mapping.*;
import com.iofairy.pattern.type.*;
import java.util.Objects;
/**
* Pattern Matching for Java
*
* @since 0.0.1
*/
public class Pattern {
public static final PatternDefault DEFAULT = PatternDefault.DEFAULT; // DEFAULT can match by value or boolean
public static final PatternValue VALUE = PatternValue.VALUE; // match by value
public static final PatternType TYPE = PatternType.TYPE; // match by value type(Class)
public static final PatternString STRING = PatternString.STRING; // match by String value
public static final PatternString IGNORECASE = PatternString.IGNORECASE; // match by String value ignore case
public static final PatternString CONTAIN = PatternString.CONTAIN; // match by String value using String.contains
public static final PatternString PREFIX = PatternString.PREFIX; // match by String value using String.startsWith
public static final PatternString SUFFIX = PatternString.SUFFIX; // match by String value using String.endsWith
public static final PatternString ICCONTAIN = PatternString.ICCONTAIN; // ignore case for contain
public static final PatternString ICPREFIX = PatternString.ICPREFIX; // ignore case for prefix
public static final PatternString ICSUFFIX = PatternString.ICSUFFIX; // ignore case for suffix
public static None NONE = None.NONE;
/*
* Value for null pattern
*/
public static final PatternNull1 VALUE1 = PatternNull1.VALUE1;
public static final PatternNull2 VALUE2 = PatternNull2.VALUE2;
public static final PatternNull3 VALUE3 = PatternNull3.VALUE3;
public static final PatternNull4 VALUE4 = PatternNull4.VALUE4;
public static final PatternNull5 VALUE5 = PatternNull5.VALUE5;
public static final PatternNull6 VALUE6 = PatternNull6.VALUE6;
public static final PatternNull7 VALUE7 = PatternNull7.VALUE7;
public static final PatternNull8 VALUE8 = PatternNull8.VALUE8;
/**
* {@code match} can instead of {@code switch} statement or {@code if} statement.
* 使用 match 来替代 switch 和 if 语句
* Examples:
* {@code
* String s = "5";
* String result = match(s)
* .when("1", v -> v + v)
* .when("2", v -> v + "a")
* .when(in("3", "4", "5", "6"), v -> v + " - abcd")
* .orElse(v -> "no match");
*
* System.out.println("match result: " + result);
* }
*
* @param value value
* @param value type
* @return MixMatcherMapping
* @since 0.0.1
*/
public static ValueMatcherMapping match(V value) {
return match(value, DEFAULT);
}
public static ValueMatcherMapping match(V value, PatternDefault patternDefault) {
Objects.requireNonNull(patternDefault);
return new ValueMatcherMapping(value);
}
public static ValueMatcherMapping match(V value, PatternValue patternValue) {
Objects.requireNonNull(patternValue);
return new ValueMatcherMapping(value);
}
/**
* There is multiple {@code if} statements, but they're not related,
* use {@code match()} without value.
* 当你有多条if语句,但是彼此并不相关时,可以使用不带value的match。
* Examples:
* {@code
* int i = 10;
* String s = "abc";
* Object o = new Object();
*
* String res = match()
* .when(i == 5, v -> "i == 5")
* .when(s.equals("abc"), v -> "abc")
* .when(o == null, v -> "object is null")
* .orElse(v -> null);
* }
*
* @return BooleanMatcherMapping
* @see #match(None)
* @since 0.0.1
*/
public static BooleanMatcherMapping match() {
return match(NONE);
}
public static BooleanMatcherMapping match(None value) {
return new BooleanMatcherMapping<>(value);
}
/**
* Use Type Matcher instead of {@code instanceof}.
* 此 {@code match()} 函数可替代 {@code instanceof} 类型检测与类型转换功能。
* Examples:
* {@code
* Object o = Tuple.of("zs", 20);
*
* Integer result = match(o, TYPE)
* .when(Integer.class, v -> v + 10)
* .when(Tuple2.class, v -> v.arity())
* .when(String.class, v -> v.contains("abc") ? 20 : 30)
* .orElse(v -> 40);
* }
* It is equivalent to the code below:
* {@code
* Integer ifResult;
* if (o instanceof Integer) {
* ifResult = (Integer) o + 10;
* } else if (o instanceof Tuple2) {
* ifResult = ((Tuple2) o).arity();
* } else if (o instanceof String) {
* ifResult = ((String) o).contains("abc") ? 20 : 30;
* } else {
* ifResult = 40;
* }
* }
*
* @param value value
* @param patternType {@link PatternType}
* @param value type
* @return TypeMatcherMapping
* @since 0.0.1
*/
public static TypeMatcherMapping match(V value, PatternType patternType) {
Objects.requireNonNull(patternType);
return new TypeMatcherMapping<>(value);
}
/**
* Pattern matching for String.
* 为字符串提供强大的模式匹配。
* Examples:
* {@code
* String str = "aBcdE123.$fGHIj";
*
* // ignore case match
* String res1 = match(str, IGNORECASE)
* .when((String) null, v -> "match null")
* .when("abcd", v -> "match abcd")
* .when("abcde123.$fGHIj", v -> "ignore case match") // match this
* .orElse(v -> "no match");
*
* // CONTAIN match
* String res2 = match(str, CONTAIN)
* .when("abcd", v -> "abcd")
* .when("E123", v -> "E123") // match this
* .orElse(v -> "no match");
*
* // ignore case for contain
* String res3 = match(str, ICCONTAIN)
* .when("abcd1", v -> "abcd1")
* .when(in(null, "aaa", ".$fghi", "123"), v -> ".$fghi") // match this
* .orElse(v -> "no match");
*
* // PREFIX
* String res4 = match(str, PREFIX)
* .when("abcd", v -> "abcd")
* .when("aBcd", v -> "aBcd") // match this
* .orElse(v -> "no match");
*
* // ignore case for suffix
* String res5 = match(str, ICSUFFIX)
* .when("fghij", v -> "fGHIj") // match this
* .when("aBcd", v -> "aBcd")
* .orElse(v -> "no match");
* }
*
* @param value value
* @param patternString {@link PatternString}
* @return StringMatcherMapping
* @since 0.0.1
*/
public static StringMatcherMapping match(String value, PatternString patternString) {
Objects.requireNonNull(patternString);
return new StringMatcherMapping(value, patternString);
}
public static ClassValueMatcherMapping> match(Class> clazz) {
return new ClassValueMatcherMapping<>(clazz);
}
/**
* The values in {@code .when(value)} are preprocessed by {@code preAction} and then {@code match}.
* 对 when 中的值进行预处理以后再进行模式匹配
* Examples:
* {@code
* String str = "123abc";
*
* R1 preAction = s -> "123" + (s == null ? null : s.toLowerCase());
* String res1 = match(str, preAction, String.class)
* .when("123", v -> "1 " + v + "-- 123")
* .when("123ABC", v -> "2 " + v + "-- 123ABC")
* .when("ABC", v -> "4 " + v + "-- ABC") // will be matched
* .orElse(v -> "orElse " + v);
* System.out.println(res1); // output: 4 123abc-- ABC
* }
*
* @param value value
* @param preAction Preprocess for value in {@code .when(value)}
* @param value type
* @return ActionValueMatcherMapping
* @since 0.0.1
*/
public static ActionValueMatcherMapping match(V value, R1 super V, V> preAction) {
Objects.requireNonNull(preAction);
return new ActionValueMatcherMapping<>(value, preAction);
}
public static ActionValueMatcherMapping match(V value, R1 super T, V> preAction, Class clazz) {
Objects.requireNonNull(preAction);
return new ActionValueMatcherMapping<>(value, preAction);
}
public static ActionNoneMatcherMapping match(R1 super T, Boolean> preAction, Class clazz) {
Objects.requireNonNull(preAction);
return new ActionNoneMatcherMapping<>(NONE, preAction);
}
/**
* 适用于判断多个值是否为null值(或其他终止条件),只要其中一个值满足终止条件,则立即 {@code return} 方法,终止后续语句运算。
* Examples:
* {@code
* public String patternCheckNull() {
* Account account = new Account("12345", "", "aaaabbbb");
* Order order = new Order("order_123456", 10.5, new User("zs", 10, account));
*
* Tuple7 values = matchNull()
* .whenV(order, v -> v.buyer, "order is null or order.buyer is null!")
* .whenW(VALUE1, v -> v.account, v -> "user " + v._1.name + "'s account is null!")
* .whenV(order, v -> v.orderId, G::isBlank, "order.orderId is blank!")
* .whenV(order, v -> v.price, v -> v < 0, "order.price < 0!")
* .whenW(VALUE2, v -> v.userName, G::isEmpty, "order.buyer.account.userName is empty!")
* .whenW(VALUE1, v -> v.age, v -> v < 0, "order.buyer.age < 0!")
* .orElse(null);
*
* User user = values._1;
* Account account1 = values._2;
* String orderId = values._3;
* Double price = values._4;
* String userName = values._5;
* Integer age = values._6;
* String msg = values._7;
*
* return msg;
* }
*
* It is equivalent to the code below:
*
* public String commonCheckNull() {
* Account account = new Account("12345", "", "aaaabbbb");
* Order order = new Order("order_123456", 10.5, new User("zs", 10, account));
*
* String msg = null;
* if (order == null || order.buyer == null) {
* return "order is null or order.buyer is null!";
* }
* User user = order.buyer;
* if (user.account == null) {
* return "user " + user.name + "'s account is null!";
* }
* if (G.isBlank(order.orderId)) {
* return "order.orderId is blank!";
* }
* if (order.price < 0) {
* return "order.price < 0!";
* }
* if (G.isEmpty(user.account.userName)) {
* return "order.buyer.account.userName is empty!";
* }
* if (user.age < 0) {
* return "order.buyer.age < 0!";
* }
*
* return null;
* }
* }
*
* @return NullMatcherMapping
*/
public static NullMatcherMapping matchNull() {
return new NullMatcherMapping<>(None.NONE);
}
/*###################################################################################
************************************************************************************
------------------------------------------------------------------------------------
********************* Referencing methods of other classes *********************
********************* 引用其他类中的方法,方便静态导入 *********************
------------------------------------------------------------------------------------
************************************************************************************
###################################################################################*/
@SafeVarargs
public static PatternIn in(T... values) {
return PatternIn.in(values);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy